Android中的自定義視圖

   一般在繪製圖形界面時,我們用到的是配置文件中的視圖,那麼我們能不能定義自己需要的視圖呢?答案當然是可以的,我們可以利用畫筆在畫布上自己繪製自己需要的視圖,在界面中引用過即可。然而,象畫圖這樣的操作,我們不建議放在主UI線程中使用,我們可以利用繼承自SurfaceView或者繼承自View的方式去實現,我們具體來看一下吧。

   一:繼承自View完成自定義視圖

   自定義視圖無疑就是繪製自己想要的視圖樣式,引用到工程中的過程。先來看看,如何自定義視圖?

   1:自定義繼承自View的類,用來完成繪製。

   (1)添加構造方法,在構造方法中實例化畫筆,爲畫筆設置顏色

   (2)重寫onDraw方法:參數爲畫布,可以設置畫布的背景色,完成圖形的繪製等

//自定義視圖繼承自View
public class MyView extends View{
    private Paint paint;//聲明畫筆
    public MyView(Context context) {
        super(context);
        paint = new Paint();//實例化畫筆
        paint.setColor(Color.GREEN);//設置畫筆的顏色
    }
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(Color.WHITE);//設置畫布的背景色
        //繪製矩形,參數(起始點x座標,起始點y座標,寬度,高度,畫筆對象)
        canvas.drawRect(10, 10, 100, 100, paint);
    }
}

   2:在主界面的onCreate方法中引入自定義的視圖對象

setContentView(new MyView(this));

   3:結果:在主界面上繪製出了自定義的視圖樣式,如下

   二:應用繼承自View實現矩形塊的”一定一動“

   1:添加構造方法,完成畫筆的初始化與屬性的設置

public MyRect(Context context) {
        super(context);
        paint.setColor(Color.GREEN);
    }

   2:繼承自View的類中的onDraw方法中,實現矩形的繪製

private float x = 0;// 起始x,y座標
    private float y = 0;
    private float speedx = 50;// 矩形的寬與高
    private float speedy = 50;
    private float addy = 2;// 每次移動時,x,y的增量值
    private float addx = 2;
    // 設置畫布的背景色
        canvas.drawColor(Color.WHITE);
        // 矩形的繪製
        canvas.drawRect(x, y, x + speedx, y + speedy, paint);
        y += addy;// y座標值得變化
        if (y < 0) {// 若y的上邊界超出了正值的範圍,跑到了手機屏幕的上方
            addy = Math.abs(addy);// 則讓他的增量值爲+,向下跑
        }
        if (y > getHeight() - speedy) {// 如果y的下邊界超出了屏幕範圍
            addy = -Math.abs(addy);// 則讓他的增量值爲負,向上跑
        }
        x += addx;// x座標值得變化
        if (x < 0) {// 若x的左邊界超出了正值的範圍,跑到了手機屏幕的左方
            addx = Math.abs(addx);
        }
        if (x > getWidth() - speedx) {// 如果x的右邊界超出了屏幕範圍
            addx = -Math.abs(addx);// 則讓他的增量值爲負,向左跑
        }

3:創建Handler對象,實現Handler對象,在其中的handleMessage方法中實現重繪

private Handler handler = new Handler() {
        public void handleMessage(android.os.Message msg) {
            invalidate();// 重畫
        };
    };

   4:添加計時器的啓動與終止方法,在啓動計時器中添加handler發送消息的方法

// 計時器的啓動
    public void startTimer() {
        timer = new Timer();
        task = new TimerTask() {
            @Override
            public void run() {
                // 發送消息
                handler.sendEmptyMessage(0);
            }
        };
        // 啓動計時器
        timer.schedule(task, 100, 10);
    }
    // 終止計時器
    public void stopTimer() {
        timer.cancel();
    }

   5:主界面中,對自定義視圖添加OnTouchListener監聽,根據觸發的動作,實現”一定一動“的效果

