goo blog サービス終了のお知らせ 

marunomaruno-memo

marunomaruno-memo

[Android] グラフィックス (2) 指を追うように円を動かす - タッチ・イベント

2012年01月19日 | Android
[Android] グラフィックス (2) 指を追うように円を動かす - タッチ・イベント
================================================================================

画面に描いた円が、タッチした指を追って動くように描画するサンプル。
タッチしたことに対して、何か処理を行うので、タッチ・イベントに対するハンドラーを
つくる。ハンドラーは、View クラスの onTouchEvent() メソッドをオーバーライドする。

アクティビティや、レイアウト(res/layout/main.xml) は、前回と同じである。
グラフィックス (1)
http://blog.goo.ne.jp/marunomarunogoo/d/20111016


◆ 描画関係のクラス

□ GraphicsView.java
---
package jp.marunomaruno.android.graphics;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.util.AttributeSet;
import android.view.Display;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;

/**
 * 指を追うように円動かす。
 * @author marunomaruno
 * @see Graphics04Activity
 */
public class GraphicsView extends View {

    private Paint paint;
    private float cx;    // 図形を描画する X 座標    // (1)
    private float cy;    // 図形を描画する Y 座標    // (2)
    private float radius;    // 円の半径    // (3)

    public GraphicsView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initialize();
    }

    public GraphicsView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initialize();
    }

    public GraphicsView(Context context) {
        super(context);
        initialize();
    }

    private void initialize() {
        // ペイントオブジェクトを設定する
        paint = new Paint();
        paint.setAntiAlias(true);
        paint.setColor(Color.BLUE);    // (4)
        paint.setStyle(Style.FILL);    // (5)

        // 丸を描画する初期値を設定する
        cx = 100;
        cy = 200;
        radius = 50;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        // 格子を描画する
        drawGrid(canvas, 50);    

        // 円を描画する
        canvas.drawCircle(cx, cy, radius, paint);    // (6)
    }
    
    @Override
    public boolean onTouchEvent(MotionEvent event) {    // (7)
        switch (event.getAction()) {
        
        case MotionEvent.ACTION_DOWN:    // 指をタッチした    // (8)
            assert true;    // 何もしない
            break;

        case MotionEvent.ACTION_MOVE:    // 指を動かしている    // (9)
            cx = event.getX();    // (10)
            cy = event.getY();    // (11)
            break;

        case MotionEvent.ACTION_UP:        // 指を離した    // (12)
            assert true;    // 何もしない
            break;

        default:
            assert true;    // 何もしない
            break;
        }
        
        invalidate();    // (13)

        return true;    // (14)
    }

    /**
     * 画面に格子を描画する。
     * @param canvas
     * @param interval 格子を描く間隔
     */
    private void drawGrid(final Canvas canvas, int interval) {
        // 画面のサイズを取得する
        WindowManager manager = (WindowManager) getContext().getSystemService(
                Context.WINDOW_SERVICE);
        Display display = manager.getDefaultDisplay();
        int width = display.getWidth();
        int height = display.getHeight();

        // 格子を描画する
        Paint paint = new Paint();        // (15)
        paint.setColor(Color.WHITE);
        paint.setStrokeWidth(1);
        for (int i = 0; i < Math.max(width, height); i += interval) {
            canvas.drawText(Integer.toString(i), i, paint.getTextSize(), paint);
            canvas.drawLine(i, 0, i, height, paint);
            canvas.drawText(Integer.toString(i), 0, i, paint);
            canvas.drawLine(0, i, width, i, paint);
        }
    }
}
---

(1)(2) 図形を描画する座標の保持

onTouchEvent() で取得した座標を、onDraw() メソッドで使うので、インスタンス変数に
しておく。

    private float cx;    // 図形を描画する X 座標    // (1)
    private float cy;    // 図形を描画する Y 座標    // (2)


(3) 円の半径

    private float radius;    // 円の半径    // (3)

ただし、これはプログラム中で変更しないのであれば、定数でもよい。


(4)(5) ペイントオブジェクトを設定する

今回は、色を青、円の中は塗りつぶすことにする。

    paint.setColor(Color.BLUE);    // (4)
    paint.setStyle(Style.FILL);    // (5)


(6) 円を描画する

drawCircle() メソッドを使って円を描く。

    canvas.drawCircle(cx, cy, radius, paint);    // (6)


(7) タッチイベントのハンドラー・メソッド

View クラスの次のメソッドをオーバーライドする。

    public boolean onTouchEvent(MotionEvent event) {    // (7)

引数は MotionEvent オブジェクト。
返り値は、イベントの処理が終わった(true)か終わっていないか(false)。


・MotionEvent クラス

指やマウス、ペン、トラックボールの動きのイベント。

java.lang.Object
   +     android.view.InputEvent
         +     android.view.MotionEvent

・Action 関係で、指の動き関係(と思われる)の定数
---
int  ACTION_DOWN  タッチしたとき(指をつけたとき)
int  ACTION_MOVE  指を動かしているとき(ACTION_DOWN と ACTION_UP の間)
int  ACTION_UP    指を離したとき
---

・主なメソッド
---
final int    getAction()
final int    getPointerCount()                
final int    getPointerId(int pointerIndex)
final float  getX(int pointerIndex)
final float  getY(int pointerIndex)
final float  getY()
---


(8)(9)(12) アクションによる処理

上記 getAction() メソッドにより、どのアクションかを取得した後、アクションごとに
そのアクションに対する処理をケースわけしていく。

    case MotionEvent.ACTION_DOWN:    // 指をタッチした    // (8)
    case MotionEvent.ACTION_MOVE:    // 指を動かしている    // (9)
    case MotionEvent.ACTION_UP:        // 指を離した    // (12)


(10)(11) 指を動かしているときに、その位置の座標を取得する

タッチしている位置は、event オブジェクトの getX()、getY() メソッドを使って取得す
る。

    cx = event.getX();    // (10)
    cy = event.getY();    // (11)


(13) 再描画

ビュー全体を一度無効にすることで、再描画する。

    invalidate();    // (13)

・View クラスのオーバーロードされている invalidate() メソッド
---
void  invalidate(Rect dirty)
void  invalidate(int l, int t, int r, int b)
void  invalidate()
void  invalidateDrawable(Drawable drawable)
---


(14) アクションは処理済とする

    return true;    // (14)

この返り値が false のままだと、未処理となるので、つぎのイベントを拾えない。
今回は、MotionEvent を拾うハンドラーは、このメソッドなので、true にしておく。


(15) 格子描画用のペイント・オブジェクト

格子に使う使う色や線の太さなど、描きたい図形と違う場合があるので、格子用のペイン
ト・オブジェクトを作っておく。

    Paint paint = new Paint();        // (15)



最新の画像もっと見る

コメントを投稿

サービス終了に伴い、10月1日にコメント投稿機能を終了させていただく予定です。