Android 自定义View总结 —— onLayout()

说明:本博客为原创,转载请注明出处 CSDN-ANDROID笔记栈
由于作者水平有限,错误在所难免,请见谅,可以留言,本人会及时改正


索引


onLayout

自定义View继承ViewGroup必须要实现这个方法,该方法实现了所有子View的具体位置

protected void onLayout(boolean changed, int left, int top, int right, int bottom){
// changed,如果View大小改变 或者位置改变为true
// left,top,right,bottom 是左上右下值,这个值是相对于它的ParentView而言的。
//View的大小是基于一个矩形来确定的,四个点可以确定一个矩形的位置及大小。
// 10,10,30,40的意思是当前View距离ParentView的左边距为10,上边距为10,当前View的宽度为20,高度为30
}
//真正的layout入口是layout方法
public void layout(int l, int t, int r, int b){
...
    onLayout();
...
}

Demo

GitHub地址: GitHub
环境: Windows7+JAVA8
IDE: AndroidStdio2.2.2
compileSdkVersion:24
测试设备:Nexus5(6.0.1)

运行结果截图
ViewGroup onLayout

自定义ViewGroup实现了如图所示的布局

//xml源码
...
//DLCustomViewGroup 宽高都是match_parent的,但是在onMeasure方法中改变了这个值
 <com.neulion.android.dl.customviewdemo.widget.DLCustomViewGroup
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#ffeb3b">

        <com.neulion.android.dl.customviewdemo.widget.DLCustomView
                android:layout_width="48dp"
                android:layout_height="48dp"
                android:background="#ff0000" />

        <com.neulion.android.dl.customviewdemo.widget.DLCustomView
                android:layout_width="48dp"
                android:layout_height="48dp"
                android:background="#00ff00" />

        <com.neulion.android.dl.customviewdemo.widget.DLCustomView
                android:layout_width="48dp"
                android:layout_height="48dp"
                android:background="#0000ff" />

        <com.neulion.android.dl.customviewdemo.widget.DLCustomView
                android:layout_width="48dp"
                android:layout_height="48dp"
                android:background="#000000" />

    </com.neulion.android.dl.customviewdemo.widget.DLCustomViewGroup>
...
// DLCustomViewGroup部分源码
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
    //ViewGroup自己测量所有子View的大小,该方法是ViewGroup自带的
    measureChildren(widthMeasureSpec, heightMeasureSpec);

    //计算所有子View的高度(类似于LinearLayout垂直布局)
    int childrenHeight = 0;

    //遍历所有子View
    for (int i = 0; i < getChildCount(); i++){
        childrenHeight += getChildAt(i).getMeasuredHeight();
    }

    //height并没有解析xml属性,这里只是做个测试
    //在这里应该基于XML布局的属性,子View的大小,ViewGroup实现的布局等来确定最后的大小!
    setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), childrenHeight);
}

最后看下onLayout方法源码

void layoutChildren(int left, int top, int right, int bottom)
{
    final int count = getChildCount();
    //child 初始left,top值
    int childLeft = left + getPaddingLeft();
    int childTop = top + getPaddingTop();
    //遍历所有子View
    for (int i = 0; i < count; i++)
    {
        final View child = getChildAt(i);
        //这里所有的子View应该是已经被测量好了的!
        int childRight = childLeft + child.getMeasuredWidth();

        int childBottom = childTop + child.getMeasuredHeight();
        //摆放View的具体位置
        child.layout(childLeft, childTop, childRight, childBottom);
        //下一个View的Left就是当前View的Right
        childLeft = childRight;

        childTop = childBottom;
        }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值