神刀安全网

自定义ViewGroup,你真正懂了吗?

背景

自定义View简单,因为它只需管好自己即可,而自定义ViewGroup不仅仅要管好自己,还要管好子View。接触过ViewGroup的童鞋应该都清楚,ViewGroup是作为一个View的容器,它装着子View并将子View放到指定位置上去。

目的

让大家举一反三地去自定义定制化的GroupView

思路

自定义GroupView思路

  • 首先需要知道子View大小,然后才能确定自定义的GroupView如何设置才能容纳它们。
  • 根据子View的大小和ViewGroup需要实现的效果,确定最终ViewGroup的大小。
  • ViewGroup和子View的大小确定后,接着就是如何去摆放子View,你可以按照自己特定的规则去摆放。
  • 然后将子View对号入座放入已知的分割单元。

实践

接下来我做一个示例将子View按从左到右顺序一个挨着一个摆放,即模仿实现LinearLayout的横向布局。

首先重写onMeasure,测量子View大小以及设定ViewGroup最终大小,代码如下:

 @Override     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {         super.onMeasure(widthMeasureSpec, heightMeasureSpec);         // 对所有子view进行测量,触发所有子view的onMeasure函数         measureChildren(widthMeasureSpec, heightMeasureSpec);          // 宽度模式         int widthMode = MeasureSpec.getMode(widthMeasureSpec);         // 测量宽度         int widthSize = MeasureSpec.getSize(widthMeasureSpec);         // 高度模式         int heightMode = MeasureSpec.getMode(heightMeasureSpec);         // 测量高度         int heightSize = MeasureSpec.getSize(heightMeasureSpec);         // 子view数目         int childCount = getChildCount();         if (childCount == 0){             // 如果当前ViewGroup没有子View,就没有存在的意义,无需占空间             setMeasuredDimension(0, 0);         }else {             // 如果宽高都是包裹内容             if (widthMode == MeasureSpec.AT_MOST && heightMode == MeasureSpec.AT_MOST){                 // 宽度为所有子view宽度相加,高度取子view最大高度                 int width = getTotalWidth();                 int height = getMaxHeight();                 setMeasuredDimension(width, height);             }else if (widthMode == MeasureSpec.AT_MOST){                 // 宽度为所有子View宽度相加,高度为测量高度                 setMeasuredDimension(getTotalWidth(), heightSize);             }else if (heightMode == MeasureSpec.AT_MOST){                 // 宽度为测量宽度,高度为子view最大高度                 setMeasuredDimension(widthSize, getMaxHeight());             }         }     }        /**      * 获取子view最大高度      * @author leibing      * @createTime 2016/09/19      * @lastModify 2016/09/19      * @param      * @return      */     private int getMaxHeight() {         // 最大高度         int maxHeight = 0;         // 子view数目         int childCount = getChildCount();         // 遍历子view拿取最大高度         for (int i=0;i<childCount;i++){             View childView = getChildAt(i);             if (childView.getMeasuredHeight() > maxHeight)                 maxHeight = childView.getMeasuredHeight();         }          return maxHeight;     }      /**      * 所有子view宽度相加      * @author leibing      * @createTime 2016/09/19      * @lastModify 2016/09/19      * @param      * @return      */     private int getTotalWidth() {         // 所有子view宽度之和         int totalWidth = 0;         // 子View数目         int childCount  = getChildCount();         // 遍历所有子view拿取所有子view宽度之和         for (int i=0;i<childCount;i++){             View childView = getChildAt(i);             totalWidth += childView.getMeasuredWidth();         }         return totalWidth;     }

接下来将子View摆放到合适的位置上去,代码如下:

    @Override     protected void onLayout(boolean changed, int l, int t, int r, int b) {         // 子view数目         int childCount = getChildCount();         // 记录当前宽度位置         int currentWidth = l;         // 逐个摆放子view         for (int i = 0;i<childCount;i++){             View childView = getChildAt(i);             int height = childView.getMeasuredHeight();             int width = childView.getMeasuredWidth();             // 摆放子view,参数分别是子view矩形区域的左、上,右,下。             childView.layout(currentWidth, t, currentWidth + width, t + height);             currentWidth += width;         }     }

运行效果图如下所示:

自定义ViewGroup,你真正懂了吗?
CustomViewGroup.gif

童鞋们,看完后,自定义ViewGroup是不是很简单了?

demo地址:[CustomView Demo]

作者

转载本站任何文章请注明:转载至神刀安全网,谢谢神刀安全网 » 自定义ViewGroup,你真正懂了吗?

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址