美文网首页
自定义viewGroup

自定义viewGroup

作者: 瞬息之李 | 来源:发表于2017-04-19 23:43 被阅读0次

    padding和margin

    padding用于控制view内容边界与view边界的距离对

    1. viewGroup用padding时,其作用于其子控件,控制子控件与该viewGroup的边距
    2. view用padding时,控制view的内容与view边界的距离
      margin用于控制本控件子控件与父控件的边距
    3. viewGroup用margin时,其控制本viewGroup与其他view的边距
    4. view用margin时,其控制本view与其他view的边距

    小结

    从上面的现象可以得出:viewGroup设置padding作用于其子view时,相当于子view设置了margin

    自定义viewGroup(包含margin,padding)

    public class SwipeItemLayout extends ViewGroup {
    
        public SwipeItemLayout(Context context) {
            super(context);
        }
    
    
        public SwipeItemLayout(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            /**
             *
             * 测量子view的大小,也可以用measureChild,需要遍历子view
             * measureChildren内部也是调用了measureChild方法
             * measureChildWithMargins也是同理
             */
    //        measureChildWithMargins();
           // measureChild(child,widthMeasureSpec,heightMeasureSpec);
            measureChildren(widthMeasureSpec,heightMeasureSpec);
    
            /**
             * 得到父view的size和mode
             */
            int widthMode = MeasureSpec.getMode(widthMeasureSpec);
            int widthSize = MeasureSpec.getSize(widthMeasureSpec);
            int heightMode = MeasureSpec.getMode(heightMeasureSpec);
            int heightSize = MeasureSpec.getSize(heightMeasureSpec);
    
            /**
             * 在测量大小时,需要计算padding值,而margin值的计算是放在具体的测量中,getTotalWidth,getMaxHeight
             */
            int horPadding = getPaddingLeft() + getPaddingRight();
            int virPadding = getPaddingBottom() + getPaddingTop();
    
            setMeasuredDimension(widthMode == MeasureSpec.AT_MOST ? getTotalWidth()+horPadding: widthSize+horPadding,
                    heightMode == MeasureSpec.AT_MOST ? getMaxHeight()+virPadding : heightSize+virPadding);
        }
    
        /**
         * 在计算总的宽度时,需要将子view的margin值计算进去
         * @return
         */
        private int getTotalWidth(){
            int totalWidth =0;
            for (int i = 0; i < getChildCount(); i++) {
                View view = getChildAt(i);
                MarginLayoutParams params = (MarginLayoutParams) view.getLayoutParams();
                int leftMargin = params.leftMargin;
                int rightMargin = params.rightMargin;
                int measuredWidth = view.getMeasuredWidth();
                totalWidth +=(measuredWidth + leftMargin + rightMargin);
            }
            return totalWidth;
        }
    
    
        /**
         * 计算高度时,也要将子view的margin值计算进去
         * @return
         */
        private int getMaxHeight(){
            int maxHeight =0;
            for (int i = 0; i < getChildCount(); i++) {
                View child = getChildAt(i);
                MarginLayoutParams params = (MarginLayoutParams) child.getLayoutParams();
                int topMargin = params.topMargin;
                int bottomMargin = params.bottomMargin;
                int actHeight = topMargin + bottomMargin +child.getMeasuredWidth();
                if (actHeight > maxHeight){
                    maxHeight = actHeight;
                }
            }
            return maxHeight;
        }
    
    
        /**
         *在摆放view的过程中,主要计算view防止的l,t,r,b
         * margin和padding值其实都是空的,不属于view
         * 
         */
        @Override
        protected void onLayout(boolean changed, int l, int t, int r, int b) {
            int left = getPaddingLeft();    //父view的padding值,空隙
            int right =0;
            int top = getPaddingTop();
            int bottom = getPaddingBottom();
            for (int i = 0; i < getChildCount(); i++) {
                View child = getChildAt(i);
                int height = child.getMeasuredHeight();
                int width = child.getMeasuredWidth();
                MarginLayoutParams params = (MarginLayoutParams) child.getLayoutParams();
                //子view的margin值
                int leftMargin = params.leftMargin;
                int rightMargin = params.rightMargin;
                int topMargin = params.topMargin;
                int bottomMargin = params.bottomMargin;
                //摆放的时候要将padding和margin加在一起的空隙都算出来,将view放在实际的位置即可
                child.layout(left+leftMargin,top+topMargin,left+leftMargin+width,top+topMargin+height);
                left +=(leftMargin+width+rightMargin);
            }
        }
    
       
    
        @Override
        protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
            return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
        }
    
        @Override
        protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
            return new LayoutParams(p);
        }
    
        @Override
        public LayoutParams generateLayoutParams(AttributeSet attrs) {
            return new LayoutParams(getContext(),attrs);
        }
    
        public static class LayoutParams extends MarginLayoutParams{
    
            public LayoutParams(int width, int height) {
                super(width, height);
            }
            public LayoutParams(Context c, AttributeSet attrs) {
                super(c, attrs);
            }
    
            public LayoutParams(ViewGroup.LayoutParams p) {
                super(p);
            }
        }
    }
    

    总结

    1. measure: view(这里指的是view类)自身已经实现了measure方法,并且也有默认的onMeasure方法,所以我们在自定义view(这里不包括自定义viewgroup)的时候,可以重写onMeasure方法。
      而viewGroup类是抽象类,其并没有实现view类的measure方法,因此自定义viewGroup是直接使用view类的measure,其中的onMeasure方法需要我们自己去重写,因为默认的onMeasure方法只是测量了自身的宽高并没有去测量子view

    2. layout: 首先要明白layout方法能够实现将自身放置在正确的位置(已经实现),而onlayout方法是将每个子view放置在正确的位置,在view类自身已经实现了layout方法,只要传入对应的参数就可以将自身放在对应的位置上,而在抽象类viewGroup中,将onLayout设置为抽象方法,所以在实现自定义viewGroup的时候就必须要实现对应的onlayout方法,将每个子view放置在对应的位置上(其实就是将子view的layout方法中传入对应的参数去实现)

    相关文章

      网友评论

          本文标题:自定义viewGroup

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