1. 程式人生 > >Android開發中自定義檢視

Android開發中自定義檢視

很多時候,Android自身提供給我們的檢視可能不能滿足我們的需求,這個時候我們就需要 自定義檢視
雖然自定義檢視很多,但總體歸為兩個類別:

  1. 簡單檢視 。簡單檢視內部當然也可以很複雜,之所以稱之為簡單檢視是因為,簡單檢視中不包括子檢視。簡單檢視幾乎總是用來處理定製繪製。
  2. 聚合檢視 。聚合檢視一般包括很多個子檢視,在聚合檢視中一般不處理繪製事件,而是對子檢視進行管理,繪製的任務一般都是有子檢視來完成。

一般來說,自定義檢視一般可以分為兩步來完成。

  1. 選擇合適的父類。 一般來說,如果我們想在某個控制元件的基礎上進行延伸,一般選擇該控制元件為父類進行自定義檢視。如果我們向更加自由一下,那我們一般選擇 View
    作為我們的父類,繼承View 相當於我們在一張空白的畫紙上作畫,所以更加自由,所以這種方法用的最多。
  2. 覆蓋那些我們需要使用到的方法,在其中完成繪圖操作。

接下來就開始我們的工作。
先新建一個 繼承自 ViewDrawingView 的類,並覆蓋 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);
        }
    }

    ...
}

修改之後再次執行,效果如下:

到此,我們自定義檢視簡單的探究就完成了。。。。

PS:開發了一個製作個性二維碼的應用,有興趣的朋友可以試一試~ 創意二維碼製作