Android開發中自定義檢視
很多時候,Android自身提供給我們的檢視可能不能滿足我們的需求,這個時候我們就需要 自定義檢視 。
雖然自定義檢視很多,但總體歸為兩個類別:
- 簡單檢視 。簡單檢視內部當然也可以很複雜,之所以稱之為簡單檢視是因為,簡單檢視中不包括子檢視。簡單檢視幾乎總是用來處理定製繪製。
- 聚合檢視 。聚合檢視一般包括很多個子檢視,在聚合檢視中一般不處理繪製事件,而是對子檢視進行管理,繪製的任務一般都是有子檢視來完成。
一般來說,自定義檢視一般可以分為兩步來完成。
- 選擇合適的父類。 一般來說,如果我們想在某個控制元件的基礎上進行延伸,一般選擇該控制元件為父類進行自定義檢視。如果我們向更加自由一下,那我們一般選擇
View
View
相當於我們在一張空白的畫紙上作畫,所以更加自由,所以這種方法用的最多。 - 覆蓋那些我們需要使用到的方法,在其中完成繪圖操作。
接下來就開始我們的工作。
先新建一個 繼承自 View
的 DrawingView
的類,並覆蓋 View
的構造方法和 onDraw
方法。
package com.tobetheonlyone.startandroid;
import android.content.Context;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
/**
* Created by ToBeTheOnlyOne on 2018/2/10.
*/
public class DrawingView extends View {
public DrawingView1(Context context, AttributeSet attrs){
super(context,attrs);
}
@Override
protected void onDraw(Canvas canvas){
}
}
先在 onDraw
方法中在繪製檢視顏色為0xffdfdada
100
的圓。
@Override
protected void onDraw(Canvas canvas){
//繪製背景
canvas.drawColor(0xffdfdada);
//畫筆的初始化
Paint drawPaint = new Paint();
drawPaint.setColor(0xffff0000);
//繪製圓形,前兩個引數為圓點位置,第三個引數為圓的半徑,第四個為使用的畫筆
canvas.drawCircle(getWidth()/2,getHeight()/2,100,drawPaint);
}
執行效果如下:
現在基本的步驟我們都知道了,那如果我們自定義的檢視要和使用者互動該怎麼辦呢?其實也很簡單,只要我們重寫父類的 onTouchEvent
方法就可以,如下:
public class DrawingView extends View {
private final static String TAG = "DrawingView";
...
@Override
public boolean onTouchEvent(MotionEvent event) {
String action = " ";
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
action = "ACTION_DOWN";
break;
case MotionEvent.ACTION_UP:
action = "ACTION_UP";
break;
case MotionEvent.ACTION_MOVE:
action = "ACTION_MOVE";
break;
case MotionEvent.ACTION_CANCEL:
action = "ACTION_CANCEL";
break;
}
Log.w(TAG,action);
return true;
}
}
在 onTouchEvent
方法中我們對四個觸控動作進行了處理,即 ACTION_DOWN
, ACTION_UP
, ACTION_MOVE
, ACTION_CANCEL
這四個動作。這四個動作所處事件的階段如下:
- ACTION_DOWN 手指觸控到螢幕
- ACTION_UP 手指離開螢幕
- ACTION_MOVE 手指在螢幕上移動
- ACTION_CANCEL 父檢視攔截了觸控事件
再次執行專案,我們手指在螢幕上點選移動就可以在控制檯看到響應事件。
接下來我們來實現一個簡單的互動,即使用者手指在螢幕上移動,DrawingView
在使用者手指移動的區域畫一個正方形。
首先,要知道定義矩形框的兩個座標點 : 原始座標點(即手指的初始位置),當前座標點(即手指當前的位置)。
因此,我們來新建一個 Rectangle 的類來儲存我們矩形的屬性:
Rectangle.class
public class Rectangle {
private PointF mOriginPoint;
private PointF mCurrentPoint;
public Rectangle(PointF origin){
mOriginPoint = origin;
mCurrentPoint = origin;
}
public PointF getCurrentPoint(){
return mCurrentPoint;
}
public void setCurrentPoint(PointF currentPoint){
mCurrentPoint = currentPoint;
}
public PointF getOriginPoint(){
return mOriginPoint;
}
}
修改我們的DrawingView
:
DrawingView.class
public class DrawingView extends View {
private Paint drawPaint;
private Rectangle mCurrentRect;
private List<Rectangle> mRectangleList = new ArrayList<>();
public DrawingView(Context context, AttributeSet attrs){
super(context,attrs);
//畫筆的初始化
drawPaint = new Paint();
drawPaint.setColor(0x22ff0000);
}
@Override
protected void onDraw(Canvas canvas){
//繪製背景
canvas.drawColor(0xffdfdada);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
PointF current = new PointF(event.getX(),event.getY());
String action = " ";
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
action = "ACTION_DOWN";
mCurrentRect = new Rectangle(current);
mRectangleList.add(mCurrentRect);
break;
case MotionEvent.ACTION_UP:
action = "ACTION_UP";
mCurrentRect = null;
break;
case MotionEvent.ACTION_MOVE:
action = "ACTION_MOVE";
if(mCurrentRect!=null){
mCurrentRect.setCurrentPoint(current);
invalidate();
}
break;
case MotionEvent.ACTION_CANCEL:
action = "ACTION_CANCEL";
mCurrentRect = null;
break;
}
Log.w("DrawingView",action);
return true;
}
}
修改之後,無論在任何時候,檢視接受到 ACTION_DOWN
動作事件,就以手指按下的點新建 Rectangle
物件並賦值給 mCurrentRect
,然後再將該物件新增到矩形框的列表中。
當用戶手指在螢幕上移動時,會將手指所在的位置更新給 mCurrentRect.mCurrentPoint
,同時呼叫 invalidate()
方法強制 DrawingView
重新繪製自己,這樣使用者在螢幕上移動時就可以看到矩形框。
當取消觸控事件或者使用者手指離開螢幕的時候,清空 mCurrentRect
以結束螢幕的繪製。
這些工作完成之後,執行專案,發現並沒有出現繪製。這是因為我們並沒有在 onDraw
方法中進行繪製,修改 onDraw
方法:
public class DrawingView extends View {
...
@Override
protected void onDraw(Canvas canvas){
//繪製背景
canvas.drawColor(0xffdfdada);
//繪製圓形
canvas.drawCircle(getWidth()/2,getHeight()/2,100,drawPaint);
for(Rectangle rectangle:mRectangleList){
float left = Math.min(rectangle.getOriginPoint().x,rectangle.getCurrentPoint().x);
float right = Math.max(rectangle.getOriginPoint().x,rectangle.getCurrentPoint().x);
float top = Math.min(rectangle.getOriginPoint().y,rectangle.getCurrentPoint().y);
float bottom = Math.max(rectangle.getOriginPoint().y,rectangle.getCurrentPoint().y);
canvas.drawRect(left,top,right,bottom,drawPaint);
}
}
...
}
修改之後再次執行,效果如下:
到此,我們自定義檢視簡單的探究就完成了。。。。