• 自定义控件——视图的构建过程——视图的测量方法


    对于wrap_content形式的宽高,App需要测量它们的实际长度,需要测量的实体主要有3种:

    (1)文本尺寸测量文本尺寸分为文本的宽度和高度,需根据文本大小分别计算。

    (2)图形尺寸测量如果图形是Bitmap格式,就调用getWidth和getHeight方法;如果图形是Drawable格式,就调用getIntrinsicWidth和getIntrinsicHeight方法。

    (3)布局尺寸测量调用measure方法按照测量规格进行测量操

    ===========================================================================================

    文本尺寸的测量

    1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    2. android:layout_width="match_parent"
    3. android:layout_height="match_parent"
    4. android:orientation="vertical"
    5. android:padding="5dp" >
    6. <RelativeLayout
    7. android:layout_width="match_parent"
    8. android:layout_height="40dp" >
    9. <TextView
    10. android:id="@+id/tv_size"
    11. android:layout_width="wrap_content"
    12. android:layout_height="match_parent"
    13. android:layout_alignParentLeft="true"
    14. android:gravity="center"
    15. android:text="字体大小:"
    16. android:textColor="@color/black"
    17. android:textSize="17sp" />
    18. <Spinner
    19. android:id="@+id/sp_size"
    20. android:layout_width="match_parent"
    21. android:layout_height="match_parent"
    22. android:layout_toRightOf="@+id/tv_size"
    23. android:gravity="left|center"
    24. android:spinnerMode="dialog" />
    25. </RelativeLayout>
    26. <TextView
    27. android:id="@+id/tv_desc"
    28. android:layout_width="match_parent"
    29. android:layout_height="wrap_content"
    30. android:gravity="left"
    31. android:textColor="@color/black"
    32. android:textSize="17sp" />
    33. <TextView
    34. android:id="@+id/tv_text"
    35. android:layout_width="match_parent"
    36. android:layout_height="wrap_content"
    37. android:padding="10dp"
    38. android:gravity="center"
    39. android:text="每逢佳节倍思亲"
    40. android:textColor="@color/black" />
    41. </LinearLayout>

    1. <TextView xmlns:android="http://schemas.android.com/apk/res/android"
    2. android:layout_width="match_parent"
    3. android:layout_height="40dp"
    4. android:singleLine="true"
    5. android:gravity="center"
    6. android:textSize="17sp"
    7. android:textColor="#0000ff" />

    代码:

    1. package com.example.myapplication;
    2. import androidx.appcompat.app.AppCompatActivity;
    3. import android.os.Bundle;
    4. import android.util.TypedValue;
    5. import android.view.View;
    6. import android.widget.AdapterView;
    7. import android.widget.ArrayAdapter;
    8. import android.widget.Spinner;
    9. import android.widget.TextView;
    10. import com.example.myapplication.util.MeasureUtil;
    11. public class MainActivity extends AppCompatActivity
    12. {
    13. private TextView tv_desc, tv_text;
    14. @Override
    15. protected void onCreate(Bundle savedInstanceState)
    16. {
    17. super.onCreate(savedInstanceState);
    18. setContentView(R.layout.activity_main);
    19. tv_desc = findViewById(R.id.tv_desc);
    20. tv_text = findViewById(R.id.tv_text);
    21. initSizeSpinner(); // 初始化文字大小的下拉框
    22. }
    23. // 初始化文字大小的下拉框
    24. private void initSizeSpinner()
    25. {
    26. ArrayAdapter<String> sizeAdapter = new ArrayAdapter<String>(this, R.layout.item_select, descArray);
    27. Spinner sp_size = findViewById(R.id.sp_size);
    28. sp_size.setPrompt("请选择文字大小");
    29. sp_size.setAdapter(sizeAdapter);
    30. sp_size.setOnItemSelectedListener(new SizeSelectedListener());
    31. sp_size.setSelection(0);
    32. }
    33. private String[] descArray = {"12sp", "15sp", "17sp", "20sp", "22sp", "25sp", "27sp", "30sp"};
    34. private int[] sizeArray = {12, 15, 17, 20, 22, 25, 27, 30};
    35. class SizeSelectedListener implements AdapterView.OnItemSelectedListener
    36. {
    37. public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3)
    38. {
    39. String text = tv_text.getText().toString();
    40. int textSize = sizeArray[arg2];
    41. tv_text.setTextSize(TypedValue.COMPLEX_UNIT_SP, textSize);
    42. // 计算获取指定文本的宽度(其实就是长度)
    43. int width = (int) MeasureUtil.getTextWidth(text, textSize);
    44. // 计算获取指定文本的高度
    45. int height = (int) MeasureUtil.getTextHeight(text, textSize);
    46. String desc = String.format("下面文字的宽度是%d,高度是%d", width, height);
    47. tv_desc.setText(desc);
    48. }
    49. public void onNothingSelected(AdapterView<?> arg0) {}
    50. }
    51. }

     

    MeasureUtil
    
    1. package com.example.myapplication.util;
    2. import android.app.Activity;
    3. import android.graphics.Paint;
    4. import android.graphics.Paint.FontMetrics;
    5. import android.text.TextUtils;
    6. import android.view.View;
    7. import android.view.View.MeasureSpec;
    8. import android.view.ViewGroup;
    9. import android.view.ViewGroup.LayoutParams;
    10. import android.widget.LinearLayout;
    11. public class MeasureUtil
    12. {
    13. // 获取指定文本的宽度(其实就是长度)
    14. public static float getTextWidth(String text, float textSize)
    15. {
    16. if (TextUtils.isEmpty(text))
    17. {
    18. return 0;
    19. }
    20. Paint paint = new Paint(); // 创建一个画笔对象
    21. paint.setTextSize(textSize); // 设置画笔的文本大小
    22. return paint.measureText(text); // 利用画笔丈量指定文本的宽度
    23. }
    24. // 获取指定文本的高度
    25. public static float getTextHeight(String text, float textSize)
    26. {
    27. Paint paint = new Paint(); // 创建一个画笔对象
    28. paint.setTextSize(textSize); // 设置画笔的文本大小
    29. FontMetrics fm = paint.getFontMetrics(); // 获取画笔默认字体的度量衡
    30. return fm.descent - fm.ascent; // 返回文本自身的高度
    31. //return fm.bottom - fm.top + fm.leading; // 返回文本所在行的行高
    32. }
    33. // 根据资源编号获得线性布局的实际高度(页面来源)
    34. public static float getRealHeight(Activity act, int resid)
    35. {
    36. LinearLayout llayout = act.findViewById(resid);
    37. return getRealHeight(llayout);
    38. }
    39. // 根据资源编号获得线性布局的实际高度(视图来源)
    40. public static float getRealHeight(View parent, int resid)
    41. {
    42. LinearLayout llayout = parent.findViewById(resid);
    43. return getRealHeight(llayout);
    44. }
    45. // 计算指定线性布局的实际高度
    46. public static float getRealHeight(View child)
    47. {
    48. LinearLayout llayout = (LinearLayout) child;
    49. // 获得线性布局的布局参数
    50. LayoutParams params = llayout.getLayoutParams();
    51. if (params == null)
    52. {
    53. params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
    54. }
    55. // 获得布局参数里面的宽度规格
    56. int wdSpec = ViewGroup.getChildMeasureSpec(0, 0, params.width);
    57. int htSpec;
    58. if (params.height > 0) { // 高度大于0,说明这是明确的dp数值
    59. // 按照精确数值的情况计算高度规格
    60. htSpec = MeasureSpec.makeMeasureSpec(params.height, MeasureSpec.EXACTLY);
    61. } else { // MATCH_PARENT=-1,WRAP_CONTENT=-2,所以二者都进入该分支
    62. // 按照不确定的情况计算高度规则
    63. htSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
    64. }
    65. llayout.measure(wdSpec, htSpec); // 重新丈量线性布局的宽高
    66. // 获得并返回线性布局丈量之后的高度。调用getMeasuredWidth方法可获得宽度
    67. return llayout.getMeasuredHeight();
    68. }
    69. }

     

    1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    2. android:layout_width="match_parent"
    3. android:layout_height="match_parent"
    4. android:orientation="vertical" >
    5. <include layout="@layout/drag_drop_header" />
    6. <TextView
    7. android:id="@+id/tv_desc"
    8. android:layout_width="match_parent"
    9. android:layout_height="wrap_content"
    10. android:padding="5dp"
    11. android:gravity="left"
    12. android:textColor="@color/black"
    13. android:textSize="17sp" />
    14. </LinearLayout>

    1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    2. android:id="@+id/ll_header"
    3. android:layout_width="match_parent"
    4. android:layout_height="wrap_content"
    5. android:background="#eeeeee"
    6. android:gravity="center_horizontal"
    7. android:orientation="vertical"
    8. android:paddingBottom="15dp"
    9. android:paddingTop="15dp" >
    10. <ImageView
    11. android:layout_width="wrap_content"
    12. android:layout_height="wrap_content"
    13. android:src="@drawable/ic_header" />
    14. <LinearLayout
    15. android:id="@+id/ll_content"
    16. android:layout_width="match_parent"
    17. android:layout_height="wrap_content"
    18. android:gravity="center"
    19. android:orientation="horizontal" >
    20. <ImageView
    21. android:id="@+id/iv_arrow"
    22. android:layout_width="wrap_content"
    23. android:layout_height="wrap_content"
    24. android:layout_gravity="center"
    25. android:src="@drawable/ic_arrow" />
    26. <LinearLayout
    27. android:layout_width="wrap_content"
    28. android:layout_height="wrap_content"
    29. android:layout_marginLeft="10dp"
    30. android:gravity="center_horizontal"
    31. android:orientation="vertical" >
    32. <TextView
    33. android:id="@+id/tv_tips"
    34. android:layout_width="wrap_content"
    35. android:layout_height="wrap_content"
    36. android:text="轻轻下拉,刷新精彩..."
    37. android:textColor="@color/black"
    38. android:textSize="17sp" />
    39. </LinearLayout>
    40. </LinearLayout>
    41. </LinearLayout>

    代码:

    1. package com.example.myapplication;
    2. import androidx.appcompat.app.AppCompatActivity;
    3. import android.os.Bundle;
    4. import android.widget.LinearLayout;
    5. import android.widget.TextView;
    6. import com.example.myapplication.util.MeasureUtil;
    7. public class MainActivity extends AppCompatActivity
    8. {
    9. @Override
    10. protected void onCreate(Bundle savedInstanceState)
    11. {
    12. super.onCreate(savedInstanceState);
    13. setContentView(R.layout.activity_main);
    14. LinearLayout ll_header = findViewById(R.id.ll_header);
    15. TextView tv_desc = findViewById(R.id.tv_desc);
    16. // 计算获取线性布局的实际高度
    17. float height = MeasureUtil.getRealHeight(ll_header);
    18. String desc = String.format("上面下拉刷新头部的高度是%f", height);
    19. tv_desc.setText(desc);
    20. }
    21. }

    MeasureUtil
    
    1. package com.example.myapplication.util;
    2. import android.app.Activity;
    3. import android.graphics.Paint;
    4. import android.graphics.Paint.FontMetrics;
    5. import android.text.TextUtils;
    6. import android.view.View;
    7. import android.view.View.MeasureSpec;
    8. import android.view.ViewGroup;
    9. import android.view.ViewGroup.LayoutParams;
    10. import android.widget.LinearLayout;
    11. public class MeasureUtil
    12. {
    13. // 获取指定文本的宽度(其实就是长度)
    14. public static float getTextWidth(String text, float textSize)
    15. {
    16. if (TextUtils.isEmpty(text))
    17. {
    18. return 0;
    19. }
    20. Paint paint = new Paint(); // 创建一个画笔对象
    21. paint.setTextSize(textSize); // 设置画笔的文本大小
    22. return paint.measureText(text); // 利用画笔丈量指定文本的宽度
    23. }
    24. // 获取指定文本的高度
    25. public static float getTextHeight(String text, float textSize)
    26. {
    27. Paint paint = new Paint(); // 创建一个画笔对象
    28. paint.setTextSize(textSize); // 设置画笔的文本大小
    29. FontMetrics fm = paint.getFontMetrics(); // 获取画笔默认字体的度量衡
    30. return fm.descent - fm.ascent; // 返回文本自身的高度
    31. //return fm.bottom - fm.top + fm.leading; // 返回文本所在行的行高
    32. }
    33. // 根据资源编号获得线性布局的实际高度(页面来源)
    34. public static float getRealHeight(Activity act, int resid)
    35. {
    36. LinearLayout llayout = act.findViewById(resid);
    37. return getRealHeight(llayout);
    38. }
    39. // 根据资源编号获得线性布局的实际高度(视图来源)
    40. public static float getRealHeight(View parent, int resid)
    41. {
    42. LinearLayout llayout = parent.findViewById(resid);
    43. return getRealHeight(llayout);
    44. }
    45. // 计算指定线性布局的实际高度
    46. public static float getRealHeight(View child)
    47. {
    48. LinearLayout llayout = (LinearLayout) child;
    49. // 获得线性布局的布局参数
    50. LayoutParams params = llayout.getLayoutParams();
    51. if (params == null)
    52. {
    53. params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
    54. }
    55. // 获得布局参数里面的宽度规格
    56. int wdSpec = ViewGroup.getChildMeasureSpec(0, 0, params.width);
    57. int htSpec;
    58. if (params.height > 0) { // 高度大于0,说明这是明确的dp数值
    59. // 按照精确数值的情况计算高度规格
    60. htSpec = MeasureSpec.makeMeasureSpec(params.height, MeasureSpec.EXACTLY);
    61. } else { // MATCH_PARENT=-1,WRAP_CONTENT=-2,所以二者都进入该分支
    62. // 按照不确定的情况计算高度规则
    63. htSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
    64. }
    65. llayout.measure(wdSpec, htSpec); // 重新丈量线性布局的宽高
    66. // 获得并返回线性布局丈量之后的高度。调用getMeasuredWidth方法可获得宽度
    67. return llayout.getMeasuredHeight();
    68. }
    69. }

     

     

     

     

     

     

  • 相关阅读:
    迁移学习 - 微调
    目录信息收集
    测试员都是背锅侠?测试人员避“锅”攻略,拿走不谢
    【Cucumber】关于BDD自然语言自动化测试的语法总结
    python毕业设计作品基于django框架新闻信息管理系统毕设成品(4)开题报告
    【网络学习笔记】
    Oracle/PLSQL: NULLIF Function
    练[BJDCTF2020]Easy MD5
    【单片机】18-红外线遥控
    asyncio 异步编程
  • 原文地址:https://blog.csdn.net/m0_61442607/article/details/126678741