Android Studio新手开发第二十六天

目录

视图构建过程(二)

视图的测量方法

1.文本尺寸测量

2.图形尺寸测量

3.布局尺寸测量

视图构建过程(二)

之前介绍过视图的四个构造方法以及用法,这是自定义控件的第一步,接下来要介绍视图的测量方法。

视图的测量方法

自定义控件的第二步是测量尺寸,需要重写onMeasure方法。控件的宽高在xml文件中分别由layout_width属性和layout_height属性规定。它们有3种赋值方式,match_parent、wrap_content与具体的数值。第一种与第三种的值获取比较简单,要么取上级视图的数值,要么取具体数值。比较难的是第二种,它需要知道视图自身的尺寸。Android提供了相关的测量方法,支持在不同情况下测量尺寸。需要测量的实体主要有三种,分别为文本尺寸。图形尺寸以及布局尺寸。

1.文本尺寸测量

文本尺寸分为文本的宽度和高度,需要根据文本的大小分别计算。文本宽度可以使用Paint类的measureText方法测量,示例代码如下。

java 复制代码
        Paint paint = new Paint();
        paint.setTextSize(20);//设置文本的大小,参数单位为sp
        paint.measureText("MeasureText");//设置测量文本,返回值单位为px

文本高度的计算较为复杂,计算高度用到FontMetrics类,该类提供了五个与高度相关的属性,如下表所示。

|---------|-------------|
| 距离属性 | 说明 |
| top | 行的顶部与基线的距离 |
| ascent | 字符的顶部与基线的距离 |
| descent | 字符的底部与基线的距离 |
| bottom | 行的底部与基线的距离 |
| leading | 行间距 |

示例代码如下。

XML 复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".CustomWidget.MeasureTextActivity"
    android:orientation="vertical">

    <TextView
        android:id="@+id/textView_1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/app_name"
        android:textSize="20sp"/>
    <TextView
        android:id="@+id/textView_2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>

部分Java代码如下。

java 复制代码
public class MeasureTextActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_measure_text);
        TextView textView_1, textView_2;
        textView_1 = findViewById(R.id.textView_1);
        textView_2 = findViewById(R.id.textView_2);
        float width = getWidth(textView_1.getText().toString(), textView_1.getTextSize());
        float height = getHeight(textView_1.getText().toString(), textView_1.getTextSize());
        String string = String.format("上面文本的大小为%.0fpx,宽度为%.0fpx,高度为%.0fpx", textView_1.getTextSize(), width, height);
        textView_2.setText(string);
    }

    public float getWidth(String text, float textSize) {
        if (TextUtils.isEmpty(text)) {
            return 0;
        }
        Paint paint = new Paint();
        paint.setTextSize(textSize);
        return paint.measureText(text);
    }

    public float getHeight(String text, float textSize) {
        if (TextUtils.isEmpty(text)) {
            return 0;
        }
        Paint paint = new Paint();
        paint.setTextSize(textSize);
        paint.measureText(text);
        Paint.FontMetrics fontMetrics = paint.getFontMetrics();
        return fontMetrics.descent - fontMetrics.ascent;//返回值单位为px
    }
}

效果图如下。

2.图形尺寸测量

图形尺寸测量较为简单,因为Android提供了现成的方法获取宽高。如果图形格式为Bitmap则调用getWidth方法或者getHeight方法获取宽高。若是Drawable格式就通过方法getIntrinsicWidth以及方法getIntrinsicHeight获取宽高。

3.布局尺寸测量

布局尺寸测量不同于上述两种尺寸,布局中可能有其他视图或者布局存在,而且还有padding与margin。逐个测量布局的内部控件是不现实的。View类提供了一种测量整体布局的思路,对应layout_width与layout_height的三种赋值方式,Android的视图基类同样提供了三种测量方式,具体说明如下表所示。

|-------------|--------------|------|
| 测量模式 | 宽高赋值方式 | 说明 |
| AT_MOST | MATCH_PARENT | 达到最大 |
| UNSPECIFIED | WRAP_CONTENT | 自适应 |
| EXACTLY | 具体dp值 | 精确尺寸 |

围绕这三种方式衍生了相关的度量方法,如ViewGroup类的getChildMeasureSpec方法,用于获取下级视图的测量规格、MeasureSpec类的makeMeasureSpec方法,根据指定参数指定测量规格、View类的measure方法,按照测量规格进行测量操作等。下面以线性布局为例,示例代码如下。

java 复制代码
    public float getLayoutHeight(View view){
        LinearLayout llayout = (LinearLayout) view;
        // 获得线性布局的布局参数
        ViewGroup.LayoutParams params = llayout.getLayoutParams();
        if (params == null) {
            params = new ViewGroup.LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        }
        // 获得布局参数里面的宽度规格
        int wdSpec = ViewGroup.getChildMeasureSpec(0, 0, params.width);
        int htSpec;
        if (params.height > 0) { // 高度大于0,说明这是明确的dp数值
            // 按照精确数值的情况计算高度规格
            htSpec = View.MeasureSpec.makeMeasureSpec(params.height, View.MeasureSpec.EXACTLY);
        } else { // MATCH_PARENT=-1,WRAP_CONTENT=-2,所以二者都进入该分支
            // 按照不确定的情况计算高度规则
            htSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
        }
        llayout.measure(wdSpec, htSpec); // 重新丈量线性布局的宽高
        // 获得并返回线性布局丈量之后的高度。调用getMeasuredWidth方法可获得宽度
        return llayout.getMeasuredHeight();
    }
相关推荐
子兮曰3 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰3 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万3 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝3 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
千里马学框架3 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台3 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
三十而立洋3 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
AFinalStone3 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
卡布鲁3 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
致远ccc3 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试