Android -- MeasureSpec

自定义控件都会去重写View的onMeasure方法,因为该方法指定该控件在屏幕上的大小

protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec)

onMeasure传入的两个参数是由上一层控件传入的大小,有多种情况,重写该方法时需要对计算控件的实际大小,然后调用setMeasuredDimension(int, int)设置实际大小。

onMeasure传入的widthMeasureSpec和heightMeasureSpec不是一般的尺寸数值,而是将模式和尺寸组合在一起的数值。

常用的三个函数                                                                                         

int getMode(int measureSpec)//根据提供的测量值(格式)提取模式(上述三个模式之一)
int getSize(int measureSpec)//根据提供的测量值(格式)提取大小值(这个大小也就是我们通常所说的大小)
int makeMeasureSpec(int size,int mode)//根据提供的大小值和模式创建一个测量值(格式)

得到模式:

int mode = MeasureSpec.getMode(widthMeasureSpec)

得到尺寸:

int size = MeasureSpec.getSize(widthMeasureSpec)

Mode                                                                                                    

mode共有三种情况,取值分别为

MeasureSpec.UNSPECIFIED, MeasureSpec.EXACTLY, MeasureSpec.AT_MOST
  • MeasureSpec.EXACTLY是精确尺寸,当我们将控件的layout_width或layout_height指定为具体数值时如andorid:layout_width="50dip",或者为FILL_PARENT是,都是控件大小已经确定的情况,都是精确尺寸。
  • MeasureSpec.AT_MOST是最大尺寸,当控件的layout_width或layout_height指定为WRAP_CONTENT时,控件大小一般随着控件的子空间或内容进行变化,此时控件尺寸只要不超过父控件允许的最大尺寸即可。因此,此时的mode是AT_MOST,size给出了父控件允许的最大尺寸。
  • MeasureSpec.UNSPECIFIED是未指定尺寸,这种情况不多,一般都是父控件是AdapterView,通过measure方法传入的模式。

Code                                                                                                    

控件根据横竖屏、屏幕大小自适应:

复制代码
@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        if (0 == mRatioWidth || 0 == mRatioHeight) {
            setMeasuredDimension(width, height);
        } else {
            if (width < height * mRatioWidth / mRatioHeight) {
                setMeasuredDimension(width, width * mRatioHeight / mRatioWidth);
            } else {
                setMeasuredDimension(height * mRatioWidth / mRatioHeight, height);
            }
        }
    }

    public void fitWindow(int width, int height) {
        if (width < 0 || height < 0) {
            throw new IllegalArgumentException("Size cannot be negative.");
        }
        mRatioWidth = width;//屏幕宽
        mRatioHeight = height;//屏幕高
        requestLayout();//促使调用onMeasure
    }
复制代码

我是天王盖地虎的分割线                                                                             

posted @   我爱物联网  阅读(1443)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
AmazingCounters.com
点击右上角即可分享
微信分享提示