<50 android hacks>中的卡牌问题---自定义ViewGroup

来源:互联网 发布:云视通摄像头扫描软件 编辑:程序博客网 时间:2024/06/11 19:34

学安卓的时间并不算短,但是一直都没有认认真真的看过,前段时间看见<50 android hacks>,觉得这本书写的真的不错,国内也有中文版.

要求显示上面的效果,通常我就会用RelativeLayout和layout_margin*来实现

In this hack, we’ll look at another way of creating
the same type of layout—we’ll create a custom View-
Group . The benefits of using a custom ViewGroup
instead of adding margins by hand in an XML file are
these:

A.It’s easier to maintain if you’re using it in different activities.

B. You can use custom attributes to customize the position of the ViewGroup children.
C. The XML will be easier to understand because it’ll be more concise.
D. If you need to change the margins, you won’t need to recalculate by hand every child’s margin.



下面用ViewGroup实现:

java:

package com.example.lock;import android.content.Context;import android.content.res.TypedArray;import android.util.AttributeSet;import android.util.Log;import android.view.View;import android.view.ViewGroup;/** *  * @author kutear * */public class ExampleView extends ViewGroup{    private int horizontal_spacing = 0;     private int vertical_spacing = 0; TypedArray t = null;public ExampleView(Context context, AttributeSet attrs) {super(context, attrs);// TODO Auto-generated constructor stub//这里是取得< ExampleView />的自定义属性 t = context.obtainStyledAttributes(attrs, com.example.lock.R.styleable.ExampleView); horizontal_spacing = t.getDimensionPixelSize(com.example.lock.R.styleable.ExampleView_horizontal_spacing, 20); vertical_spacing = t.getDimensionPixelSize(com.example.lock.R.styleable.ExampleView_vertical_spacing, 30); int marginleft = t.getDimensionPixelSize(com.example.lock.R.styleable.ExampleView_layout_marginleft,10); Log.v("XML-height",""+ horizontal_spacing); Log.v("XML-width",""+ vertical_spacing); Log.v("XML-MarginLeft",""+ marginleft); t.recycle();}   /** * 用来计算Parent和Child的尺寸 */@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {// TODO Auto-generated method stubint width = MeasureSpec.getSize(widthMeasureSpec); //if fill_parent,ViewGroup的宽为该值..int height = MeasureSpec.getSize(heightMeasureSpec);//同上Log.v("width", "width:"+width);Log.v("height", "height:"+height);int modeWidth = MeasureSpec.getMode(widthMeasureSpec);int modeHeight = MeasureSpec.getMode(heightMeasureSpec);Log.v("Mode--H:", ""+modeHeight);Log.v("Mode--W:", ""+modeWidth);Log.v("AT_MOST:",""+MeasureSpec.AT_MOST);Log.v("EXACTLY:",""+MeasureSpec.EXACTLY);Log.v("UNSPECIFIED:",""+MeasureSpec.UNSPECIFIED);int childHeight = 0; //Child的总高度....用来确定ViewGroup是wrap_content时的高度int childWidth = 0;  //同上int count = getChildCount();for(int i=0;i<count;i++){View child = getChildAt(i);//This will display 0Log.v("before-Child-size",""+ child.getMeasuredHeight());//计算Child的大小measureChild(child,widthMeasureSpec,heightMeasureSpec);//This will display ready sizeLog.v("after-Child-Size",""+ child.getMeasuredHeight());ExampleView.LayoutParams lp = (ExampleView.LayoutParams) child.getLayoutParams();int cHeight = child.getMeasuredHeight();int cWidth = child.getMeasuredWidth();if (i==0) {childHeight += cHeight;childWidth += cWidth+lp.marginleft;}else {childHeight += vertical_spacing;childWidth +=horizontal_spacing+lp.marginleft;}}Log.v("Wrap_content:", childWidth+"---"+childHeight);setMeasuredDimension(MeasureSpec.AT_MOST==modeWidth?childWidth:width,//warp_content时为前者MeasureSpec.AT_MOST==modeHeight?childHeight:height); //parent's Size, fill_parent or wrap_content}/** * 绘制Child的位置 */@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {/** * 参数表示:l-->left  ViewGroup的左边的坐标 *         其他的类似 *   ViewGroup在整个屏幕中的位置.... *   不是ViewGroup的相对位置... *    *    */// TODO Auto-generated method stub int WT_S=0; //下一View的开始位置  //int WT_E=0; //下一VIew的结束位置 int childCount = getChildCount();    Log.v("-----", "L="+l+"--T="+t+"--R="+r+"--B="+b);    for (int i = 0; i < childCount; i++) {           View childView = getChildAt(i);           // 获取在onMeasure中计算的视图尺寸           int measureHeight = childView.getMeasuredHeight();           int measuredWidth = childView.getMeasuredWidth();           Log.v("Child-Height", measureHeight+"");        Log.v("Child-Width", measuredWidth+"");        ExampleView.LayoutParams lp = (ExampleView.LayoutParams) childView.getLayoutParams();        Log.v("leftMargin",""+lp.marginleft);        Log.v("leftMargin",""+lp.rightMargin);        WT_S += (i==0?0:horizontal_spacing)+lp.marginleft;        Log.v("WT_S", WT_S+"");        //这里的四个方向的参数位相对与ViewGroup的位置,,ViewGroup的左上角位(0,0)        childView.layout(WT_S, vertical_spacing*i,        WT_S+measuredWidth, vertical_spacing*i+measureHeight);                    }   }@Override    protected android.view.ViewGroup.LayoutParams generateDefaultLayoutParams() {        return new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,                ViewGroup.LayoutParams.MATCH_PARENT);    }     @Override    public android.view.ViewGroup.LayoutParams generateLayoutParams(            AttributeSet attrs) {        return new LayoutParams(getContext(), attrs);    }     @Override    protected android.view.ViewGroup.LayoutParams generateLayoutParams(            android.view.ViewGroup.LayoutParams p) {        return new LayoutParams(p);    }    public static class LayoutParams extends MarginLayoutParams {        private int horizontal_spacing = 0;         private int vertical_spacing = 0;         public int marginleft = -1;        public LayoutParams(Context c, AttributeSet attrs) {            super(c, attrs);             TypedArray ta = c.obtainStyledAttributes(attrs,                    R.styleable.ExampleView);           //此处是取得ViewGroup中的Child中的自定义属性            horizontal_spacing = ta.getInt(R.styleable.ExampleView_horizontal_spacing, -1);            vertical_spacing = ta.getInt(R.styleable.ExampleView_vertical_spacing, -1);            marginleft = ta.getDimensionPixelSize(R.styleable.ExampleView_layout_marginleft, 0);            int paddingleft = ta.getIndex(R.styleable.View_paddingEnd);            Log.v("Padding",""+paddingleft);             Log.v("marginleft",""+marginleft);             ta.recycle();        }         public LayoutParams(int width, int height) {            super(width, height);        }          public LayoutParams(android.view.ViewGroup.LayoutParams source) {            super(source);        }         public LayoutParams(MarginLayoutParams source) {            super(source);        }    }}

xml:

attrs.xml

<?xml version="1.0" encoding="utf-8"?><resources>    <declare-styleable name="ExampleView">        <attr name="horizontal_spacing" format="dimension" />        <attr name="vertical_spacing" format="dimension" />        <attr name="layout_marginleft" format="dimension"/>    </declare-styleable></resources>

test.aml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:cascade="http://schemas.android.com/apk/res/com.example.lock"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >    <TextView        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="MMMMMM" >    </TextView>    <com.example.lock.ExampleView        android:layout_width="wrap_content"        android:layout_height="wrap_content"        cascade:layout_marginleft="20dp"        android:background="#abcdef"        cascade:horizontal_spacing="30dp"        cascade:vertical_spacing="30dp" >        <TextView            android:layout_width="100dp"            android:layout_height="150dp"            android:background="#FF0000"            android:text="AAA" />        <TextView            android:layout_width="100dp"            android:layout_height="150dp"            cascade:layout_marginleft="20dp"            android:background="#0000FF"            android:text="BBB" />        <TextView            android:layout_width="100dp"            android:layout_height="150dp"            android:background="#00FF00"            android:text="CCC" />    </com.example.lock.ExampleView></LinearLayout>


0 0
原创粉丝点击