自定义控件之CascadeLayout(一)

来源:互联网 发布:印度不服中国 知乎 编辑:程序博客网 时间:2024/06/15 19:25


1. 自定义控件中的三个构造方法
     一个参数的是在java中实例化调用的。
     二个参数的是在xml中配置时调用的。
     三个参数的构造方法系统不会自动调用,是代码调用的,如在两个参数的构造方法中显式的调用。第一在attrs.xml中声明,第二其值是当前activity或者application中设置的theme中配置。第一属性声明类型是reference,第二中其值指向一个style,style中可以配置相应属性。
详细说明可看
http://www.cnblogs.com/angeldevil/p/3479431.html
或者在经典文章中也有。

2.attr中定义 自定义属性

<declare-styleable name= "CascadeLayout" >         <attr name = "horizontal_spacing" format = "dimension" />         <attr name = "vertical_spacing" format = "dimension" /> </declare-styleable >  

3.xml中配置自定义属性
<qingfengmy.cascadelayout.CascadeLayout    android:layout_width= "match_parent"    android:layout_height= "match_parent"    cascade:horizontal_spacing= "30dp"    cascade:vertical_spacing= "20dp" >    <View        android:layout_width= "100dp"        android:layout_height= "150dp"        android:background= "#FF0000" />    <View        android:layout_width= "100dp"        android:layout_height= "150dp"        android:background= "#00FF00" />    <View        android:layout_width= "100dp"        android:layout_height= "150dp"        android:background= "#0000FF" /></qingfengmy.cascadelayout.CascadeLayout>

4. 代码中获取自定义属性
TypedArray a = context.obtainStyledAttributes(attrs,           R.styleable. CascadeLayout);try {     mHorizontalSpacing = a.getDimensionPixelSize(                R.styleable. CascadeLayout_horizontal_spacing,                getResources().getDimensionPixelSize(                           R.dimen. activity_horizontal_margin));     mVerticalSpacing = a.getDimensionPixelSize(                R.styleable. CascadeLayout_vertical_spacing,                getResources().getDimensionPixelSize(                           R.dimen. activity_vertical_margin));} catch (NotFoundException e) {     e.printStackTrace();} finally {     a.recycle();}

5. 自定义LayoutParams,用来记录view左上角的x/y坐标
public static class LayoutParams extends ViewGroup.LayoutParams {     int x;     int y;     public LayoutParams(Context context, AttributeSet attrs) {            super(context, attrs);     }     public LayoutParams( int w, int h) {            super(w, h);     }}

6. 重写LayoutParams还需重写以下方法,否则会出错,而且这些方法的重写是惯例,以后再用到也这样写就可以了。
@Overrideprotected boolean checkLayoutParams(ViewGroup.LayoutParams p) {     return p instanceof LayoutParams;}@Overrideprotected LayoutParams generateDefaultLayoutParams() {     return new LayoutParams(LayoutParams. WRAP_CONTENT,                LayoutParams. WRAP_CONTENT);}@Overridepublic LayoutParams generateLayoutParams(AttributeSet attrs) {     return new LayoutParams(getContext(), attrs);}@Overrideprotected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {     return new LayoutParams(p. width, p. height);}

7. onMeasure方法中测量控件本身大小
@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {     int width = 0;     int height = getPaddingTop();     int count = getChildCount();     for (int i = 0; i < count; i++) {           View child = getChildAt(i);            // 令每个子view测量自身           measureChild(child, widthMeasureSpec, heightMeasureSpec);           LayoutParams lp = (LayoutParams) child.getLayoutParams();           width = getPaddingLeft() + mHorizontalSpacing * i;            // layoutParams中保存每个子视图左上角的x和y坐标           lp. x = width;           lp. y = height;           width += child.getMeasuredWidth();           height += mVerticalSpacing;     }     // 使用计算所得的宽高设置整个布局的测量尺寸     width += getPaddingRight();     height += getChildAt(getChildCount() - 1).getMeasuredHeight()                + getPaddingBottom();     // resolveSize的主要作用就是根据你提供的大小和MeasureSpec,返回你想要的大小值,这个里面根据传入模式的不同来做相应的处理     setMeasuredDimension(resolveSize(width, widthMeasureSpec),                 resolveSize(height, heightMeasureSpec));}

8. onLayout方法中利用onmeasure中获取的数据,重新为子view布局,设置位置
@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {     int count = getChildCount();     for (int i = 0; i < count; i++) {           View child = getChildAt(i);           LayoutParams lp = (LayoutParams) child.getLayoutParams();           child.layout(lp. x, lp. y, lp. x + child.getMeasuredWidth(), lp.y                     + child.getMeasuredHeight());     }}


9. 源码

https://github.com/qingfengmy/Cascadelayout


0 0