前言
儘管Android系統提供了不少控制元件,但是有很多酷炫效果仍然是系統原生控制元件無法實現的。好在Android允許自定義控制元件,來彌補原生控制元件的不足。但是在很多初學者看來,自定義View似乎很難掌握。其中有很大一部分原因是我們平時看到的自定義View使用中,有多種形式,有的寥寥數筆,有的邏輯很複雜,有的直接繼承View或ViewGroup,有的卻直接繼承系統的原生控制元件,有的可以直接使用系統定義的屬性,而有的卻自定義了自己的屬性......所以不明白使用規則的開發者,很容易被這隻“紙老虎”嚇到。
實際上實現自定義View的方式,從整體上看,只分為三種:組合控制元件,繼承控制元件,自繪控制元件。然後就是根據需要來新增自定義的屬性,就這麼簡單。本文將會針對這4個方面進行詳細的講解。主要內容如下:
一、組合控制元件
組合控制元件,顧名思義,就是將系統原有的控制元件進行組合,構成一個新的控制元件。這種方式下,不需要開發者自己去繪製圖上顯示的內容,也不需要開發者重寫onMeasure,onLayout,onDraw方法來實現測量、佈局以及draw流程。所以,在實現自定義view的三種方式中,這一種相對比較簡單。
實際開發中,標題欄就是一個比較常見的例子。因為在一個app的各個介面中,標題欄基本上是大同小異,複用率很高。所以經常會將標題欄單獨做成一個自定義view,在不同的介面直接引入即可,而不用每次都把標題欄佈局一遍。本節就自定義一個標題欄,包含標題和返回按鈕兩個控制元件,來介紹這種組合控制元件的實現方式。
1、定義標題欄佈局檔案
定義標題欄的佈局檔案custom_title_view.xml,將返回按鈕和標題文字進行組合。這一步用於確定標題欄的樣子,程式碼如下所示:
1 <?xml version="1.0" encoding="utf-8"?> 2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="wrap_content" 5 android:background="@android:color/holo_orange_light"> 6 <Button 7 android:id="@+id/btn_left" 8 android:layout_width="wrap_content" 9 android:layout_height="wrap_content" 10 android:layout_centerVertical="true" 11 android:layout_marginLeft="5dp" 12 android:text="Back" 13 android:textColor="@android:color/white" /> 14 15 <TextView 16 android:id="@+id/title_tv" 17 android:layout_width="wrap_content" 18 android:layout_height="wrap_content" 19 android:layout_centerInParent="true" 20 android:text="Title" 21 android:textColor="@android:color/white" 22 android:textSize="20sp" /> 23 </RelativeLayout>
這個佈局很簡單,就不多說了。
2、根據給定佈局實現自定義View
1 public class CustomTitleView extends FrameLayout implements View.OnClickListener { 2 private View.OnClickListener mLeftOnClickListener; 3 private Button mBackBtn; 4 private TextView mTittleView; 5 6 public CustomTitleView(@NonNull Context context, @Nullable AttributeSet attrs) { 7 super(context, attrs); 8 LayoutInflater.from(context).inflate(R.layout.custom_title_view, this); 9 mBackBtn = findViewById(R.id.btn_left); 10 mBackBtn.setOnClickListener(this); 11 mTittleView = findViewById(R.id.title_tv); 12 } 13 14 @Override 15 public void onClick(View v) { 16 switch (v.getId()) { 17 case R.id.btn_left: 18 if (mLeftOnClickListener != null) { 19 mLeftOnClickListener.onClick(v); 20 } 21 break; 22 } 23 } 24 25 public void setLeftOnClickListener(View.OnClickListener leftOnClickListener) { 26 mLeftOnClickListener = leftOnClickListener; 27 } 28 29 public void setTittle(String title){ 30 mTittleView.setText(title); 31 } 32 }
為了編譯理解和記憶,這裡對該部分做一點說明:
(1)程式碼中對外提供了兩個介面,一是動態設定標題,二是使用者可以自定義返回按鈕的點選事件。
(2)CustomTitleView的建構函式,要選擇兩個引數的,選擇其它引數的建構函式會報錯。這一點是筆者開發機測試的結果,暫時不清楚是不是所有手機上都是這樣。
(3)這裡是繼承的FrameLayout,但是繼承LinearLayout,RelativeLayout等系統佈局控制元件都可以。之所以要繼承這些系統現成的ViewGroup,是因為這樣可以不用再重寫onMeasure,onLayout等,這樣省事很多。由於這裡是一個佈局控制元件,要用LayoutInflater來填充,所以需要繼承ViewGroup,如果繼承View的直接子類,編譯會不通過。所以,CustomTitleView自己就是一個容器,完全可以當成容器使用,此時CustomTitleView自身的內容會和其作為父佈局新增的子控制元件,效果會疊加,具體的疊加效果是根據繼承的容器特性決定的。
3、在Activity的佈局檔案中新增CustomTitleView
在Activity的佈局檔案activity_custom_view_compose_demo.xml中,像使用系統控制元件一樣使用CustomTitleView即可。前說了,CustomTitleView自己就是繼承的現成的系統佈局,所以它們擁有的屬性特性,CustomTitleView一樣擁有。
1 <?xml version="1.0" encoding="utf-8"?> 2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent"> 5 <com.example.demos.customviewdemo.CustomTitleView 6 android:id="@+id/customview_title" 7 android:layout_width="match_parent" 8 android:layout_height="wrap_content"> 9 </com.example.demos.customviewdemo.CustomTitleView> 10 </RelativeLayout>
4、在Activity中操作CustomTitleView
1 public class CustomViewComposeDemoActivity extends AppCompatActivity { 2 3 private CustomTitleView mCustomTitleView; 4 @Override 5 protected void onCreate(Bundle savedInstanceState) { 6 super.onCreate(savedInstanceState); 7 setContentView(R.layout.activity_custom_view_compose_demo); 8 mCustomTitleView = findViewById(R.id.customview_title); 9 mCustomTitleView.setTittle("This is Title"); 10 mCustomTitleView.setLeftOnClickListener(new View.OnClickListener() { 11 @Override 12 public void onClick(View v) { 13 finish(); 14 } 15 }); 16 17 } 18 }
在第8行中,獲取到CustomTitleView例項,第9行設定標題文字,第10行自定義“Back”按鈕點選事件。
5、效果圖
按照如上的4步,就通過組合控制元件完成了一個比較簡單的自定義標題欄。可見,這種方式是非常簡單的。
二、繼承控制元件
通過繼承系統控制元件(View子類控制元件或ViewGroup子類控制元件)來完成自定義View,一般是希望在原有系統控制元件基礎上做一些修飾性的修改,而不會做大幅度的改動,如在TextView的文字下方新增下劃線,在LinearLayout佈局中加一個蒙板等。這種方式往往都會複用系統控制元件的onMeasure和onLayout方法,而只需要重寫onDraw方法,在其中繪製一些需要的內容。下面會分別繼承View類控制元件和ViewGroup類控制元件來舉例說明。
1、繼承View類系統控制元件
如下示例為在TextView文字下方顯示紅色下劃線,其基本步驟如下:
(1)繼承View控制元件,並重寫onDraw方法
1 @SuppressLint("AppCompatCustomView") 2 public class UnderlineTextView extends TextView{ 3 public UnderlineTextView(Context context, @Nullable AttributeSet attrs) { 4 super(context, attrs); 5 } 6 7 @Override 8 protected void onDraw(Canvas canvas) { 9 super.onDraw(canvas); 10 Paint paint = new Paint(); 11 paint.setColor(Color.RED); 12 paint.setStrokeWidth(5); 13 int width = getWidth(); 14 int height = getBaseline(); 15 canvas.drawLine(0,height,width,height,paint); 16 } 17 }
(2)在佈局檔案中呼叫
就像使用一個普通TextView一樣使用UnderlineTextView。
1 <?xml version="1.0" encoding="utf-8"?> 2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent"> 5 <com.example.demos.customviewdemo.UnderlineTextView 6 android:layout_width="wrap_content" 7 android:layout_height="wrap_content" 8 android:textSize="50dp" 9 android:layout_centerInParent="true" 10 android:text="Hello World!"/> 11 </RelativeLayout>
(3)效果圖
2、繼承ViewGroup類系統控制元件
如下示例演示,在layout佈局上新增一個淺紅色的半透明蒙板,這種需求在工作中也是非常常見的。
(1)繼承ViewGroup類系統控制元件
1 public class ForegroundLinearLayout extends LinearLayout{ 2 public ForegroundLinearLayout(Context context, @Nullable AttributeSet attrs) { 3 super(context, attrs); 4 } 5 6 @Override 7 protected void dispatchDraw(Canvas canvas) { 8 super.dispatchDraw(canvas); 9 canvas.drawColor(Color.parseColor("#50FF0000")); 10 } 11 }
(2)在佈局檔案中呼叫
對ForegroundLinearLayout的使用,就和使用其父類LinearLayout一樣。
1 <?xml version="1.0" encoding="utf-8"?> 2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent"> 5 <com.example.demos.customviewdemo.ForegroundLinearLayout 6 android:layout_width="match_parent" 7 android:layout_height="200dp" 8 android:layout_centerInParent="true" 9 android:gravity="center"> 10 11 <TextView 12 android:layout_width="wrap_content" 13 android:layout_height="wrap_content" 14 android:layout_centerInParent="true" 15 android:text="Hello World!" 16 android:textColor="@android:color/black" 17 android:textSize="50dp" /> 18 </com.example.demos.customviewdemo.ForegroundLinearLayout> 19 </RelativeLayout>
(3)效果圖
在寬為全屏寬度,高為200dp的佈局範圍內,繪製完子其子控制元件TextView後,在上面覆蓋了一層淺紅色的半透明蒙板。
從上面兩個例子可見,繼承系統原有的控制元件來實現自定義View,步驟非常簡單,比組合控制元件簡單多了。但是這一節需要對Canvas,paint等繪製方面的知識有一定的瞭解,且還需要對ViewGroup的中內容的繪製順序有一定的瞭解,才能在原生控制元件的基礎上做出想要的效果來。
三、自繪控制元件
這三種方法中,自繪控制元件是最複雜的,因為所有的繪製邏輯和流程都需要自己完成。採用自繪控制元件這種方式時,如果自定義View為最終的葉子控制元件,那麼需要直接繼承View;而不過自定義View為容器類控制元件,則需要直接繼承ViewGroup。這裡依然針對直接繼承View和ViewGroup分別舉例進行說明。
1、自繪葉子View控制元件
這裡通過畫一個直方圖來展示自繪View控制元件的實現。
(1)直接繼承View類
自繪葉子View控制元件時,最主要工作就是繪製出豐富的內容,這一過程是在重寫的onDraw方法中實現的。由於是葉子view,它沒有子控制元件了,所以重寫onLayout沒有意義。onMeasure的方法可以根據自己的需要來決定是否需要重寫,很多情況下,不重寫該方法並不影響正常的繪製。
1 public class HistogramView extends View{ 2 3 private Paint mPaint; 4 private Path mPath; 5 6 public HistogramView(Context context, @Nullable AttributeSet attrs) { 7 super(context, attrs); 8 mPaint = new Paint(); 9 mPath = new Path(); 10 } 11 12 @Override 13 protected void onDraw(Canvas canvas) { 14 super.onDraw(canvas); 15 //繪製座標軸 16 mPaint.reset(); 17 mPath.reset(); 18 mPaint.setColor(Color.BLACK); 19 mPaint.setStyle(Paint.Style.STROKE); 20 mPath.moveTo(100,100); 21 mPath.rLineTo(0,402); 22 mPath.rLineTo(800,0); 23 canvas.drawPath(mPath,mPaint); 24 //繪製文字 25 mPaint.reset(); 26 mPaint.setTextSize(30); 27 mPaint.setStyle(Paint.Style.FILL); 28 canvas.drawText("Froyo",160,540,mPaint); 29 canvas.drawText("CB",280,540,mPaint); 30 canvas.drawText("ICS",380,540,mPaint); 31 canvas.drawText("J",480,540,mPaint); 32 canvas.drawText("KitKat",560,540,mPaint); 33 canvas.drawText("L",690,540,mPaint); 34 canvas.drawText("M",790,540,mPaint); 35 //繪製直方圖,柱形圖是用較粗的直線來實現的 36 mPaint.reset(); 37 mPaint.setColor(Color.GREEN); 38 mPaint.setStrokeWidth(80); 39 float[] lines3={ 40 200,500,200,495, 41 300,500,300,480, 42 400,500,400,480, 43 500,500,500,300, 44 600,500,600,200, 45 700,500,700,150, 46 800,500,800,350, 47 }; 48 canvas.drawLines(lines3,mPaint); 49 } 50 }
(2)在Activity介面的佈局檔案中引入
和其它自定義控制元件一樣,直接在佈局檔案中引入即可。
1 <?xml version="1.0" encoding="utf-8"?> 2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent"> 5 6 <com.example.demos.customviewdemo.HistogramView 7 android:layout_width="match_parent" 8 android:layout_height="wrap_content"/> 9 10 </RelativeLayout>
(3)效果圖
2、自繪ViewGroup控制元件
這裡通過自定義一個父佈局控制元件,並新增一個子view來作為例子講解該方法的實現。
(1)直接繼承ViewGroup類
自繪ViewGroup控制元件,需要直接繼承ViewGroup,在該系列第一篇文章中將繪製流程的時候就講過,onLayout是ViewGroup中的抽象方法,其直接繼承者必須實現該方法。所以這裡,onLayout方法必須要實現的,如果這裡面的方法體為空,那該控制元件的子view就無法顯示了。要想準確測量,onMeasure方法也是要重寫的。下面例子中,只演示了第一個子view的測量和佈局,onLayout方法中的child.layout,就完成了對子view的佈局。
1 public class CustomLayout extends ViewGroup { 2 public CustomLayout(Context context, AttributeSet attrs) { 3 super(context, attrs); 4 } 5 6 @Override 7 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 8 super.onMeasure(widthMeasureSpec, heightMeasureSpec); 9 if (getChildCount() > 0) { 10 //只測量第一個child 11 View child = getChildAt(0); 12 measureChild(child, widthMeasureSpec, heightMeasureSpec); 13 } 14 } 15 16 @Override 17 protected void onLayout(boolean changed, int l, int t, int r, int b) { 18 if (getChildCount() > 0) { 19 //只佈局第一個child 20 View child = getChildAt(0); 21 child.layout(0, 0, child.getMeasuredWidth(), child.getMeasuredHeight()); 22 } 23 } 24 }
(2)在佈局檔案中和普通父佈局一樣被引入
1 <?xml version="1.0" encoding="utf-8"?> 2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent"> 5 6 <com.example.demos.customviewdemo.CustomLayout 7 android:layout_width="match_parent" 8 android:layout_centerInParent="true" 9 android:layout_height="wrap_content"> 10 <TextView 11 android:layout_width="wrap_content" 12 android:layout_height="wrap_content" 13 android:text="Hello World!" 14 android:textSize="50dp"/> 15 16 </com.example.demos.customviewdemo.CustomLayout> 17 18 </RelativeLayout>
(3)效果圖
上述程式碼中第8行沒有起效,從佈局上看TextView應該是處於螢幕的正中央,但是實際結果卻還是在左上方顯示。這是因為CustomLayout控制元件,並沒有實現“android:layout_centerInParent”這個屬性,所以是無效的。關於屬性的問題,正是下一節要介紹的內容。
四、在自定義View中使用自定義屬性
我們在使用Android原生控制元件的時候,經常可以看到在佈局檔案中可以設定很多的屬性值,如
1 <TextView 2 android:id="@+id/title_tv" 3 android:layout_width="wrap_content" 4 android:layout_height="wrap_content" 5 android:layout_centerInParent="true" 6 android:text="Title" 7 android:textColor="@android:color/white" 8 android:textSize="20sp" />
這裡可以根據需要隨時設定TextView要顯示的文字,文字顏色,文字大小等各種屬性,給使用者帶來了極大的方便。我們在使用自定義View的時候,也非常希望能夠像TextView等系統原生控制元件一樣通過設定屬性值來個性化自定義View。本節我們們在上一節自定義直方圖的基礎上,來介紹自定義屬性的基本使用流程。
1、在values中編寫需要的屬性
在res/values/下新建資原始檔,這裡我們們命名為attrs.xml,在其中編寫所需要的屬性
1 <?xml version="1.0" encoding="utf-8"?> 2 <resources> 3 <declare-styleable name="HistogramView"> 4 <attr name="textColor" format="color"/> 5 <attr name="histogramColor" format="color"/> 6 </declare-styleable> 7 </resources>
這裡<declare-styleable>中的name是自行命名的,可以理解為這個自定義屬性集合的名稱。程式碼中包含了兩個自定義屬性,名稱分別為“textColor”和“histogramColor”,這裡用來設定直方圖中文字的顏色和直方圖的顏色。format表示的是屬性的格式,這裡均設定為“color”,表示對應的屬性是用來設定顏色值的。對於“format”,後面還會詳細講到。其它的就是固定的格式了,直接套用就行。
2、在自定義View中引入屬性
1 public class HistogramView extends View{ 2 3 private Paint mPaint; 4 private Path mPath; 5 private int mTextColor,mHistogramColor; 6 7 public HistogramView(Context context, @Nullable AttributeSet attrs) { 8 super(context, attrs); 9 mPaint = new Paint(); 10 mPath = new Path(); 11 initAttrs(context,attrs); 12 } 13 14 15 private void initAttrs(Context context, AttributeSet attrs){ 16 TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.HistogramView); 17 mTextColor = typedArray.getColor(R.styleable.HistogramView_textColor,Color.BLACK); 18 mHistogramColor = typedArray.getColor(R.styleable.HistogramView_histogramColor,Color.GREEN); 19 typedArray.recycle(); 20 } 21 22 @Override 23 protected void onDraw(Canvas canvas) { 24 super.onDraw(canvas); 25 //繪製座標軸 26 mPaint.reset(); 27 mPath.reset(); 28 mPaint.setColor(Color.BLACK); 29 mPaint.setStyle(Paint.Style.STROKE); 30 mPath.moveTo(100,100); 31 mPath.rLineTo(0,402); 32 mPath.rLineTo(800,0); 33 canvas.drawPath(mPath,mPaint); 34 //繪製文字 35 mPaint.reset(); 36 mPaint.setTextSize(30); 37 mPaint.setColor(mTextColor); 38 mPaint.setStyle(Paint.Style.FILL); 39 canvas.drawText("Froyo",160,540,mPaint); 40 canvas.drawText("CB",280,540,mPaint); 41 canvas.drawText("ICS",380,540,mPaint); 42 canvas.drawText("J",480,540,mPaint); 43 canvas.drawText("KitKat",560,540,mPaint); 44 canvas.drawText("L",690,540,mPaint); 45 canvas.drawText("M",790,540,mPaint); 46 //繪製直方圖,柱形圖是用較粗的直線來實現的 47 mPaint.reset(); 48 mPaint.setColor(mHistogramColor); 49 mPaint.setStrokeWidth(80); 50 float[] lines3={ 51 200,500,200,495, 52 300,500,300,480, 53 400,500,400,480, 54 500,500,500,300, 55 600,500,600,200, 56 700,500,700,150, 57 800,500,800,350, 58 }; 59 canvas.drawLines(lines3,mPaint); 60 } 61 }
將上述程式碼和前面第三節中自繪直方圖程式碼對比,紅色部分是修改或新增的程式碼。第15~20行程式碼就是初始化屬性的地方,這個過程需要在建構函式中完成。其中,第16行是和自定義屬性集建立聯絡,第17和18行是獲取開發者在佈局檔案中使用時設定的相應屬性值,如果沒有設定,則會使用預設設定的顏色,分別為Color.BLACK和Color.GREEN。這裡注意第19行,用完後一定要回收資源。這樣就初始化了文字顏色mTextColor值和mHistogramColor值,在後面onDraw中就使用該值來繪製對應的部分。
3、在佈局檔案中設定屬性值
1 <?xml version="1.0" encoding="utf-8"?> 2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 xmlns:app="http://schemas.android.com/apk/res-auto" 4 android:layout_width="match_parent" 5 android:layout_height="match_parent"> 6 7 <com.example.demos.customviewdemo.HistogramView 8 android:layout_width="match_parent" 9 android:layout_height="wrap_content" 10 app:textColor="@android:color/holo_red_light" 11 app:histogramColor="@android:color/holo_blue_bright"/> 12 13 </RelativeLayout>
這段程式碼中,第3,10,11行和以往的佈局檔案有些不一樣,這是使用自定義屬性時的固定格式。第3行中,如果佈局檔案中沒有這一句,一定要加上,這句是宣告名稱空間,只有宣告瞭名稱空間才能使用自定義屬性。“app”是該名稱空間的名稱,這裡是自行命名的,不一定非要用“app”。第10行和11行,“app:attrName”表示用的是自定義的屬性,固定用法,前面mTextColor和mHistogramColor值就是從這裡獲取的。
還記得上一節結尾處說“android:layout_centerInParent”沒有起效嗎?現在我們知道,這裡設定的屬性,是在自定義View程式碼中獲取該值,根據該值來確定顯示效果的。“android:layout_centerInParent”的值在View的原始碼中沒有被使用,所以設定後也就無效了。“android:layout_width”和“android:layout_height”屬性是必須要有的,所有的View的實現都要用到這兩個屬性來確定寬高。現在,我們們應該明白,設定控制元件屬性值是如何起作用的了吧。
4、效果圖
五、自定義屬性格式彙總
在上面一節中,僅僅只是對文字顏色和直方圖顏色的屬性值做了設定,是為了演示自定義屬性的使用步驟。在實際開發中,完全可以定義更多型別的屬性,如顯示文字的內容,文字的大小,直方圖的寬度等。format也不只限定於“color”,還有“String”,“Integer”等,多種多樣。本節就彙總一下平時比較常用的一些屬性format。
本節主要參考瞭如下文章:【Android自定義View全解】
1、常用的11種format型別
1 <?xml version="1.0" encoding="utf-8"?> 2 <resources> 3 <declare-styleable name="SelfAttr"> 4 <!--1.reference:參考某一資源ID--> 5 <attr name="background" format="reference" /> 6 <!--2. color:顏色值--> 7 <attr name = "textColor" format = "color" /> 8 <!--3.boolean:布林值--> 9 <attr name = "focusable" format = "boolean" /> 10 <!--4.dimension:尺寸值--> 11 <attr name = "layout_width" format = "dimension" /> 12 <!--5. float:浮點值--> 13 <attr name = "fromAlpha" format = "float" /> 14 <!--6.integer:整型值--> 15 <attr name = "lines" format="integer" /> 16 <!--7.string:字串--> 17 <attr name = "text" format = "string" /> 18 <!--8.fraction:百分數--> 19 <attr name = "pivotX" format = "fraction" /> 20 <!--9.enum:列舉值。屬性值只能選擇列舉值中的一個--> 21 <attr name="orientation"> 22 <enum name="horizontal" value="0" /> 23 <enum name="vertical" value="1" /> 24 </attr> 25 <!--10.flag:位或運算。屬性值可以選擇其中多個值--> 26 <attr name="gravity"> 27 <flag name="top" value="0x01" /> 28 <flag name="bottom" value="0x02" /> 29 <flag name="left" value="0x04" /> 30 <flag name="right" value="0x08" /> 31 <flag name="center_vertical" value="0x16" /> 32 ... 33 </attr> 34 <!--11.混合型別:屬性定義時可以指定多種型別值--> 35 <attr name = "background_2" format = "reference|color" /> 36 </declare-styleable> 37 </resources>
如上列出了平時工作中在常見的11種型別的格式,說是11種,但最後一種是前面10種的組合而已。看到上述的屬性名稱應該很熟悉吧,都是系統原生控制元件的屬性名稱。
2、使用舉例
如下對上述屬性的使用一一舉例演示,可以對照著來理解,都是平時常用的系統控制元件。
1 <!--1.reference:參考某一資源ID--> 2 <ImageView android:background = "@drawable/圖片ID"/> 3 <!--2. color:顏色值--> 4 <TextView android:textColor = "#00FF00"/> 5 <!--3.boolean:布林值--> 6 <Button android:focusable = "true"/> 7 <!--4.dimension:尺寸值--> 8 <Button android:layout_width = "42dp"/> 9 <!--5. float:浮點值--> 10 <alpha android:fromAlpha = "1.0"/> 11 <!--6.integer:整型值--> 12 <TextView android:lines="1"/> 13 <!--7.string:字串--> 14 <TextView android:text = "我是文字"/> 15 <!--8.fraction:百分數--> 16 <rotate android:pivotX = "200%"/> 17 <!--9.enum:列舉值--> 18 <LinearLayout 19 android:orientation = "vertical"> 20 </LinearLayout> 21 <!--10.flag:位或運算--> 22 <TextView android:gravity="bottom|left"/> 23 <!--11.混合型別:屬性定義時可以指定多種型別值--> 24 <ImageView android:background = "@drawable/圖片ID" /> 25 <!--或者--> 26 <ImageView android:background = "#00FF00" />
結語
關於自定義View的3中實現方式以及自定義屬性的使用,這裡就講完了。讀完後,是不是發現基本的實現流程其實非常簡單呢?當然,本文為了說明實現流程,所以舉的例子都比較簡單,但不是說繪製內容也一樣簡單。就好像辦理入學手續很簡單,但讀書這件事卻不那麼容易一樣。要完成一些酷炫的自定義View,還需要好好地掌握Canvas,Paint,Path等工具的使用,以及View的繪製流程原理。當然,本文肯定有很多描述不妥或不準確的地方,歡迎來拍磚。