Android自定义View(优化)

话不多说,上图:

onMeasure()伪代码如下:

 //测量
    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        for (i in 0 until childCount) {
            val childView = getChildAt(i)
            //1.0 获取子view的layoutParams
            val layoutParams = childView.layoutParams
            //1.1 layoutParams->MeasureSpec
            val childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec, 0, layoutParams.width)
            val childHeightMeasureSpec = getChildMeasureSpec(widthMeasureSpec, 0, layoutParams.height)
            //2 获取子view的宽高
            childView.measure(childWidthMeasureSpec,childHeightMeasureSpec)
            val measuredWidth = childView.measuredWidth
            val measuredHeight = childView.measuredHeight

            /**
             * 中间经过计算view group需要的宽高
             * 父布局给的宽度selfWidth  ,测量中子view要求view group的宽度parentNeededWidth
             * 父布局给的高度selfHeight  测量中子view要求view group的高度parentNeededHeight
             */
            //3 计算(度量)view group的宽高
            val widthMode = MeasureSpec.getMode(widthMeasureSpec)
            val heightMode = MeasureSpec.getMode(heightMeasureSpec)
            val realWidth = widthMode == MeasureSpec.EXACTLY ? selfWidth : parentNeededWidth
            val realHeight = heightMode == MeasureSpec.EXACTLY ? selfHeight : parentNeededHeight
            // 这个传递的是具体的size,不是MeasureSpec
            setMeasuredDimension(realWidth, realHeight);
        }
    }

onLayout()伪代码如下:

@Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        // 总共的行数
        int lineCount = allLines.size();
        int curL = getPaddingLeft();
        int curT = getPaddingTop();
        for (int i = 0; i < lineCount; i++) {//
            List<View> lineViews = allLines.get(i);
            int lineHeight = lineHeights.get(i);
            for (int j = 0; j < lineViews.size(); j++) {// 每行的view进行布局
                View view = lineViews.get(j);
                // 根据子view的测量宽高,计算left、top、right、bottom
                int left = curL;
                int top = curT;
                int right = left + view.getMeasuredWidth();
                int bottom = top + view.getMeasuredHeight();
                view.layout(left, top, right, bottom);
                // 是你调用完这个View的layout之后才会有的值,而getMeasuredWidth 是你调用完measure之后就可以获取
                curL = right + mHorizontalSpacing;
            }
            curL = getPaddingLeft();
            curT = curT + lineHeight + mVerticalSpacing;
        }

    }

LayoutParams是什么?与MeasureSpec有关系吗?

        LayoutParams:直接从表面看就知道,是布局的参数。ViewGroup里面的一个静态类

public static class LayoutParams {
        /**
         * Special value for the height or width requested by a View.
         * FILL_PARENT means that the view wants to be as big as its parent,
         * minus the parent's padding, if any. This value is deprecated
         * starting in API Level 8 and replaced by {@link #MATCH_PARENT}.
         */
        @SuppressWarnings({"UnusedDeclaration"})
        @Deprecated
        public static final int FILL_PARENT = -1;

        /**
         * Special value for the height or width requested by a View.
         * MATCH_PARENT means that the view wants to be as big as its parent,
         * minus the parent's padding, if any. Introduced in API Level 8.
         */
        public static final int MATCH_PARENT = -1;

        /**
         * Special value for the height or width requested by a View.
         * WRAP_CONTENT means that the view wants to be just large enough to fit
         * its own internal content, taking its own padding into account.
         */
        public static final int WRAP_CONTENT = -2;

        public int width;
.
.
.
.
}

那么和MeasureSpec有什么关系呢?

子view通过getChildMeasureSpec()方法传入layoutparams获取对应的MeasureSpec,由于子view的测量。

MeasureSpec是什么呢?

        MeasureSpec是View中的内部类,用于保存宽高的信息(int 累心,32位,高2位标识Mode:UNSPECIFIED、EXACTLY、AT_MOST,低30位标识size)

UNSPECIFIED:不对View大小做限制

EXACTLY:确切的大小:如 100dp

AT_MOST:大小不可超过某个数值,如:match_parent,做大不能超过parent        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值