Android自定义ViewGroup四打造自己的布局容器Word下载.docx
- 文档编号:22044195
- 上传时间:2023-02-02
- 格式:DOCX
- 页数:21
- 大小:134.15KB
Android自定义ViewGroup四打造自己的布局容器Word下载.docx
《Android自定义ViewGroup四打造自己的布局容器Word下载.docx》由会员分享,可在线阅读,更多相关《Android自定义ViewGroup四打造自己的布局容器Word下载.docx(21页珍藏版)》请在冰豆网上搜索。
protectedvoidonMeasure(intwidthMeasureSpec,intheightMeasureSpec){
//计算出所有的childView的宽和高
measureChildren(widthMeasureSpec,heightMeasureSpec);
//测量并保存layout的宽高(使用getDefaultSize时,wrap_content和match_perent都是填充屏幕)
//稍后会重新写这个方法,能达到wrap_content的效果
setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(),widthMeasureSpec),
getDefaultSize(getSuggestedMinimumHeight(),heightMeasureSpec));
*为所有的子控件摆放位置.
@Override
protectedvoidonLayout(booleanchanged,intleft,inttop,intright,intbottom){
finalintcount=getChildCount();
intchildMeasureWidth=0;
intchildMeasureHeight=0;
intlayoutWidth=0;
//容器已经占据的宽度
intlayoutHeight=0;
intmaxChildHeight=0;
//一行中子控件最高的高度,用于决定下一行高度应该在目前基础上累加多少
for(inti=0;
i<
count;
i++){
Viewchild=getChildAt(i);
//注意此处不能使用getWidth和getHeight,这两个方法必须在onLayout执行完,才能正确获取宽高
childMeasureWidth=child.getMeasuredWidth();
childMeasureHeight=child.getMeasuredHeight();
if(layoutWidth<
getWidth()){
//如果一行没有排满,继续往右排列
left=layoutWidth;
right=left+childMeasureWidth;
top=layoutHeight;
bottom=top+childMeasureHeight;
}else{
//排满后换行
layoutWidth=0;
layoutHeight+=maxChildHeight;
maxChildHeight=0;
layoutWidth+=childMeasureWidth;
//宽度累加
if(childMeasureHeight>
maxChildHeight){
maxChildHeight=childMeasureHeight;
//确定子控件的位置,四个参数分别代表(左上右下)点的坐标值
child.layout(left,top,right,bottom);
}
布局文件:
<
?
xmlversion="
1.0"
encoding="
utf-8"
>
com.openxu.costomlayout.CustomLayoutxmlns:
android="
android:
layout_width="
wrap_content"
layout_height="
>
<
Button
background="
#FF8247"
textColor="
#ffffff"
textSize="
20dip"
padding="
text="
按钮1"
/>
#8B0A50"
10dip"
按钮2222222222222"
#7CFC00"
15dip"
按钮333333"
#1E90FF"
按钮4"
#191970"
按钮5"
#7A67EE"
按钮6"
/com.openxu.costomlayout.CustomLayout>
2.自定义LayoutParams
回想一下我们平时使用RelativeLayout的时候,在布局文件中使用android:
layout_alignParentRight="
true"
、android:
layout_centerInParent="
等各种属性,就能控制子控件显示在父控件的上下左右、居中等效果。
,我们有了解过ViewGroup.LayoutParams类,ViewGroup中有两个内部类ViewGroup.LayoutParams和ViewGroup.MarginLayoutParams,MarginLayoutParams继承自LayoutParams,这两个内部类就是ViewGroup的布局参数类,比如我们在LinearLayout等布局中使用的layout_width\layout_hight等以“layout_”开头的属性都是布局属性。
在View中有一个mLayoutParams的变量用来保存这个View的所有布局属性。
ViewGroup.LayoutParams有两个属性layout_width和layout_height,因为所有的容器都需要设置子控件的宽高,所以这个LayoutParams是所有布局参数的基类,如果需要扩展其他属性,都应该继承自它。
比如RelativeLayout中就提供了它自己的布局参数类RelativeLayout.LayoutParams,并扩展了很多布局参数,我们平时在RelativeLayout中使用的布局属性都来自它:
declare-styleablename="
RelativeLayout_Layout"
attrname="
layout_toLeftOf"
format="
reference"
layout_toRightOf"
layout_above"
format="
layout_below"
layout_alignBaseline"
layout_alignLeft"
layout_alignTop"
layout_alignRight"
layout_alignBottom"
layout_alignParentLeft"
boolean"
layout_alignParentTop"
layout_alignParentRight"
layout_alignParentBottom"
layout_centerInParent"
layout_centerVertical"
layout_alignWithParentIfMissing"
layout_toStartOf"
layout_toEndOf"
layout_alignStart"
layout_alignEnd"
layout_alignParentStart"
layout_alignParentEnd"
/declare-styleable>
看了上面的介绍,我们大概知道怎么为我们的布局容器定义自己的布局属性了吧,就不绕弯子了,按照下面的步骤做:
①.大致明确布局容器的需求,初步定义布局属性
在定义属性之前要弄清楚,我们自定义的布局容器需要满足那些需求,需要哪些属性,比如,我们现在要实现像相对布局一样,为子控件设置一个位置属性layout_position=”“,来控制子控件在布局中显示的位置。
暂定位置有五种:
左上、左下、右上、右下、居中。
有了需求,我们就在attr.xml定义自己的布局属性(和之前讲的自定义属性一样的操作)。
resources>
declare-styleablename="
layout_position"
enumname="
center"
value="
0"
left"
1"
right"
2"
bottom"
3"
rightAndBottom"
4"
/attr>
/declare-styleable>
/resources>
left就代表是左上(按常理默认就是左上方开始,就不用写leftTop了,简洁一点),bottom左下,right右上,rightAndBottom右下,center居中。
属性类型是枚举,同时只能设置一个值。
②.继承LayoutParams,定义布局参数类
我们可以选择继承ViewGroup.LayoutParams,这样的话我们的布局只是简单的支持layout_width和layout_height;
也可以继承MarginLayoutParams,就能使用layout_marginxxx属性了。
因为后面我们还要用到margin属性,所以这里方便起见就直接继承MarginLayoutParams了。
覆盖构造方法,然后在有AttributeSet参数的构造方法中初始化参数值,这个构造方法才是布局文件被映射为对象的时候被调用的。
publicstaticclassCustomLayoutParamsextendsMarginLayoutParams{
publicstaticfinalintPOSITION_MIDDLE=0;
//中间
publicstaticfinalintPOSITION_LEFT=1;
//左上方
publicstaticfinalintPOSITION_RIGHT=2;
//右上方
publicstaticfinalintPOSITION_BOTTOM=3;
//左下角
publicstaticfinalintPOSITION_RIGHTANDBOTTOM=4;
//右下角
publicintposition=POSITION_LEFT;
//默认我们的位置就是左上角
publicCustomLayoutParams(Contextc,AttributeSetattrs){
super(c,attrs);
TypedArraya=c.obtainStyledAttributes(attrs,R.styleable.CustomLayout);
//获取设置在子控件上的位置属性
position=a.getInt(R.styleable.CustomLayout_layout_position,position);
a.recycle();
publicCustomLayoutParams(intwidth,intheight){
super(width,height);
publicCustomLayoutParams(ViewGroup.LayoutParamssource){
super(source);
③.重写generateLayoutParams()
在ViewGroup中有下面几个关于LayoutParams的方法,generateLayoutParams(AttributeSetattrs)是在布局文件被填充为对象的时候调用的,这个方法是下面几个方法中最重要的,如果不重写它,我么布局文件中设置的布局参数都不能拿到。
后面我也会专门写一篇博客来介绍布局文件被添加到activity窗口的过程,里面会讲到这个方法被调用的来龙去脉。
其他几个方法我们最好也能重写一下,将里面的LayoutParams换成我们自定义的CustomLayoutParams类,避免以后会遇到布局参数类型转换异常。
@Override
publicLayoutParamsgenerateLayoutParams(AttributeSetattrs){
returnnewCustomLayoutParams(getContext(),attrs);
protectedViewGroup.LayoutParamsgenerateLayoutParams(ViewGroup.LayoutParamsp){
returnnewCustomLayoutParams(p);
protectedLayoutParamsgenerateDefaultLayoutParams(){
returnnewCustomLayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT);
protectedbooleancheckLayoutParams(ViewGroup.LayoutParamsp){
returnpinstanceofCustomLayoutParams;
④.在布局文件中使用布局属性
注意引入命名空间xmlns:
openxu="
xmlns:
background="
#33000000"
match_parent"
match_parent"
openxu:
layout_position="
text="
textSize="
18dip"
textSize
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Android 自定义 ViewGroup 打造 自己 布局 容器