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

自定义控件——视图的构建过程——视图的测量方法_第1张图片

自定义控件——视图的构建过程——视图的测量方法_第2张图片

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

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

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

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

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

文本尺寸的测量



    

        

        
    

    

    


自定义控件——视图的构建过程——视图的测量方法_第3张图片


自定义控件——视图的构建过程——视图的测量方法_第4张图片

代码:

package com.example.myapplication;

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.TypedValue;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.TextView;
import com.example.myapplication.util.MeasureUtil;

public class MainActivity extends AppCompatActivity
{
    private TextView tv_desc, tv_text;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        tv_desc = findViewById(R.id.tv_desc);
        tv_text = findViewById(R.id.tv_text);


        initSizeSpinner(); // 初始化文字大小的下拉框
    }

    // 初始化文字大小的下拉框
    private void initSizeSpinner()
    {
        ArrayAdapter sizeAdapter = new ArrayAdapter(this, R.layout.item_select, descArray);

        Spinner sp_size = findViewById(R.id.sp_size);
        sp_size.setPrompt("请选择文字大小");
        sp_size.setAdapter(sizeAdapter);
        sp_size.setOnItemSelectedListener(new SizeSelectedListener());
        sp_size.setSelection(0);

    }

    private String[] descArray = {"12sp", "15sp", "17sp", "20sp", "22sp", "25sp", "27sp", "30sp"};

    private int[] sizeArray = {12, 15, 17, 20, 22, 25, 27, 30};

    class SizeSelectedListener implements AdapterView.OnItemSelectedListener
    {


        public void onItemSelected(AdapterView arg0, View arg1, int arg2, long arg3)
        {

            String text = tv_text.getText().toString();

            int textSize = sizeArray[arg2];

            tv_text.setTextSize(TypedValue.COMPLEX_UNIT_SP, textSize);

            // 计算获取指定文本的宽度(其实就是长度)
            int width = (int) MeasureUtil.getTextWidth(text, textSize);

            // 计算获取指定文本的高度
            int height = (int) MeasureUtil.getTextHeight(text, textSize);

            String desc = String.format("下面文字的宽度是%d,高度是%d", width, height);

            tv_desc.setText(desc);
        }

        public void onNothingSelected(AdapterView arg0) {}

    }

}

自定义控件——视图的构建过程——视图的测量方法_第5张图片

 自定义控件——视图的构建过程——视图的测量方法_第6张图片

MeasureUtil
package com.example.myapplication.util;

import android.app.Activity;
import android.graphics.Paint;
import android.graphics.Paint.FontMetrics;
import android.text.TextUtils;
import android.view.View;
import android.view.View.MeasureSpec;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.LinearLayout;

public class MeasureUtil 
{

    // 获取指定文本的宽度(其实就是长度)
    public static float getTextWidth(String text, float textSize) 
    {
        if (TextUtils.isEmpty(text)) 
        {
            return 0;
        }
        
        Paint paint = new Paint(); // 创建一个画笔对象
        paint.setTextSize(textSize); // 设置画笔的文本大小
        return paint.measureText(text); // 利用画笔丈量指定文本的宽度
    }

    // 获取指定文本的高度
    public static float getTextHeight(String text, float textSize) 
    {
        Paint paint = new Paint(); // 创建一个画笔对象
        paint.setTextSize(textSize); // 设置画笔的文本大小
        FontMetrics fm = paint.getFontMetrics(); // 获取画笔默认字体的度量衡
        return fm.descent - fm.ascent; // 返回文本自身的高度
        //return fm.bottom - fm.top + fm.leading;  // 返回文本所在行的行高
    }

    // 根据资源编号获得线性布局的实际高度(页面来源)
    public static float getRealHeight(Activity act, int resid) 
    {
        LinearLayout llayout = act.findViewById(resid);
        return getRealHeight(llayout);
    }

    // 根据资源编号获得线性布局的实际高度(视图来源)
    public static float getRealHeight(View parent, int resid)
    {
        LinearLayout llayout = parent.findViewById(resid);
        return getRealHeight(llayout);
    }

