標籤:意義 java 測量 apple xml檔案 根據 size change pixel
一、Android自訂view屬性
1.在res/values/styles.xml
檔案裡面聲明一個我們自訂的屬性:
<resources> <!--name為聲明的"屬性集合"名,可以隨便取,但是最好是設定為跟我們的View一樣的名稱--> <declare-styleable name="CircleView"> <!--聲明我們的屬性,名稱為default_size,取實值型別為尺寸類型(dp,px等)--> <attr name="radius" format="dimension"></attr> <attr name="circle_color" format="color"></attr> </declare-styleable></resources>
2.在自訂View中擷取對應設定的屬性值
public CircleView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); //即屬性集合的標籤,在R檔案中名稱為R.styleable+name TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CircleView); //第一個參數為屬性集合裡面的屬性,R檔案名稱:R.styleable+屬性集合名稱+底線+屬性名稱 //第二個參數為,如果沒有設定這個屬性,則設定的預設的值 radius = typedArray.getDimensionPixelOffset(R.styleable.CircleView_radius, 20); color = typedArray.getColor(R.styleable.CircleView_circle_color, 000000); //最後記得將TypedArray對象回收 typedArray.recycle(); }
3.在xml檔案中設定屬性值(1)首先需要定義命名空間 xmlns:rc="http://schemas.android.com/apk/res-auto"(2)設定屬性值 rc:radius rc:circle_color
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:rc="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.ruanchao.todaynews.UserViewActivity"> <com.ruanchao.todaynews.view.CircleView android:layout_width="wrap_content" android:layout_height="wrap_content" rc:radius="50dp" rc:circle_color="#FF69B4"/> </LinearLayout>
二、Android自訂View 1.onMeasure
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
參數中的
widthMeasureSpec
和
heightMeasureSpec包含了兩層資訊:測量模式和測量尺寸
(1)測量模式:
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
測量模式 |
表示意思 |
UNSPECIFIED |
父容器沒有對當前View有任何限制,當前View可以任意取尺寸(match_parent) |
EXACTLY |
當前的尺寸就是當前View應該取的尺寸(xml配置固定值) |
AT_MOST |
當前尺寸是當前View能取的最大尺寸(wrap_content) |
(2)尺寸大小:
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
範例程式碼:
private int getMySize(int defaultSize, int measureSpec) { int mySize = defaultSize; int mode = MeasureSpec.getMode(measureSpec); int size = MeasureSpec.getSize(measureSpec); switch (mode) { case MeasureSpec.UNSPECIFIED: {//如果沒有指定大小,就設定為預設大小 mySize = defaultSize; break; } case MeasureSpec.AT_MOST: {//如果測量模式是最大取值為size //我們將大小取最大值,你也可以取其他值 mySize = size; break; } case MeasureSpec.EXACTLY: {//如果是固定的大小,那就不要去改變它 mySize = size; break; } } return mySize;} @Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width = getMySize(100, widthMeasureSpec); int height = getMySize(100, heightMeasureSpec); if (width < height) { height = width; } else { width = height; } setMeasuredDimension(width, height);}
<com.hc.studyview.MyView android:layout_width="match_parent" android:layout_height="100dp" android:background="#ff0000" />
2.onDraw 直接在畫板Canvas對象上繪製(1)invalidate方法會執行onDraw過程,只能在UI線程調用(2)postInvalidate 可以在非UI線程調用,省去了Handler訊息調用(3)RequestLayout 會執行onMeasure,onLayout ,onDraw三、Android自訂ViewGroup自訂ViewGruup要經曆以下幾步:1、根據各個子View的大小,確定ViewGroup大小(重寫onMeasure()方法)2、在ViewGroup中進行View的擺放(重寫onLayout()方法) 範例程式碼:自訂ViewGroup實現LinearLayout布局第一步:確定ViewGroup大小
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int with = MeasureSpec.getSize(widthMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); int withMode = MeasureSpec.getMode(widthMeasureSpec); int heigthMode = MeasureSpec.getMode(heightMeasureSpec); if (getChildCount() == 0) {//如果沒有子View,當前ViewGroup沒有存在的意義,不用佔用空間 setMeasuredDimension(0, 0); return; } if (withMode == MeasureSpec.AT_MOST && heigthMode == MeasureSpec.AT_MOST){ //高度累加,寬度取最大 setMeasuredDimension(getMaxChildWidth(),getTotleHeight()); }else if (heigthMode == MeasureSpec.AT_MOST){ setMeasuredDimension(with,getTotleHeight()); }else if (withMode == MeasureSpec.AT_MOST){ setMeasuredDimension(getMaxChildWidth(),height); } } /*** * 擷取子View中寬度最大的值 */ private int getMaxChildWidth() { int childCount = getChildCount(); int maxWidth = 0; for (int i = 0; i < childCount; i++) { View childView = getChildAt(i); if (childView.getMeasuredWidth() > maxWidth) { maxWidth = childView.getMeasuredWidth(); } } return maxWidth; } /*** * 將所有子View的高度相加 **/ private int getTotleHeight() { int childCount = getChildCount(); int height = 0; for (int i = 0; i < childCount; i++) { View childView = getChildAt(i); height += childView.getMeasuredHeight(); } return height; }
第二步:在ViewGroup中進行子View的擺放
@Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { int count = getChildCount(); int currentHeigth = 0; //將子View逐個擺放 for (int i = 0; i < count; i++) { View child = getChildAt(i); int childHeigth = child.getMeasuredHeight(); child.layout(left, currentHeigth, right + child.getMeasuredWidth(), currentHeigth + childHeigth); currentHeigth += childHeigth; } }
測試xml
<com.rc.studyview.MyViewGroup android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#ff9900"> <Button android:layout_width="100dp" android:layout_height="wrap_content" android:text="btn" /> <Button android:layout_width="200dp" android:layout_height="wrap_content" android:text="btn" /> <Button android:layout_width="50dp" android:layout_height="wrap_content" android:text="btn" /> </com.rc.studyview.MyViewGroup>
Android 自訂View、ViewGroup和自訂屬性