慢慢成长路——自定义ViewGroup(1)

在这之前我首先看了网上多个版本的继承ViewGroup的方式,详细版如下:

http://blog.csdn.net/xmxkf/article/details/51500304

快捷版:

http://blog.csdn.net/huachao1001/article/details/51577291

 

好了,先来说说自定义ViewGroup遇到的一些问题,总的来说,继承ViewGroup和继承View差别并不是很大,只是继承ViewGroup必须重写OnLayout方法,然后OnMeasure方法测量宽和高要考虑的东西也不一样!

好啦!咱们先来说说OnLayout方法吧,这个方法中有五个参数,是用于子View摆放的位置的,l,t,r,b就相当于是子View矩形区域的上下左右,在这里还得说一下另一个方法叫做getChildCount();这个函数返回的是当前layout内的所有子控件的数量(ps:子控件内的子控件是不算的)

先上代码,再继续说:

 

public class MyLayout extends ViewGroup {
    public MyLayout(Context context) {
        super(context);
    }

    public MyLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int count = getChildCount();
        //记录当前的高度位置
        int curHeight = t;
        //将子View逐个摆放
        for (int i = 0; i < count; i++) {
            View child = getChildAt(i);
            int height = child.getMeasuredHeight();
            int width = child.getMeasuredWidth();
            //摆放子View,参数分别是子View矩形区域的左、上、右、下边
            child.layout(l, curHeight, l + width, curHeight + height);
            curHeight += height;
        }
    }
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        measureChildren(widthMeasureSpec,heightMeasureSpec);
        int widthMode=MeasureSpec.getMode(widthMeasureSpec);
        int heightMode=MeasureSpec.getMode(heightMeasureSpec);
        int width=MeasureSpec.getSize(widthMeasureSpec);
        int height=MeasureSpec.getSize(heightMeasureSpec);
        //返回所有子控件的数量,但不会返回子控件内子控件的数量
        int childcount=getChildCount();
        if (childcount==0){
            setMeasuredDimension(0,0);
        }else {
            if (widthMode==MeasureSpec.AT_MOST&&heightMode==MeasureSpec.AT_MOST){
                for (int i=0;i<childcount;i++){
                    View view=getChildAt(i);
                   // getMeasuredHeight()表示View的实际大小,getHeight()表示View在屏幕上显示的大小
                    height+=view.getMeasuredHeight();
                    width=view.getMeasuredWidth();
                    setMeasuredDimension(width,height);
                }
            }else if (widthMode==MeasureSpec.AT_MOST){
width=getMeasuredWidth();
setMeasuredDimension(width,height);
            }else if (heightMode==MeasureSpec.AT_MOST){
                height=getMeasuredHeight();
                setMeasuredDimension(width,height);
            }
        }
    }
}

 

 

 

这是仿造快捷版链接里面那个自定义的LinearLayout,功能是一样的,但是只可以垂直排列,先说一下OnMeasure方法

这个方法再ViewGroup中有三个内置方法:

measureChildren\measureChild\measureChildWithMargins

第一个measureChildren,用于测量当前所有子View的宽和高的总和;

第二个measureChild,用来测量当前某一个子View的宽和高

第三个同理,只是加上了Margin值;

现在砸门来分析一下代码:

首先继承ViewGroup,重写三个构造函数,还有Onlayout和OnMeasure方法,然后再OnMeasure中,我们使用onMesureChildren取得所有子View的宽和高,然后初始化长宽的模式和长宽大小,先判断再我们的lauout中有没有子View,如果没有的话我们将长和宽设置为0,如果有的话判断属性中用户传给我们的到底是Warp还是Match,如果长和宽都为match,那么高和宽就都等于整个屏幕的高宽度,如果包含了warp或者都为warp,则宽等于最宽的子View的宽度,高等于所有子View加起来的高度,完成了这些之后,再onlayout中我们设置子View的排列方式

首先我们记录当前的子View的高度,然后当我们新添View的时候,我们将下一个View的左坐标设置为默认的l(0),将上坐标设置为前一个View的高度,那么这个新的子View自然就在其下方,右方坐标当然就可以直接使用getmeasurewidth来获取用户自己设置的宽度,下方坐标就应该是前一个子View加上现在这个子View的共同高度,然后在循环中,我们每一次添加一个View就将获取到的第一个View的高度加上新的View的高度

 

 

以上内容纯属个人学习总结,如有错误欢迎指出

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值