美文网首页
Android自定义View onMeasure 方法

Android自定义View onMeasure 方法

作者: 清梦星河哈 | 来源:发表于2019-07-31 11:35 被阅读0次
    onMeasure 作用

    1.一般情况重写onMeasure()方法作用是为了自定义View尺寸的规则,如果你的自定义View的尺寸是根据父控件行为一致,就不需要重写onMeasure()方法
    2.如果不重写onMeasure方法,那么自定义view的尺寸默认就和父控件一样大小,当然也可以在布局文件里面写死宽高,而重写该方法可以根据自己的需求设置自定义view大小

    认识 onMeasure

    1.onMeasure (int widthMeasureSpec, int heightMeasureSpec)是view自己的方法
    2.onMeasure 方法简单的理解就是是用于测量视图的大小,主要是用来测量自己和内容的来确定宽度和高度
    3.onMeasure有两个参数 ( int widthMeasureSpec, int heightMeasureSpec),该参数表示控件可获得的空间以及关于这个空间描述的元数据.
    4.widthMeasureSpec和heightMeasureSpec这两个值通常情况下都是由父视图经过计算后传递给子视图的,说明父视图会在一定程度上决定子视图的大小。

    认识 MeasureSpec

    在测量自定义view的大小之前,我们需要认识一个类MeasureSpec,它封装了父布局传递给子布局的布局要求,每个MeasureSpec代表了一组宽度和高度的要求MeasureSpec由size和mode组成。

    specMode一共有三种类型,如下所示:
    1. EXACTLY
      表示父视图希望子视图的大小应该是由specSize的值来决定的,系统默认会按照这个规则来设置子视图的大小,简单的说(当设置width或height为match_parent时,模式为
      EXACTLY,因为子view会占据剩余容器的空间,所以它大小是确定的)
    2. AT_MOST
      表示子视图最多只能是specSize中指定的大小。(当设置为wrap_content时,模式为AT_MOST, 表示子view的大小最多是多少,这样子view会根据这个上限来设置自己的尺寸)
    3. UNSPECIFIED
      表示开发人员可以将视图按照自己的意愿设置成任意的大小,没有任何限制。这种情况比较少见,不太会用到。
        /**
         * 比onDraw先执行
         * <p>
         * 一个MeasureSpec封装了父布局传递给子布局的布局要求,每个MeasureSpec代表了一组宽度和高度的要求。
         * 一个MeasureSpec由大小和模式组成
         * 它有三种模式:UNSPECIFIED(未指定),父元素部队自元素施加任何束缚,子元素可以得到任意想要的大小;
         * EXACTLY(完全),父元素决定自元素的确切大小,子元素将被限定在给定的边界里而忽略它本身大小;
         * AT_MOST(至多),子元素至多达到指定大小的值。
         * <p>
         * 它常用的三个函数:
         * 1.static int getMode(int measureSpec):根据提供的测量值(格式)提取模式(上述三个模式之一)
         * 2.static int getSize(int measureSpec):根据提供的测量值(格式)提取大小值(这个大小也就是我们通常所说的大小)
         * 3.static int makeMeasureSpec(int size,int mode):根据提供的大小值和模式创建一个测量值(格式)
         */
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            final int minimumWidth = getSuggestedMinimumWidth();
            final int minimumHeight = getSuggestedMinimumHeight();
            int width = measureWidth(minimumWidth, widthMeasureSpec);
            int height = measureHeight(minimumHeight, heightMeasureSpec);
            setMeasuredDimension(width, height);
        }
    
        private int measureWidth(int defaultWidth, int measureSpec) {
            int specMode = MeasureSpec.getMode(measureSpec);
            int specSize = MeasureSpec.getSize(measureSpec);
            int width;
            switch (specMode) {
                case MeasureSpec.AT_MOST:
                    //指定wrap_content时的宽度,这里的500一个替换为
                    //该View宽度设置为wrap_content时,View保持完整
                    //性的最小宽度。
                    width = 500 + getPaddingLeft() + getPaddingRight();
                    break;
                case MeasureSpec.EXACTLY:
                    width = specSize;
                    break;
                case MeasureSpec.UNSPECIFIED:
                    width = Math.max(defaultWidth, specSize);
                default:
                    width = 500;
                    break;
            }
            return width;
        }
    
    
        private int measureHeight(int defaultHeight, int measureSpec) {
            int specMode = MeasureSpec.getMode(measureSpec);
            int specSize = MeasureSpec.getSize(measureSpec);
            int height;
            switch (specMode) {
                case MeasureSpec.AT_MOST:
                    //同measureWidth相同位置的含义
                    height = 800 + getPaddingTop() + getPaddingBottom();
                    break;
                case MeasureSpec.EXACTLY:
                    height = specSize;
                    break;
                case MeasureSpec.UNSPECIFIED:
                    height = Math.max(defaultHeight, specSize);
                    break;
                default:
                    height = 800;
                    break;
            }
            return height;
        }
    

    相关文章

      网友评论

          本文标题:Android自定义View onMeasure 方法

          本文链接:https://www.haomeiwen.com/subject/pqjzrctx.html