2011年7月26日火曜日

続・フリック

開発環境:
Windows Vista Home
eclipse 3.5(ガリレオ)
ADT_今日の時点で最新の物(バージョン不明)
JavaSDK 1.6.0_24
AndroidSDK_r11
開発・ターゲットVer=Android2.1


テスト環境:
媒体 = エミュレータ
↑SDK ManagerでVer2.1のHVGAで作成


フリックした時に特定のオブジェクト(部品)だけ反応して欲しい。

しかし、今の作りだとどこを押しても「onTouchEvent」が走ってしまう。


private GestureDetector mDetector;

public void onCreate(Bundle savedInstanceState) {
    mDetector = new GestureDetector(MyActivity.this, MyActivity.this);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    super.onTouchEvent(event);
    mDetector.onTouchEvent(event);
    return true;
}

@Override
public boolean onFling(MotionEvent e0, MotionEvent e1,
                        float velocityX, float velocityY)
{
    // 右方向へフリック
    if (e0.getX() < e1.getX()) {
        // 処理
    }
}


タッチした対象オブジェクトを知りたい場合どうすればいいのか。

そもそも、フリックは「GestureDetector」と「onTouchEvent」と「onFling」を使っているが、これを使い続けた場合タッチされたオブジェクトの特定は出来ないかもしれない。

そこで、オブジェクトごとにタッチイベントを捕らえる事にした。


public class MyActivity extends Activity implements OnTouchListener{

    private TextView mTvView;
    private GestureDetector mDetector;

    public void onCreate(Bundle savedInstanceState) {
        mTvView = (TextView)findViewById(R.id.tvMenu);
        // クリックリスナー登録
        mTvView.setOnTouchListener(this);
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        // 処理
        return mDetector.onTouchEvent(event);
    }

    @Override
    public boolean onFling(MotionEvent e0, MotionEvent e1,
                            float velocityX, float velocityY)
    {
        // 右方向へフリック
        if (e0.getX() < e1.getX()) {
            // 処理
        }
    }
}


「onTouch」の引数にViewが渡ってくるし、フリックしたいオブジェクトだけ「setOnTouchListener」すればいい。

これで「onFling」を引き続き使えると思っていたら、ScrollViewに対してはタッチイベントは来る物の、フリックイベントは走らない。

原因不明。

なので、「onFling」は使うのをやめて「onTouch」で泥臭いコードを書く事にする。


private float lastTouchX;
private float currentX;

@Override
public boolean onTouch(View v, MotionEvent event) {
    switch (event.getAction()) {

    case MotionEvent.ACTION_DOWN:
        lastTouchX = event.getX();
        break;

    case MotionEvent.ACTION_UP:
        currentX = event.getX();
        if (lastTouchX < currentX) {
            //前に戻る動作
        }
        if (lastTouchX > currentX) {
            //次に移動する動作
        }
        break;

    case MotionEvent.ACTION_CANCEL:
        currentX = event.getX();
        if (lastTouchX < currentX) {
             //前に戻る動作
        }
        if (lastTouchX > currentX) {
             //次に移動する動作
        }
        break;
    }
    return false;
}

ちなみに、 event.getX()は相対座標が帰ってくる。

部品の上でタッチしたらその部品の座標が帰ってくる。
ボタンの上でタッチしたらボタンのX座標が帰ってくるが、押したまま移動(MOVE)させるとボタンから指がはずれて、スクリーン全体の座標が取れるようになる。

タッチダウン → ムーブ で指を動かしている最中に突然、おかしな値が取れるように見える。

タッチした部品の座標ではなく、常にスクリーンの絶対座標が取得したい場合は、event.getRawX()」で取得できる。
 

   ↓クリックで、このブログの評価が上がり執筆者が喜びます
にほんブログ村 IT技術ブログ プログラム・プログラマーへ
   にほんブログ村

0 件のコメント: