標籤:
- Android自訂view通過繼承系統的View並重寫部分方法來滿足自己的特定需要。首先我們來看一下都有哪些方法可能需要被重寫:
onMeasure() 檢測View組件及其子組件的大小 onLayout() 當該組件需要分配其子組件的位置、大小時 onTouchEvent 當發生觸屏事件時 onDraw() 當組件將要繪製它的內容時 onKeyDown 當按下某個鍵盤時 onKeyUp 當鬆開某個鍵盤時 onTrackballEvent 當發生軌跡球事件時 onSizeChange() 當該組件的大小被改變時 onFinishInflate() 回調方法,當應用從XML載入該組件並用它構建介面之後調用的方法 onWindowFocusChanged(boolean) 當該組件得到、失去焦點時 onAtrrachedToWindow() 當把該組件放入到某個視窗時 onDetachedFromWindow() 當把該組件從某個視窗上分離時觸發的方法 onWindowVisibilityChanged(int): 當包含該組件的視窗的可見度發生改變時觸發的方法 紅色標註的部分是我們經常需要重寫的函數。具體的實現我們舉一個簡單的例子來說明,首先上: 圓形和文字跟隨觸摸事件移動的一個簡單的自訂view
- 實現上面的效果我們大致需要分成這幾步
- 在res/values/ 下建立一個attrs.xml 來聲明自訂view的屬性
- 一個繼承View並複寫部分函數的自訂view的類
- 一個展示自訂view 的容器介面
- 我們的view 叫做myView,一定要和我們的class檔案名稱相同。它有一個屬性值,格式為color
<?xml version="1.0" encoding="utf-8"?><resources> <declare-styleable name="myView"> <attr name="TextColor" format="color"/> </declare-styleable> </resources>
2.在自訂view類中實現其建構函式(用於初始獲得view的屬性配置)和複寫onDraw和onTouchEvent。
public class myView extends View{ //定義畫筆和初始位置 Paint p = new Paint(); public float currentX = 50; public float currentY = 50; public int textColor; public myView(Context context, AttributeSet attrs) { super(context, attrs); //擷取資源檔裡面的屬性,由於這裡只有一個屬性值,不用遍曆數組,直接通過R檔案拿出color值 //把屬性放在資源檔裡,方便設定和複用 TypedArray array = context.obtainStyledAttributes(attrs,R.styleable.myView); textColor = array.getColor(R.styleable.myView_TextColor,Color.BLACK); array.recycle(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //畫一個藍色的圓形 p.setColor(Color.BLUE); canvas.drawCircle(currentX,currentY,30,p); //設定文字和顏色,這裡的顏色是資源檔values裡面的值 p.setColor(textColor); canvas.drawText("BY finch",currentX-30,currentY+50,p); } @Override public boolean onTouchEvent(MotionEvent event) { currentX = event.getX(); currentY = event.getY(); invalidate();//重新繪製圖形 return true; }}
這裡思路很簡單,通過不斷的更新當前位置座標和重新繪製圖形實現效果,要注意的是使用TypedArray後一定要記得recycle(),否則會對下次調用產生影響。
除非你不會再用TypedArray.
3.我們把myView放在activity_main.xml裡面,當然也可以在代碼中通過addview函數加到布局中。
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:myview="http://schemas.android.com/apk/res-auto" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="finch.scu.cn.myview.MainActivity"> <finch.scu.cn.myview.myView android:layout_width="match_parent" android:layout_height="match_parent" myview:TextColor="#ff0000" /></RelativeLayout>
這裡 xmlns:自訂控制項的首碼="http://schemas.android.com/apk/res/包名(或res-auto)" , 首碼:TextColor="#ff0000"。如果不申明命名空間屬性就會
最後是MainActivity
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); }}
- 具體的view要根據具體的需求來,比如我們要側滑刪除的listview我們可以繼承listview,監聽側滑事件,顯示刪除按鈕實現功能。
Android 自訂控制項(view)的簡單例子