    // 计算指定线性布局的实际高度
    public static float getRealHeight(View child) 
    {
        LinearLayout llayout = (LinearLayout) child;
        
        // 获得线性布局的布局参数
        LayoutParams params = llayout.getLayoutParams();
        
        if (params == null) 
        {
            params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
        }
        
        // 获得布局参数里面的宽度规格
        int wdSpec = ViewGroup.getChildMeasureSpec(0, 0, params.width);
        
        int htSpec;
        
        if (params.height > 0) { // 高度大于0,说明这是明确的dp数值
            // 按照精确数值的情况计算高度规格
            htSpec = MeasureSpec.makeMeasureSpec(params.height, MeasureSpec.EXACTLY);
        } else { // MATCH_PARENT=-1,WRAP_CONTENT=-2,所以二者都进入该分支
            // 按照不确定的情况计算高度规则
            htSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
        }
        llayout.measure(wdSpec, htSpec); // 重新丈量线性布局的宽高
        // 获得并返回线性布局丈量之后的高度。调用getMeasuredWidth方法可获得宽度
        return llayout.getMeasuredHeight();
    }

}

自定义控件——视图的构建过程——视图的测量方法_第7张图片

 自定义控件——视图的构建过程——视图的测量方法_第8张图片



    

    


自定义控件——视图的构建过程——视图的测量方法_第9张图片



    

    

        

        

            
        
    


自定义控件——视图的构建过程——视图的测量方法_第10张图片

代码:

package com.example.myapplication;

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.example.myapplication.util.MeasureUtil;

public class MainActivity extends AppCompatActivity
{

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        LinearLayout ll_header = findViewById(R.id.ll_header);

        TextView tv_desc = findViewById(R.id.tv_desc);

        // 计算获取线性布局的实际高度
        float height = MeasureUtil.getRealHeight(ll_header);

        String desc = String.format("上面下拉刷新头部的高度是%f", height);

        tv_desc.setText(desc);
    }
}

自定义控件——视图的构建过程——视图的测量方法_第11张图片

MeasureUtil
package com.example.myapplication.util;

import android.app.Activity;
import android.graphics.Paint;
import android.graphics.Paint.FontMetrics;
import android.text.TextUtils;
import android.view.View;
import android.view.View.MeasureSpec;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.LinearLayout;

public class MeasureUtil
{

    // 获取指定文本的宽度(其实就是长度)
    public static float getTextWidth(String text, float textSize)
    {
        if (TextUtils.isEmpty(text))
        {
            return 0;
        }

        Paint paint = new Paint(); // 创建一个画笔对象
        paint.setTextSize(textSize); // 设置画笔的文本大小
        return paint.measureText(text); // 利用画笔丈量指定文本的宽度
    }

    // 获取指定文本的高度
    public static float getTextHeight(String text, float textSize)
    {
        Paint paint = new Paint(); // 创建一个画笔对象
        paint.setTextSize(textSize); // 设置画笔的文本大小
        FontMetrics fm = paint.getFontMetrics(); // 获取画笔默认字体的度量衡
        return fm.descent - fm.ascent; // 返回文本自身的高度
        //return fm.bottom - fm.top + fm.leading;  // 返回文本所在行的行高
    }

    // 根据资源编号获得线性布局的实际高度(页面来源)
    public static float getRealHeight(Activity act, int resid)
    {
        LinearLayout llayout = act.findViewById(resid);
        return getRealHeight(llayout);
    }

    // 根据资源编号获得线性布局的实际高度(视图来源)
    public static float getRealHeight(View parent, int resid)
    {
        LinearLayout llayout = parent.findViewById(resid);
        return getRealHeight(llayout);
    }

    // 计算指定线性布局的实际高度
    public static float getRealHeight(View child)
    {
        LinearLayout llayout = (LinearLayout) child;

        // 获得线性布局的布局参数
        LayoutParams params = llayout.getLayoutParams();

        if (params == null)
        {
            params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
        }

        // 获得布局参数里面的宽度规格
        int wdSpec = ViewGroup.getChildMeasureSpec(0, 0, params.width);

        int htSpec;

        if (params.height > 0) { // 高度大于0,说明这是明确的dp数值
            // 按照精确数值的情况计算高度规格
            htSpec = MeasureSpec.makeMeasureSpec(params.height, MeasureSpec.EXACTLY);
        } else { // MATCH_PARENT=-1,WRAP_CONTENT=-2,所以二者都进入该分支
            // 按照不确定的情况计算高度规则
            htSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
        }
        llayout.measure(wdSpec, htSpec); // 重新丈量线性布局的宽高
        // 获得并返回线性布局丈量之后的高度。调用getMeasuredWidth方法可获得宽度
        return llayout.getMeasuredHeight();
    }

}

 

 

 

 

 

 自定义控件——视图的构建过程——视图的测量方法_第12张图片

你可能感兴趣的:(android,android,studio,ide)