public class MainActivity extends Activity implements OnTouchListener {
    private MyRect myRect;// 聲明自定義視圖
    private int flag = 0;// 標誌
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        myRect = new MyRect(this);// 實例化自定義視圖
        setContentView(myRect);// 添加視圖
        myRect.setOnTouchListener(this);// 加載監聽
    }
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:// 是不是按下操作
            if (flag == 0) {// 若是第一次單擊
                myRect.startTimer();// 啓動,讓他走
                flag = 1;// 更改標誌
            }else if(flag==1){//若再次單擊
                myRect.stopTimer();//則停止,不讓他動
                flag=0;//修改標誌
            }
            break;
        }
        return true;//注意,只有true的時候纔會觸發
    }
}

   6:結果:通過這種方法,實現矩形“一定一動”效果。可以自行試試。

   三:繼承自SurfaceView實現的自定義視圖

   普通的繪製靜態圖形的操作還好,但是如果繪製動態或者更耗時的操作時,我們並不建議將他們直接放置在主UI線程中,我們繼承自SurfaceView就是自己創建了一個線程,在這個線程中去完成操作,顯得更好一些。

   應用:我們利用這種方法實現矩形的自由移動。

   1:繼承自SurfaceView,並實現SurfaceHolder.Callback接口,重寫其中的三個方法

public class MySurface extends SurfaceView implements SurfaceHolder.Callback

   (1)surfaceCreated方法:當SurfaceView第一次創建時觸發的方法,主要完成初始化的工作,一搬不要在這裏完成繪製的操作

   (2)surfaceChanged方法:當Surface的狀態發生變化時,觸發的方法

   (3)surfaceDestoryed方法:當Surface銷燬前觸發的狀態,用於清理資源。

   2:添加構造方法,實現畫筆的初始化及屬性設置,並添加回調

public MySurface(Context context) {
        super(context);
        paint.setColor(Color.GREEN);//畫筆的顏色設置
        getHolder().addCallback(this);//添加回調
    }

   3:自定義繪圖方法,完成矩形的繪製

private float x=0;//起始x,y座標
    private float y=0;
    private float speedx=50;//矩形的寬與高
    private float speedy=50;
    private float addy = 2;//每次移動時,x,y的增量值
    private float addx=2;
    public void draw(){
        //鎖定畫布,所有的繪圖操作,都要在鎖定於解鎖之間完成,否則出錯
        Canvas canvas=  getHolder().lockCanvas();
        //設置畫布的背景色
        canvas.drawColor(Color.WHITE);
        //矩形的繪製
        canvas.drawRect(x, y, x+speedx, y+speedy,paint);
        y +=addy;//y座標值得變化
        if(y<0){//若y的上邊界超出了正值的範圍,跑到了手機屏幕的上方
            addy = Math.abs(addy);//則讓他的增量值爲+,向下跑
        }
        if(y>getHeight()-speedy){//如果y的下邊界超出了屏幕範圍
            addy = -Math.abs(addy);//則讓他的增量值爲負,向上跑
        }
        x +=addx;//x座標值得變化
        if(x<0){//若x的左邊界超出了正值的範圍,跑到了手機屏幕的左方
            addx = Math.abs(addx);
        }
        if(x>getWidth()-speedx){//如果x的右邊界超出了屏幕範圍
            addx = -Math.abs(addx);//則讓他的增量值爲負,向左跑
        }
        //解鎖畫布
        getHolder().unlockCanvasAndPost(canvas);
    }

   4:自定義定時器的啓動與暫停,並在計時器中調用繪圖方法

//計時器的啓動
    public void startTImer(){
        timer = new Timer();//實例化計時器
        task = new TimerTask() {
                                                                                                                                                                                                                                                
            @Override
            public void run() {
                draw();//調用繪圖方法
            }
        };
        //啓動計時器
        timer.schedule(task, 100,10);
    }
    //停止計時器
    public void stopTimer(){
        timer.cancel();
    }

   5:將啓動計時器,關閉計時器的方法的引用添加到接口中重寫的三個方法中(注意引用的位置)

// 調用啓動計時器的方法
    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {
        startTImer();
    }
    @Override
    public void surfaceCreated(SurfaceHolder holder) {
    }
    // 調用終止計時器的方法
    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        stopTimer();
    }

   6:結果:實現了綠色矩形塊在屏幕範圍內的自由移動。

   自定義視圖很有用處,我們得熟記於心哦。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章