Android自定义ViewAndroid知识Android开发

Android自定义控件之从0到1轻松实现侧滑按钮

2017-06-07  本文已影响241人  Angels_安杰

一、前言


二、构想图

EasySwipeMenuLayout构想图.jpg

三、具体实现

布局文件配置效果


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        
        //1、获取childView的个数
      int count = getChildCount();
        //参考frameLayout测量代码
        //2、判断我们的EasySwipeMenuLayout的宽高是明确的具体数值还是匹配或者包裹父布局,为什么要处理呢,还不大清楚的可以看Android之自定义View的死亡三部曲之(Measure) 这篇文章
      final boolean measureMatchParentChildren =
                MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.EXACTLY ||
                        MeasureSpec.getMode(heightMeasureSpec) != MeasureSpec.EXACTLY;
        mMatchParentChildren.clear();
        int maxHeight = 0;
        int maxWidth = 0;
        int childState = 0;
        //3、开始遍历childViews进行测量
      for (int i = 0; i < count; i++) {
            View child = getChildAt(i);

            //4、如果view是GONE,那么我们就不需要测量它了,因为它是隐藏的嘛
            if (child.getVisibility() != GONE) {
              
              //5、测量子childView
                measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);
                MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
                //6、获取childView中宽的最大值
                maxWidth = Math.max(maxWidth,
                        child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin);
                //7、获取childView中高的最大值
                maxHeight = Math.max(maxHeight,
                        child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin);
                childState = combineMeasuredStates(childState, child.getMeasuredState());
                
                //8、如果child中有MATCH_PARENT的,需要再次测量,这里先添加到mMatchParentChildren集合中
                if (measureMatchParentChildren) {
                    if (lp.width == LayoutParams.MATCH_PARENT ||
                            lp.height == LayoutParams.MATCH_PARENT) {
                        mMatchParentChildren.add(child);
                    }
                }
            }
        }
        // Check against our minimum height and width
        //9、我们的EasySwipeMenuLayout的宽度和高度还要考虑背景的大小哦
      maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight());
        maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth());
        
        //10、设置我们的EasySwipeMenuLayout的具体宽高
        setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState),
                resolveSizeAndState(maxHeight, heightMeasureSpec,
                        childState << MEASURED_HEIGHT_STATE_SHIFT));
        
        //11、EasySwipeMenuLayout的宽高已经知道了,前面MATCH_PARENT的child的值当然我们也能知道了 ,所以这次再次测量它
        count = mMatchParentChildren.size();
        if (count > 1) {
            for (int i = 0; i < count; i++) {
                final View child = mMatchParentChildren.get(i);
                final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();

                //12、以下是重新设置child测量所需的MeasureSpec对象
                final int childWidthMeasureSpec;
                if (lp.width == LayoutParams.MATCH_PARENT) {
                    final int width = Math.max(0, getMeasuredWidth()
                            - lp.leftMargin - lp.rightMargin);
                    childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(
                            width, MeasureSpec.EXACTLY);
                } else {
                    childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec,
                            lp.leftMargin + lp.rightMargin,
                            lp.width);
                }

                final int childHeightMeasureSpec;
                if (lp.height == FrameLayout.LayoutParams.MATCH_PARENT) {
                    final int height = Math.max(0, getMeasuredHeight()
                            - lp.topMargin - lp.bottomMargin);
                    childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(
                            height, MeasureSpec.EXACTLY);
                } else {
                    childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec,
                            lp.topMargin + lp.bottomMargin,
                            lp.height);
                }
              
                //13、重新测量child
                child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
            }
        }

    }

总结

上一篇 下一篇

猜你喜欢

热点阅读