自己设置Viewgroup机制

作者 : 开心源码 本文共3332个字,预计阅读时间需要9分钟 发布时间: 2022-05-14 共178人阅读

在我们做的项目中,假如需要做某些定制性高的自己设置ViewGroup,假如有不错的Viewgroup机制功底,那做起来就会有奇效。富有创造性的viewgroup会让人看得瞠目结舌,所以从肯定程度上说,写viewgroup的水平很看出一个开发人员的技术如何。比方Android自带的RelativeLayout、LinearLayout、FrameLayout、Viewpager等都是继承自ViewGroup类。

ViewGroup层级图:

Viewgroup绘制流程:

会通过onMeasure、onLayout、onDraw顺序的流程方法进行绘制。

onMeasure

ViewGroup的测量需要遍历所有子view,对所有子view进行测量。

@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  int childCount = this.getChildCount();  for (int i = 0; i < childCount; i++) {      View child = this.getChildAt(i);      this.measureChild(child, widthMeasureSpec, heightMeasureSpec);      int cw = child.getMeasuredWidth();      int ch = child.getMeasuredHeight();  }}
onLayout

自己设置viewgroup必需要实现onLayout方法,在其中需要遍历所有子view对其调用layout方法,设置各个子view的左上右下坐标。而viewgroup的宽高则会根据所有子view所需最大的宽高来设置自己的宽高。

protected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int arg4) {  int childCount = this.getChildCount();  for (int i = 0; i < childCount; i++) {      View child = this.getChildAt(i);      LayoutParams lParams = (LayoutParams) child.getLayoutParams();      child.layout(lParams.left, lParams.top, lParams.left + childWidth,              lParams.top + childHeight);  }}
onDraw

viewgroup会按照子类的排列顺序,调用子类的onDraw方法分别进行绘制。

示例:写一个水平的LinearLayout的功能。
public class MyLinearLayout extends ViewGroup {    public MyLinearLayout(Context context) {        super(context);    }    public MyLinearLayout(Context context, AttributeSet attrs) {        super(context, attrs);    }    @Override    protected void onLayout(boolean changed, int l, int t, int r, int b) {        View childView;        int startLeft = l;  //父view当前的左边距位置,这里只每一个子view的起始左边距位置        for (int i = 0; i < getChildCount(); i++) {            childView = getChildAt(i);            int width = childView.getMeasuredWidth();  //当前子view的宽            int height = childView.getMeasuredHeight();  //当前子view的高            childView.layout(startLeft, t, startLeft + width, height);            startLeft += width;        }    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        measureChildren(widthMeasureSpec, heightMeasureSpec);  //对所有子view进行测量        int widthMode = MeasureSpec.getMode(widthMeasureSpec);        int heigthMode = MeasureSpec.getMode(heightMeasureSpec);        int widthSize = MeasureSpec.getSize(widthMeasureSpec);        int heightSize = MeasureSpec.getSize(heightMeasureSpec);        if (widthMode == MeasureSpec.AT_MOST && heigthMode == MeasureSpec.AT_MOST) {            //宽高都为wrapcontent,则设置尺寸为子view所需宽高的最大值            setMeasuredDimension(totalWidth(), totalHeight());        } else if (widthMode == MeasureSpec.AT_MOST) {            setMeasuredDimension(totalWidth(), heightSize);        } else if (heigthMode == MeasureSpec.AT_MOST) {            setMeasuredDimension(widthSize, totalHeight());        }    }    /**     * 计算子view所需最大宽度,宽度为所有子view之和     * @return     */    private int totalWidth() {        int totalWidth = 0;        for (int i = 0; i < getChildCount(); i++) {            totalWidth += getChildAt(i).getMeasuredWidth();        }        return totalWidth;    }    /**     * 计算子view所需最大高度,为子view中最大高度     * @return     */    private int totalHeight() {        int maxHeight = 0;        for (int i = 0; i < getChildCount(); i++) {            if (getChildAt(i).getMeasuredHeight() > maxHeight) {                maxHeight = getChildAt(i).getMeasuredHeight();            }        }        return maxHeight;    }}
布局代码:
    <com.example.apple.viewgroupuse.MyLinearLayout        android:layout_width="wrap_content"        android:layout_height="wrap_content">        <View            android:layout_width="80dp"            android:layout_height="80dp"            android:background="#00BC1B"/>        <View            android:layout_width="80dp"            android:layout_height="80dp"            android:background="#12B7F5"/>        <View            android:layout_width="80dp"            android:layout_height="80dp"            android:background="#FF9F00"/>        <View            android:layout_width="80dp"            android:layout_height="80dp"            android:background="#EF1200"/>    </com.example.apple.viewgroupuse.MyLinearLayout>
运行结果:

增加子view会水平线性摆放

上一篇 目录 已是最后

说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » 自己设置Viewgroup机制

发表回复