自定义ViewGroup这个是在android中自定义控件中不可获缺的很重要的一部分,关于它的意义这里就不过多阐述了,为了在未来深入上继续走下去,所以先把基础给打牢。

这篇主要是理解ViewGroup中如何去通过onLayout方法去布局添加的子控件,那另外一个自定义ViewGroup的也很重要的方法onMesure方法呢?下篇再来学习,一步步来,首先先新建一个ViewGroup,搭建基础框架:

自定义ViewGroup基础巩固1---理解onLayout()方法_自定义view

其中需要实现ViewGroup的抽象方法onLayout():

自定义ViewGroup基础巩固1---理解onLayout()方法_自定义view_02

然后在MainActivity中布局文件中进行声明:

自定义ViewGroup基础巩固1---理解onLayout()方法_控件_03

在ViewGroup添加一个子控件初识onLayout():

目前ViewGroup中木有一个子控件,所以运行肯定一片空白,所以呢,先在init中去添加一个子控件:

自定义ViewGroup基础巩固1---理解onLayout()方法_android ui_04

这里先来个套路,虽然大家都懂的,运行看下:

自定义ViewGroup基础巩固1---理解onLayout()方法_控件_05

不多解释,懂android的都知道原因,因为自定义ViewGroup的子控制的显示是需要自己做下处理才能够显示的,而这个方法就是onLayout(),先来看一下它的参数意义:

自定义ViewGroup基础巩固1---理解onLayout()方法_自定义view_06

先不用过多去揣测这四个参数的真实意义,先粗暴的去让这四个参数传给我们添加的控件:

/**
* 自定义ViewGroup基础巩固
* 先将添加的一个子视图显示出来
*/
public class MyViewGroup extends ViewGroup {
public MyViewGroup(Context context) {
this(context, null);
}

public MyViewGroup(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}

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

private void init() {
//第一步:先添加一个子视图
ImageView imageView = new ImageView(getContext());
imageView.setImageResource(R.mipmap.ic_launcher);
addView(imageView);
}

/**
* 主要是用于对子视图的摆放,其参数2、3、4、5表示当前控件对应的边的左上右下
*/
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
//获得我们添加的子视图
View child0 = getChildAt(0);
//摆放孩子视图
child0.layout(l, t, r, b);//直接用默认的参数的值,则是充满整个屏幕
}
}

编译运行:

自定义ViewGroup基础巩固1---理解onLayout()方法_控件_07

可以正常显示了,但是图片糊了,因为原图被拉伸了,那下面修改一下代码,尝试让咱们的子视图大小变小一点:

自定义ViewGroup基础巩固1---理解onLayout()方法_android ui_08

 编译运行:

自定义ViewGroup基础巩固1---理解onLayout()方法_android ui_09

嗯~~不错~~确实onLayout()可以控制子视图的大小,那下面再来理解一下onLayout()中的四个参数:"表示当前控件对应边左上右下",而当前控件在布局文件的声明是填满父控件的:

自定义ViewGroup基础巩固1---理解onLayout()方法_自定义view_10

所以实际上MyViewGroup当前控件的大小为:

自定义ViewGroup基础巩固1---理解onLayout()方法_控件_11

那这四个参数的位置为:

自定义ViewGroup基础巩固1---理解onLayout()方法_android ui_12

下面可以打印看一下是不是如此:

自定义ViewGroup基础巩固1---理解onLayout()方法_自定义view_13

自定义ViewGroup基础巩固1---理解onLayout()方法_自定义view_14

嗯~~确实是如此,所以对于这个结果就可以理解啦:

自定义ViewGroup基础巩固1---理解onLayout()方法_android ui_15

自定义ViewGroup基础巩固1---理解onLayout()方法_自定义view_16

onLayout()加强:布局多个子控件

对于子控件通常是有多个的,所以这里在init()中添加3个ImageView,如下:

自定义ViewGroup基础巩固1---理解onLayout()方法_自定义view_17

目前当然是无法将添加的控件正常显示出来滴,接着处理下onLayout()对子控件进行布局,这里模拟Android的LinearLayout让其子控件水平显示,在实现之前先看一下LinearLayout也是继承ViewGroup去实现的, 可以瞅一下它的onLayout()方法:

自定义ViewGroup基础巩固1---理解onLayout()方法_android ui_18

具体的显示也是有自己的处理规则的,当然它的实现是比较复杂的,了解下,下面来简单把我们的子控件水平排列:

自定义ViewGroup基础巩固1---理解onLayout()方法_自定义view_19

编译运行:

自定义ViewGroup基础巩固1---理解onLayout()方法_自定义view_20

由于子控件的layout方法摆放的基准点是基于当前ViewGroup的控件,所以比较好理解,不多解释,接下来将它竖着排列:

自定义ViewGroup基础巩固1---理解onLayout()方法_android ui_21

编译运行:

自定义ViewGroup基础巩固1---理解onLayout()方法_控件_22 

onLayout()脑动大开:将子视图布局成倒着的杨辉三角形

有了上面的基础,拉下来多添加几个子控件,来实现类似杨辉三角形的效果,类似于:

自定义ViewGroup基础巩固1---理解onLayout()方法_android ui_23

【注】:至于什么是杨辉三角可以百度百科,这里不是讨论的重点。

首先添加6个子控件:

自定义ViewGroup基础巩固1---理解onLayout()方法_自定义view_24

接着具体来摆放它们:

自定义ViewGroup基础巩固1---理解onLayout()方法_自定义view_25

实现代码比较好理解,不多解释,编译运行:

自定义ViewGroup基础巩固1---理解onLayout()方法_控件_26






关注个人公众号,获得实时推送

自定义ViewGroup基础巩固1---理解onLayout()方法_自定义view_27