中的卡牌問題---自定義ViewGroup

學安卓的時間並不算短,但是一直都沒有認認真真的看過,前段時間看見<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的尺寸
	 */
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		// TODO Auto-generated method stub
		
		int 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 0
			Log.v("before-Child-size",""+ child.getMeasuredHeight());
			//計算Child的大小
			measureChild(child,widthMeasureSpec,heightMeasureSpec);
			//This will display ready size
			Log.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的位置
	 */
	@Override
	protected 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>


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章