Androidで上下スライド効果を実現
6436 ワード
多くの場合、タッチスクリーンのFling、ScrollなどのGesture(ジェスチャー)操作を利用して操作すると、ブラウザでスクリーンをスクロールしたり、Flingでリーダーのページをめくったりするなど、アプリケーションのユーザー体験が大幅に向上します.Androidシステムではジェスチャーの認識はGestureDetector.OnGestureListenerインタフェースで実現されたが、WilliamはAndroidの公式ドキュメントをめくっても関連例が見つからず、API DemoのTouchPaintもonTouchイベントの処理に言及しただけで、ジェスチャーには触れていない.Android Developerディスカッショングループにも私と似たような問題がある人が少なくありません.彼らが言及した方法と私が行った実験を結びつけて、Androidでのジェスチャー認識の実現を簡単に説明します.まずいくつかの概念を明らかにします.まず、Androidのイベント処理メカニズムはListener(Listener)に基づいて実現されています.今日お話ししたタッチスクリーン関連のイベントよりも、onTouchListenerによって実現されています.次に、すべてのViewのサブクラスは、setOnTouchListener()、setOnKeyListener()などの方法で、あるイベントに対するリスナーを追加することができる.第三に、Listenerは一般に、onTouch()、onKey()などの操作を完了するために、1つ以上のabstract(抽象)メソッドを含むインタフェース(インタフェース)方式で提供される.このように、あるviewにイベントListenerを設定し、その抽象的な方法を実現すると、プログラムは、特定のイベントがそのviewにdispatchされたときにcallbakc関数によって適切な応答を与えることができる.簡単な例を見て、最も簡単なTextViewで説明します(実際にはADTで生成されたskeletonと何の違いもありません).
TextViewのインスタンスtvにonTouchListenerを設定したが,GestureTestクラスはOnTouchListenerインタフェースを実現しているので,簡単にthisをパラメータとして与えることができる.onTouchメソッドはOnTouchListenerの抽象的なメソッドを実現し、ここで論理コードを追加すれば、ユーザーが画面に触れるときに応答することができ、ここで行ったように、ヒント情報を出すことができます.
ここでは、ActionEventのgetAction()メソッドを使用して、ACTION_を含むTouchイベントのタイプを取得できます.DOWN, ACTION_MOVE, ACTION_UPとACTION_CANCEL.ACTION_DOWNとは、タッチパネルを押すこと、ACTION_MOVEとは、タッチパネルを押して受力点を移動すること、ACTION_UPとは、タッチパネルを離すこと、ACTION_CANCELはユーザーによって直接トリガーされません(したがって、今日の議論の範囲ではありません.ViewGroup.onInterceptTouchEvent(MotionEvent)を参照してください).ユーザの異なる操作の判断により,getRawX()やgetRawY()やgetX()やgetY()などの手法を組み合わせて座標を取得すると,あるボタンをドラッグしたりスクロールバーをドラッグしたりするなどの機能を実現できる.スタンバイではMotionEvent類の文書を見たり、TouchPaintの例を見たりすることができます.
今日お話しするポイントに戻りますが、Touch操作を捉えたとき、ユーザーのGestureをどのように認識しますか?ここにはGestureDetectorが必要です.OnGestureListenerインタフェースの助けで、私たちのGestureTestクラスはこのようになりました.
次に、onTouch()メソッドでは、GestureDetectorのonTouchEvent()メソッドを呼び出し、キャプチャされたMotionEventをGestureDetectorに渡して、ユーザのジェスチャーを処理するために適切なcallback関数があるかどうかを分析する.
次に,onFling(),onScroll(),onLongPress()の6つの抽象手法を実現した.私はすでにそれぞれの方法で代表されるジェスチャーの意味を注釈に書いていますが、見てみれば分かります.
ユーザがタッチパネルに軽く触れ、1つのMotionEvent ACTION_DOWNトリガ
ユーザーがタッチパネルを軽くタッチし、まだ離したりドラッグしたりしていないので、1つ1つのMotionEvent ACTION_DOWNトリガ注意とonDown()の違いは,緩めたりドラッグしたりしていない状態を強調する.
ユーザ(タッチパネルを軽くタッチした後)が離し、1つ1つのMotionEvent ACTION_UPトリガ
ユーザーがタッチパネルを押して、素早く移動してから離し、1つのMotionEvent ACTION_DOWN,複数ACTION_MOVE,1 ACTION_UPトリガ
ユーザがタッチパネルを長押しし、複数のMotionEvent ACTION_DOWNトリガ
ユーザーがタッチパネルを押してドラッグし、1つのMotionEvent ACTION_DOWN,複数ACTION_MOVEトリガ
onFling()イベントの処理をしてみましょう.onFling()メソッドの各パラメータの意味をコメントに書きました.注意しなければならないのはFlingイベントの処理コードの中で、Flingを最初にトリガーするACTION_を除いてDOWNと最後のACTION_MOVEに含まれる座標などの情報に加え,X軸またはY軸におけるユーザの移動速度を条件としてもよい.例えば、以下のコードでは、ユーザが100画素以上移動し、X軸上の毎秒の移動速度が200画素より大きい場合に処理を行う.
問題は、この時にプログラムを実行しようとすると、私たちが望んでいる結果が得られないことに気づき、コードの実行を追跡するとonFling()イベントがキャプチャされていないことに気づきます.これはちょうど最初に私を困らせた問題で、これはいったいどうしてですか?ディスカッショングループのGesture detectionという投稿で答えを見つけました.つまり、onCreateでtvを必要とします.setOnTouchListener(this);その後、次のコードを追加します.tv.setLongClickable(true); このようにしてこそ、viewはTapと異なるhold(すなわちACTION_MOVE、または複数のACTION_DOWN)を処理することができ、layout定義におけるandroid:longClickableによっても同様に行うことができる.今回出会ったこの問題は前回MapViewでsetOnKeyListenerが出会った問題とよく似ていますが、実はSDKに対する理解が不十分で、一度覚えておけばいいのです.しかし、Googleはドキュメントの面で確かに強化する必要があります.少なくともOnGestureListenerでジェスチャーが正しく認識されることを保証するには、それらの条件を満たす必要があることを説明することができます.
変換元:http://dev.10086.cn/cmdn/wiki/index.php?edition-view-5880-1.html
public class GestureTest extends Activity implements OnTouchListener{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// init TextView
TextView tv = (TextView) findViewById(R.id.page);
// set OnTouchListener on TextView
tv.setOnTouchListener(this);
// show some text
tv.setText(R.string.text);
}
@Override
public boolean onTouch(View v, MotionEvent event) {
Toast.makeText(this, "onTouch", Toast.LENGTH_SHORT).show();
return false;
}
TextViewのインスタンスtvにonTouchListenerを設定したが,GestureTestクラスはOnTouchListenerインタフェースを実現しているので,簡単にthisをパラメータとして与えることができる.onTouchメソッドはOnTouchListenerの抽象的なメソッドを実現し、ここで論理コードを追加すれば、ユーザーが画面に触れるときに応答することができ、ここで行ったように、ヒント情報を出すことができます.
ここでは、ActionEventのgetAction()メソッドを使用して、ACTION_を含むTouchイベントのタイプを取得できます.DOWN, ACTION_MOVE, ACTION_UPとACTION_CANCEL.ACTION_DOWNとは、タッチパネルを押すこと、ACTION_MOVEとは、タッチパネルを押して受力点を移動すること、ACTION_UPとは、タッチパネルを離すこと、ACTION_CANCELはユーザーによって直接トリガーされません(したがって、今日の議論の範囲ではありません.ViewGroup.onInterceptTouchEvent(MotionEvent)を参照してください).ユーザの異なる操作の判断により,getRawX()やgetRawY()やgetX()やgetY()などの手法を組み合わせて座標を取得すると,あるボタンをドラッグしたりスクロールバーをドラッグしたりするなどの機能を実現できる.スタンバイではMotionEvent類の文書を見たり、TouchPaintの例を見たりすることができます.
今日お話しするポイントに戻りますが、Touch操作を捉えたとき、ユーザーのGestureをどのように認識しますか?ここにはGestureDetectorが必要です.OnGestureListenerインタフェースの助けで、私たちのGestureTestクラスはこのようになりました.
public class GestureTest extends Activity implements OnTouchListener,
OnGestureListener {
....
}
次に、onTouch()メソッドでは、GestureDetectorのonTouchEvent()メソッドを呼び出し、キャプチャされたMotionEventをGestureDetectorに渡して、ユーザのジェスチャーを処理するために適切なcallback関数があるかどうかを分析する.
public boolean onTouch(View v, MotionEvent event) {
// OnGestureListener will analyzes the given motion event
return mGestureDetector.onTouchEvent(event);
}
次に,onFling(),onScroll(),onLongPress()の6つの抽象手法を実現した.私はすでにそれぞれの方法で代表されるジェスチャーの意味を注釈に書いていますが、見てみれば分かります.
ユーザがタッチパネルに軽く触れ、1つのMotionEvent ACTION_DOWNトリガ
@Override
public boolean onDown(MotionEvent e) {
// TODO Auto-generated method stub
Toast.makeText(this, "onDown", Toast.LENGTH_SHORT).show();
return false;
}
ユーザーがタッチパネルを軽くタッチし、まだ離したりドラッグしたりしていないので、1つ1つのMotionEvent ACTION_DOWNトリガ注意とonDown()の違いは,緩めたりドラッグしたりしていない状態を強調する.
@Override
public void onShowPress(MotionEvent e) {
// TODO Auto-generated method stub
}
ユーザ(タッチパネルを軽くタッチした後)が離し、1つ1つのMotionEvent ACTION_UPトリガ
@Override
public boolean onSingleTapUp(MotionEvent e) {
// TODO Auto-generated method stub
return false;
}
ユーザーがタッチパネルを押して、素早く移動してから離し、1つのMotionEvent ACTION_DOWN,複数ACTION_MOVE,1 ACTION_UPトリガ
@Override
public boolean onSingleTapUp(MotionEvent e) {
// TODO Auto-generated method stub
return false;
}
ユーザがタッチパネルを長押しし、複数のMotionEvent ACTION_DOWNトリガ
@Override
public void onLongPress(MotionEvent e) {
// TODO Auto-generated method stub
}
ユーザーがタッチパネルを押してドラッグし、1つのMotionEvent ACTION_DOWN,複数ACTION_MOVEトリガ
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
// TODO Auto-generated method stub
return false;
}
onFling()イベントの処理をしてみましょう.onFling()メソッドの各パラメータの意味をコメントに書きました.注意しなければならないのはFlingイベントの処理コードの中で、Flingを最初にトリガーするACTION_を除いてDOWNと最後のACTION_MOVEに含まれる座標などの情報に加え,X軸またはY軸におけるユーザの移動速度を条件としてもよい.例えば、以下のコードでは、ユーザが100画素以上移動し、X軸上の毎秒の移動速度が200画素より大きい場合に処理を行う.
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
// :
// e1: 1 ACTION_DOWN MotionEvent
// e2: ACTION_MOVE MotionEvent
// velocityX:X , /
// velocityY:Y , /
// :
// X FLING_MIN_DISTANCE, FLING_MIN_VELOCITY /
if (e1.getX() - e2.getX() > FLING_MIN_DISTANCE
&& Math.abs(velocityX) > FLING_MIN_VELOCITY) {
// Fling left
Toast.makeText(this, "Fling Left", Toast.LENGTH_SHORT).show();
} else
if (e2.getX() - e1.getX() > FLING_MIN_DISTANCE
&& Math.abs(velocityX) > FLING_MIN_VELOCITY) {
// Fling right
Toast.makeText(this, "Fling Right", Toast.LENGTH_SHORT).show();
}
return false;
}
問題は、この時にプログラムを実行しようとすると、私たちが望んでいる結果が得られないことに気づき、コードの実行を追跡するとonFling()イベントがキャプチャされていないことに気づきます.これはちょうど最初に私を困らせた問題で、これはいったいどうしてですか?ディスカッショングループのGesture detectionという投稿で答えを見つけました.つまり、onCreateでtvを必要とします.setOnTouchListener(this);その後、次のコードを追加します.tv.setLongClickable(true); このようにしてこそ、viewはTapと異なるhold(すなわちACTION_MOVE、または複数のACTION_DOWN)を処理することができ、layout定義におけるandroid:longClickableによっても同様に行うことができる.今回出会ったこの問題は前回MapViewでsetOnKeyListenerが出会った問題とよく似ていますが、実はSDKに対する理解が不十分で、一度覚えておけばいいのです.しかし、Googleはドキュメントの面で確かに強化する必要があります.少なくともOnGestureListenerでジェスチャーが正しく認識されることを保証するには、それらの条件を満たす必要があることを説明することができます.
変換元:http://dev.10086.cn/cmdn/wiki/index.php?edition-view-5880-1.html