
在androID中提供了常见的几种VIEwGroup的实现,包括linearLayout、relativeayout、FrameLayout等。这些VIEwGroup可以满足我们一般的开发需求,但是对于界面要求复杂的,这几个布局就显得捉襟见肘了。所以自定义的VIEwGroup在我们接触过的应用中比比皆是。
要想实现一个自定义的VIEwGroup,第一步是学会自定义属性,这些自定义的属性将让我们配置布局文件的时候更加的灵活。自定义属性是在value目录下声明一个attrs.xml文件。
<?xml version="1.0" enCoding="utf-8"?><resources> <declare-styleable name="CascadeVIEwGroup"> <attr name="verticalspacing" format="dimension"/> <attr name="horizontalspacing" format="dimension"/> </declare-styleable> <declare-styleable name="CascadeVIEwGroup_LayoutParams"> <attr name="layout_paddingleft" format="dimension"/> <attr name="layout_paddintop" format="dimension"/> </declare-styleable></resources>
在这里我们声明了两个自定义属性集,CascadeVIEwGroup中的属性是针对我们自定义的CascadeVIEwGroup组件设置的,也就是可以在布局文件中<CascadeVIEwGroup>标签中可以使用的属性。另外一个CascadeVIEwGroup_LayoutParams则是针对于CascadeVIEwGroup中的子VIEw设置的属性。
在编写代码前,我们还设置了一个默认的宽度和高度供CascadeLayout使用。这两个属性在dimens.xml定义。
<?xml version="1.0" enCoding="utf-8"?><resources> <dimen name="default_horizontal_spacing">10dp</dimen> <dimen name="default_vertical_spacing">10dp</dimen></resources>
下面开始编写自定义的组件CascadeLayout了。
package com.app.CustomVIEwMotion;import androID.content.Context;import androID.content.res.TypedArray;import androID.util.AttributeSet;import androID.vIEw.VIEw;import androID.vIEw.VIEwGroup;/** * Created by charles on 2015/8/13. */public class CascadeVIEwGroup extends VIEwGroup { //自定义布局中设置的宽度和高度 private int mHoriztonalSpacing; private int mVerticalSpacing; public CascadeVIEwGroup(Context context) { this(context,null); } public CascadeVIEwGroup(Context context,AttributeSet attrs) { this(context,attrs,0); } public CascadeVIEwGroup(Context context,AttributeSet attrs,int defStyle) { super(context,defStyle); TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.CascadeVIEwGroup); try { //获取设置的宽度 mHoriztonalSpacing = a.getDimensionPixelSize(R.styleable.CascadeVIEwGroup_horizontalspacing,this.getResources().getDimensionPixelSize(R.dimen.default_horizontal_spacing)); //获取设置的高度 mVerticalSpacing = a.getDimensionPixelSize(R.styleable.CascadeVIEwGroup_verticalspacing,this.getResources().getDimensionPixelSize(R.dimen.default_vertical_spacing)); } catch (Exception e) { e.printstacktrace(); } finally { a.recycle(); } } @OverrIDe protected voID onMeasure(int wIDthMeasureSpec,int heightmeasureSpec) { final int count = this.getChildCount(); int wIDth = this.getpaddingleft(); int height = this.getpaddingtop(); for (int i = 0; i < count; i++) { final VIEw currentVIEw = this.getChildAt(i); this.measureChild(currentVIEw,wIDthMeasureSpec,heightmeasureSpec); CascadeVIEwGroup.LayoutParams lp = (CascadeVIEwGroup.LayoutParams) currentVIEw.getLayoutParams(); if(lp.mSettingpaddingleft != 0){ wIDth +=lp.mSettingpaddingleft; } if(lp.mSettingpaddingtop != 0){ height +=lp.mSettingpaddingtop; } lp.x = wIDth; lp.y = height; wIDth += mHoriztonalSpacing; height += mVerticalSpacing; } wIDth +=getChildAt(this.getChildCount() - 1).getMeasureDWIDth() + this.getpaddingRight(); height += getChildAt(this.getChildCount() - 1).getMeasuredHeight() + this.getpaddingBottom(); this.setMeasuredDimension(resolveSize(wIDth,wIDthMeasureSpec),resolveSize(height,heightmeasureSpec)); } @OverrIDe protected voID onLayout(boolean b,int l,int i1,int i2,int i3) { final int count = this.getChildCount(); for (int i = 0; i < count; i++) { final VIEw currentVIEw = this.getChildAt(i); CascadeVIEwGroup.LayoutParams lp = (CascadeVIEwGroup.LayoutParams) currentVIEw.getLayoutParams(); currentVIEw.layout(lp.x,lp.y,lp.x + currentVIEw.getMeasureDWIDth(),lp.y + currentVIEw.getMeasuredHeight()); } } public static class LayoutParams extends VIEwGroup.LayoutParams { int x; int y; int mSettingpaddingleft; int mSettingpaddingtop; public LayoutParams(Context c,AttributeSet attrs) { super(c,attrs); TypedArray a = c.obtainStyledAttributes(attrs,R.styleable.CascadeVIEwGroup_LayoutParams); mSettingpaddingleft = a.getDimensionPixelSize(R.styleable.CascadeVIEwGroup_LayoutParams_layout_paddingleft,0); mSettingpaddingtop = a.getDimensionPixelSize(R.styleable.CascadeVIEwGroup_LayoutParams_layout_paddintop,0); a.recycle(); } public LayoutParams(int wIDth,int height) { super(wIDth,height); } public LayoutParams(VIEwGroup.LayoutParams source) { super(source); } } @OverrIDe protected VIEwGroup.LayoutParams generateDefaultLayoutParams() { return new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT); } @OverrIDe protected VIEwGroup.LayoutParams generateLayoutParams(VIEwGroup.LayoutParams p) { return new LayoutParams(p); } @OverrIDe public VIEwGroup.LayoutParams generateLayoutParams(AttributeSet attrs) { return new LayoutParams(this.getContext(),attrs); }}代码稍微优点长,但是结构还是很清晰的。
1)构造方法中或者XML文件中配置属性的值。通过TypedArray中的方法获取我们在layout布局中设置的属性,并且将他们保存在成员变量中。
2)构造自定义的内部类LayoutParams。构造这个内部类,可以方便我们在测量我们的子VIEw的时候保存他们的属性值,以便在Layout阶段布局。
3)generateLayoutParams()、generateDefaultParams()等方法。在这些方法中返回我们自定义的layoutParams。至于为什么要重写这些方法,可以查看VIEwGroup类的addVIEw()方法就很清楚了。
4)measure阶段。在measure阶段,我们会测量自己的大小,同时也要测量子VIEw的大小,并且将子VIEw的信息保存在LayoutParams中。
5)layout阶段。根据各个子VIEw的信息,布局他们的位置。
最后加上布局文件。
<?xml version="1.0" enCoding="utf-8"?><!--添加自定义属性给vIEwGroup--><!--新添加的命名空间的后缀必须保持和.xml中声明的包名一致--><com.app.CustomVIEwMotion.CascadeVIEwGroup xmlns:androID="http://schemas.androID.com/apk/res/androID" xmlns:ts="http://schemas.androID.com/apk/res/com.app.CustomVIEwMotion" androID:layout_wIDth="match_parent" androID:layout_height="match_parent" ts:horizontalspacing="15dp" ts:verticalspacing="15dp"> <TextVIEw androID:layout_wIDth="100dp" androID:layout_height="100dp" androID:gravity="center" androID:text="text1" androID:background="#668B8B"/> <TextVIEw androID:layout_wIDth="100dp" androID:layout_height="100dp" androID:gravity="center" androID:text="text2" androID:background="#FFDAB9"/> <TextVIEw androID:layout_wIDth="100dp" androID:layout_height="100dp" androID:gravity="center" androID:text="text3" androID:background="#43CD80"/><!--这个子vIEw中添加自定义子vIEw属性--> <TextVIEw androID:layout_wIDth="100dp" androID:layout_height="100dp" androID:gravity="center" androID:text="text4" ts:layout_paddingleft="100dp" ts:layout_paddintop="100dp" androID:background="#00CED1"/></com.app.CustomVIEwMotion.CascadeVIEwGroup>
实现的效果如下:
以上就是的全部内容,希望能给大家一个参考,也希望大家多多支持编程小技巧。
总结以上是内存溢出为你收集整理的Android自定义ViewGroup的实现方法全部内容,希望文章能够帮你解决Android自定义ViewGroup的实现方法所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)