自定义ViewGroup中onLayout()确定子View位置和大小
来源:互联网 发布:晨曦计价软件官网 编辑:程序博客网 时间:2024/05/17 08:58
先来看一个很简单的例子,一个继承至ViewGroup的自定义控件容器
public class MyViewGroup extends ViewGroup { public MyViewGroup(Context context) { super(context); } public MyViewGroup(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { }}
然后再XML中添加一个Button,结果不管在XML视图中还是运行起来都看不到button。大家都知道要在MyViewGroup中重写onLayout()方法来确定子view布局位置和大小。
我们在ViewGroup中找到onLayout()方法,发现他是一个抽象方法,你必须重写他,否则就像上面看不到子view。
/** * {@inheritDoc} */ @Override protected abstract void onLayout(boolean changed, int l, int t, int r, int b);
那究竟在onLayout()中怎么去确定子View的位置?
回到上面那个例子,如果我们把MyViewGroup换成我们常见的RelativeLayout,想都不用想妥妥能看到Button的对吧,那我们就去看看RelativeLayout的onLayout()做了什么事情,代码如下:
@Override protected void onLayout(boolean changed, int l, int t, int r, int b) { final int count = getChildCount(); for (int i = 0; i < count; i++) { View child = getChildAt(i); if (child.getVisibility() != GONE) { RelativeLayout.LayoutParams st = (RelativeLayout.LayoutParams) child.getLayoutParams(); child.layout(st.mLeft, st.mTop, st.mRight, st.mBottom); } } }
这段代码的核心就是child.layout(……)这个方法了,这个方法直接确定子view显示位置。这个方法需要传递四个参数:layout(int l, int t, int r, int b)。四个参数什么意思?先copy下网上的一张图(摘自http://blog.csdn.net/dmk877/article/details/49632959):
第一个参数l,即left对应图上的mLeft,以此类推,所以很清楚知道了四个参数分别是子view在父控件坐标系中左边框X坐标,右边框X坐标,上边框Y坐标,下边框Y坐标。为什么是这四个值?仔细想想就知道,只要这四个值就能确定子view的位置和大小了。
l和t好办,我们可以自己定义数值,设置边距。而r跟b其实就是子view的宽高了,子view宽高其实是可以获取的。首先在onMeasure()方法中测量子view的大小。
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); measureChildren(widthMeasureSpec, heightMeasureSpec); }
然后我们就可以获取子view的宽高了:
int childWidth = child.getMeasuredWidth(); int childHeight = child.getMeasuredHeight();
那现在就知道怎么修改我们的MyViewGroup了吧,改后代码是这样的:
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); measureChildren(widthMeasureSpec, heightMeasureSpec); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { final int count = getChildCount(); for (int i = 0; i < count; i++) { View child = getChildAt(i); int childWidth = child.getMeasuredWidth(); int childHeight = child.getMeasuredHeight(); if (child.getVisibility() != GONE) { child.layout(100, 200, childWidth+100, childHeight+200); } } }
测试下,嗯不负众望,子view出来了:
- 自定义ViewGroup中onLayout()确定子View位置和大小
- 自定义ViewGroup,子View可对换位置
- 自定义viewgroup中onMeasure 和onlayout的一点理解
- 自定义AlertDialog的位置和大小确定
- 自定义ViewGroup和其子View
- Android自定义ViewGroup自动分配子view位置
- viewgroup中删除和添加子view
- viewgroup中删除和添加子view
- 自定义ViewGroup onMeasure onLayout
- 自定义View和ViewGroup
- 自定义View和ViewGroup
- Android自定义ViewGroup View的大小和坐标控制
- Android自定义ViewGroup View的大小和坐标控制
- Android自定义ViewGroup的OnMeasure和onLayout详解
- 自定义view中的onLayout
- 自定义view onLayout
- Android 自定义View 和 ViewGroup
- Android 自定义View和ViewGroup
- web开发网页(一)
- 【预研】Storm C++ Wrapper demo的单机版本实现
- NYOJ860 又见01背包(01背包的另一种思路)
- 测试基础积累
- GCD dispatch_async 与dispatch_sync 的理解
- 自定义ViewGroup中onLayout()确定子View位置和大小
- Javascript Api
- redis字符串string类型的操作
- 项目部署之工具使用心得
- JSON.parse()和JSON.stringify()
- java:根据文件头来判断文件类型
- Go语言_函数学习篇
- 轮播
- 移动端页面禁用长按选中功能