设为首页 加入收藏

TOP

Android开发实践:自定义ViewGroup的onLayout()分析(二)
2015-02-02 14:37:28 来源: 作者: 【 】 浏览:30
Tags:Android 开发 实践 定义 ViewGroup onLayout )分析
致子控件的layout_margin不起效果,所以上述效果是子控件一个个紧挨着排列,中间没有空隙。那么,下面我们来研究下如何添加margin效果。


其实,如果要自定义ViewGroup支持子控件的layout_margin参数,则自定义的ViewGroup类必须重载generateLayoutParams()函数,并且在该函数中返回一个ViewGroup.MarginLayoutParams派生类对象,这样才能使用margin参数。


ViewGroup.MarginLayoutParams的定义关键部分如下,它记录了子控件的layout_margin值:


public static class MarginLayoutParams extends ViewGroup.LayoutParams {? ? ? ?
? ? public int leftMargin;
? ? public int topMargin;
? ? public int rightMargin;
? ? public int bottomMargin;
}


你可以跟踪源码看看,其实XML文件中View的layout_xxx参数都是被传递到了各种自定义ViewGroup.LayoutParams派生类对象中。例如LinearLayout的LayoutParams定义的关键部分如下:


public class LinearLayout extends ViewGroup {
?
public static class LayoutParams extends ViewGroup.MarginLayoutParams {
?
? ? public float weight;
? ? public int gravity = -1;
?
? ? public LayoutParams(Context c, AttributeSet attrs) {
?
? ? ? ? ? ? super(c, attrs);
?
? ? ? ? ? ? TypedArray a = c.obtainStyledAttributes(attrs, com.android.internal.R.styleable.LinearLayout_Layout);
? ? ? ? ? ? weight = a.getFloat(com.android.internal.R.styleable.LinearLayout_Layout_layout_weight, 0);
? ? ? ? ? ? gravity = a.getInt(com.android.internal.R.styleable.LinearLayout_Layout_layout_gravity, -1);
?
? ? ? ? ? ? a.recycle();
? ? ? ? }
? ? }
?
? ? @Override
? ? public LayoutParams generateLayoutParams(AttributeSet attrs) {
? ? ? ? return new LinearLayout.LayoutParams(getContext(), attrs);
? ? }
}


这样你大概就可以理解为什么LinearLayout的子控件支持weight和gravity的设置了吧,当然我们也可以这样自定义一些属于我们ViewGroup特有的params,这里就不详细讨论了,我们只继承MarginLayoutParams来获取子控件的margin值。


public class CustomViewGroup extends ViewGroup {
?
? ? public static class LayoutParams extends ViewGroup.MarginLayoutParams {
? ? ? ? public LayoutParams(Context c, AttributeSet attrs) {
? ? ? ? ? ? super(c, attrs);? ? ? ? ? ?
? ? ? ? }? ? ?
? ? }
?
? ? @Override?
? ? public LayoutParams generateLayoutParams(AttributeSet attrs) {?
? ? ? ? return new CustomViewGroup.LayoutParams(getContext(), attrs);?
? ? }
?
}


这样修改之后,我们就可以在onLayout()函数中获取子控件的layout_margin值了,添加了layout_margin的onLayout()函数实现如下所示:


@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
?
? ? int mViewGroupWidth? = getMeasuredWidth();? //当前ViewGroup的总宽度
? ? int mViewGroupHeight = getMeasuredHeight(); //当前ViewGroup的总高度
?
? ? int mPainterPosX = left; //当前绘图光标横坐标位置
? ? int mPainterPosY = top;? //当前绘图光标纵坐标位置?
? ?
? ? int childCount = getChildCount();? ? ? ?
? ? for ( int i = 0; i < childCount; i++ ) {
? ? ? ?
? ? ? ? View childView = getChildAt(i);
?
? ? ? ? int width? = childView.getMeasuredWidth();
? ? ? ? int height = childView.getMeasuredHeight();? ? ? ? ? ?
?
? ? ? ? CustomViewGroup.LayoutParams margins = (CustomViewGroup.LayoutParams)(childView.getLayoutParams());
? ? ? ?
? ? ? ? //ChildView占用的width? = width+leftMargin+rightMargin
? ? ? ? //ChildView占用的height = height+topMargin+bottomMargin
? ? ? ? //如果剩余的空间不够,则移到下一行开始位置
? ? ? ? if( mPainterPosX + width + margins.leftMargin + margins.rightMargin > mViewGroupWidth ) {? ? ? ? ? ? ?
? ? ? ? ? ? mPainterPosX = left;
? ? ? ? ? ? mPainterPosY += height + margins.topMargin + margins.bottomMargin;
? ? ? ? }? ? ? ? ? ? ? ? ? ?
? ? ? ?
? ? ? ? //执行ChildView的绘制
? ? ? ? childView.layout(mPainterPosX+margins.leftMargin, mPainterPosY+margins.topMargin,mPainterPosX+margins.leftMargin+width, mPainterPosY+margins.topMargin+height);
? ? ? ?
? ? ? ? mPainterPosX += width + margins.leftMargin + margins.rightMargin;
? ? }? ? ?
}


6.? 总结


费了好大劲,终于算是把自定义ViewGroup的onLayout()相关知识点讲清楚了,如果有任何疑问欢迎留言或者来信

首页 上一页 1 2 3 下一页 尾页 2/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇Android开发实践:为什么要继承on.. 下一篇Android开发实践:自定义带动画的..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: