Android學習(十)—— Android自定義控制元件
Android自定義控制元件
安卓在使用中大多數使用已有的一些控制元件,用法比較簡單,還有一部分是比較複雜的、使用者自己想的控制元件,這些就需要進行自定義控制元件,今天就來簡單說一下自定義控制元件。
1、繪製過程
- 建立一個類,繼承View類
- onMeasure()方法,測量計算檢視的大小
- onLayout()方法,設定檢視在螢幕中顯示的位置
- onDraw()方法,繪製檢視
以上就是自定義控制元件的繪製過程。
2、主要內容解釋
- measure操作
用於計算檢視的大小,即檢視的寬度和長度。在view中定義為final型別,要求子類不能修改。measure()函式中又會呼叫下面的函式:
(1)onMeasure(),確定檢視大小,也就是說measure只是對onMeasure的一個包裝,子類可以覆寫onMeasure()方法實現自己的計算檢視大小的方式,並通過setMeasuredDimension(width, height)儲存計算結果。
(2)關於MeasureSpec:
UPSPECIFIED:父容器對於子容器沒有任何限制,子容器想要多大就多大.
EXACTLY:父容器已經為子容器設定了尺寸,子容器應當服從這些邊界,不論子容器想要多大的空間.
AT_MOST:
- layout操作
用於設定檢視在螢幕中顯示的位置。在view中定義為final型別,要求子類不能修改。layout()函式中有兩個基本操作:
(1)setFrame(l,t,r,b),l,t,r,b即子檢視在父檢視中的具體位置,該函式用於將這些引數儲存起來;
(2)onLayout(),在View中這個函式什麼都不會做,提供該函式主要是為viewGroup型別佈局子檢視用的;
- draw操作
利用前兩部得到的引數,將檢視顯示在螢幕上,到這裡也就完成了整個的檢視繪製工作。其內部定義了繪圖的基本操作:
(1)繪製背景;
(2)如果要檢視顯示漸變框,這裡會做一些前期工作;
(3)繪製檢視本身,即呼叫onDraw()函式。在view中onDraw()是個空函式,也就是說具體的檢視都要覆寫該函式來實現自己的顯示。
(4)繪製子檢視,即dispatchDraw()函式。在view中這是個空函式,具體的檢視不需要實現該方法,它是專門為容器類準備的,也就是容器類必須實現該方法;
(5)應用程式呼叫了setVerticalFadingEdge或者setHorizontalFadingEdge,如果需要可以開始繪製漸變框;
(6)繪製滾動條;
從上面可以看出自定義View需要最少覆寫onMeasure()和onDraw()兩個方法。
- 自定義View的方法
- onFinishInflate(): 回撥方法,當應用從XML載入該元件並用它構建介面之後呼叫的方法
- onMeasure():檢測View元件及其子元件的大小
- onLayout(): 當該元件需要分配其子元件的位置、大小時
- onSizeChange():當該元件的大小被改變時
- onDraw(): 當元件將要繪製它的內容時
- onKeyDown: 當按下某個鍵盤時
- onKeyUp: 當鬆開某個鍵盤時
- onTrackballEvent: 當發生軌跡球事件時
- onTouchEvent: 當發生觸屏事件時
- onWindowFocusChanged(boolean):當該元件得到、失去焦點時
- onAtrrachedToWindow():當把該元件放入到某個視窗時
- onDetachedFromWindow():當把該元件從某個視窗上分離時觸發的方法
- onWindowVisibilityChanged(int):當包含該元件的視窗的可見性發生改變時觸發的方法
3、效果圖展示
4、程式碼展示
在java程式碼中我加了很多註釋,方便進行理解、學習。
佈局檔案
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 android:id="@+id/container" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:orientation="vertical"> 6 7 <sample.sdk.qy.com.androiddemo.Customize 8 android:layout_width="match_parent" 9 android:layout_height="match_parent" 10 android:layout_margin="20dp" 11 /> 12 13 </LinearLayout>
自定義控制元件類
1 public class Customize extends View { 2 private final static String TAG = Customize.class.getSimpleName(); 3 private Paint mPaint; 4 private RectF oval; 5 6 public Customize(Context context) { 7 super(context); 8 init(); 9 } 10 11 public Customize(Context context, AttributeSet attrs) { 12 super(context, attrs); 13 init(); 14 } 15 16 public Customize(Context context, AttributeSet attrs, int defStyleAttr) { 17 super(context, attrs, defStyleAttr); 18 init(); 19 } 20 21 private void init(){ 22 mPaint = new Paint(); 23 mPaint.setAntiAlias(true); 24 oval=new RectF(); 25 } 26 @Override 27 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 28 super.onMeasure(widthMeasureSpec, heightMeasureSpec); 29 int widthMode = MeasureSpec.getMode(widthMeasureSpec); 30 int widthSize = MeasureSpec.getSize(widthMeasureSpec); 31 int heightMode = MeasureSpec.getMode(heightMeasureSpec); 32 int heightSize = MeasureSpec.getSize(heightMeasureSpec); 33 switch (widthMode) { 34 case MeasureSpec.EXACTLY: 35 break; 36 case MeasureSpec.AT_MOST: 37 break; 38 case MeasureSpec.UNSPECIFIED: 39 break; 40 } 41 } 42 43 @Override 44 protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 45 super.onLayout(changed, left, top, right, bottom); 46 47 } 48 49 @Override 50 protected void onDraw(Canvas canvas) { 51 super.onDraw(canvas); 52 //設定演顏色 53 mPaint.setColor(Color.GREEN); 54 // FILL填充, STROKE描邊,FILL_AND_STROKE填充和描邊 55 mPaint.setStyle(Paint.Style.FILL_AND_STROKE); 56 //獲取控制元件的寬度和高度 57 int with = getWidth(); 58 int height = getHeight(); 59 //設定圓的半徑 60 float radius = with / 4; 61 //畫圓,設定顏色 62 canvas.drawCircle(with / 2, with / 2, radius, mPaint); 63 mPaint.setColor(Color.BLUE); 64 //用於定義的圓弧的形狀和大小的界限 65 oval.set(with / 2 - radius, with / 2 - radius, with / 2 66 + radius, with / 2 + radius); 67 //根據進度畫圓弧 68 canvas.drawArc(oval, 270, 90, true, mPaint); 69 //畫出另一個圓弧 70 mPaint.setColor(Color.YELLOW); 71 canvas.drawArc(oval, 360, 120, true, mPaint); 72 } 73 }
MainActivity類
1 public class MainActivity extends Activity { 2 3 @Override 4 protected void onCreate(Bundle savedInstanceState) { 5 super.onCreate(savedInstanceState); 6 setContentView(R.layout.activity_main); 7 8 } 9 10 }