最後更新:2012-03-20html
參考自:《Android移動開發一本就夠》java
說在前面,很早時,android就開始有支持單點手勢(單點觸控),到android2.2開始支持多點觸控.android
不一樣的動做序列合起來表示不一樣的手勢。好比Fling手勢包括三個過程:將手指按觸在屏幕上,而後快速掃過,最後api
擡起手指,而且在擡起手指仍然在運動(也就是說擡起手指前,運動的速度並不會減小).每個步操做都會觸發相應的事件。app
在View控件內,開發人員能夠像處理普通的單擊事件時使用setOnClickListener()和setOnLongClickListener()ide
方法同樣處理手勢。onTouchEvent()回調方法用於探測View區域內的用戶動做。學習
onTouchEvent()回調方法只接收一個參數。MotionEvent對象。MotionEvent對象包含在View內觸發的全部類型動做動畫
的細節,經過收集和分析連續的MotionEvent對象,開發人員能夠肯定產生了何種手勢。你可使用MotionEvent數據this
來識別的探測任何你能想像的手勢。不過你也可使用Android SDK 內置的手勢探測器來探測普通的用戶動做。idea
android目前擁有兩個不一樣的類用於手勢探測。
(1) GestureDetector類能夠用於探測通常的單點觸控手勢。
(2) ScaleGestureDetector能夠用來探測多點縮放操做手勢。
除了普通的方向性手勢,你還可使用API level 4中引入的android.gesture包中的GestureOverlayView來識別命令手勢。
下面主要是處理普通單點觸控手勢
API level 1中引入的GestureDetector類能夠用來探測單個手勢。GestureDetector類所支持的單指手勢包括如下幾種。
onDown:當用戶第一次按觸屏幕時觸發。
onShowPress:當用戶按觸屏幕,而且在擡起或移動手指以前觸發:用於顯示顯示地指示按觸事件確已探測到。
onSingleTapUp:做爲單擊(sinlge-tap)事件的一部分,在用戶從觸屏上擡起手指(使用擡起MotionEvent)時觸發。
onSingleTabConfirmed:單擊事件發生時調用。
onDoubleTab:雙擊(double-tap)事件發生時調用。
onDoubleTabEvent:在任何雙擊手勢發生時調用,包括按下(down),移動,或擡起(up)MotionEvent.
onLongPress:與onSingleTapUp相似,但只在用戶保持按觸狀態且不移動必定時間,而且不是標準的單擊操做時調用。
onScroll:用戶按下手指而且勻速移動手指後,在擡起手指前調用。一般也稱爲「拖曳」(dragging).
onFling:在用戶按下而且加速移動手指後,在擡起手指前調用,一般也稱爲"拂動(flick)手勢。
提示:你可使用GestureDetector.SimpleOnGestureListener類來監聽由GestureDetector識別的任何手勢。
實例:在Android中實現圖片左右滑動效果。
參考來自:
http://www.cnblogs.com/hanyonglu/archive/2012/02/13/2349827.html
原文比較詳細,在此不轉。注意的一點就是,爲了避免帶那些不用的方法,能夠繼承SimpleOnGestureListener類。
說一下,我我的的感覺。
1.受到一些網上不正確的文章,實習OnTouchListener了。
結果,原本應該重寫GestureDetector.OnGestureListener接口的
onTouchEvent方法時,實現了onTouch()方法,害我總是看不到效果,這裏弄,那裏查,結果,找了開始那本書學習。
系統學習以後,而後我看源代碼。發現了GestureDetector類這樣的javadoc:
/** * To use this class: * <ul> * <li>Create an instance of the {@code GestureDetector} for your {@link View} * <li>In the {@link View#onTouchEvent(MotionEvent)} method ensure you call * {@link #onTouchEvent(MotionEvent)}. The methods defined in your callback * will be executed when the events occur. * </ul> **/
上面那個ensure讓我以爲應該檢查下是否是實現了。而後,結果就出來了。哈哈。太不當心了。
關於判斷手勢效果的代碼:
Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT); if (e1.getX() - e2.getX() > 120) { this.mFlipper.setInAnimation(AnimationUtils.loadAnimation(this, R.anim.push_left_in)); this.mFlipper.setOutAnimation(AnimationUtils.loadAnimation(this, R.anim.push_left_out)); this.mFlipper.showNext(); return true; }
1.上面觸發事件時,我寫有Toast提醒代碼,可是實際上,用戶看不到。
2.第二 上面判斷手勢距離要求120px有點大長了。
下面學習下其中起到關鍵做用的另一個類。ViewFlipper.
ViewFlipper的類繼承關係以下:
ViewFlipper->ViewAnimator->FrameLayout->ViewGroup->View->Object
看一下類描述:(中文翻譯來自Android中文翻譯組)
/** * Simple {@link ViewAnimator} that will animate between two or more views * that have been added to it. Only one child is shown at a time. If * requested, can automatically flip between each child at a regular interval. * 被添加到ViewFlipper中的兩個或兩個以上的視圖之間將執行一個簡單的ViewAnimator動畫。
一次僅能顯示一個子視圖。若是須要,能夠設置間隔時間使子視圖像幻燈片同樣自動顯示。
(譯者注:com.example.android.apis.view/Animation_2.java包含該類示例程序) * @attr ref android.R.styleable#ViewFlipper_flipInterval * @attr ref android.R.styleable#ViewFlipper_autoStart */
通過使用SimpleOnGestureListener類後的所有Java代碼以下:
package me.banxi.slideapp; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.GestureDetector; import android.view.GestureDetector.OnGestureListener; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; import android.view.animation.AnimationUtils; import android.widget.ImageView; import android.widget.Toast; import android.widget.ViewFlipper; public class SlideAndGestureActivity extends Activity { private ViewFlipper mFlipper; private GestureDetector mDetector; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.slide); mDetector = new GestureDetector(getApplicationContext(),new FlingListener()); mFlipper = (ViewFlipper )findViewById(R.id.viewFlipper1); mFlipper.addView(addTextView(R.drawable.one)); mFlipper.addView(addTextView(R.drawable.two)); mFlipper.addView(addTextView(R.drawable.three)); mFlipper.addView(addTextView(R.drawable.four)); mFlipper.addView(addTextView(R.drawable.five)); } private View addTextView(int resId){ ImageView view = new ImageView(this); view.setImageResource(resId); return view; } @Override public boolean onTouchEvent(MotionEvent event) { return mDetector.onTouchEvent(event); } private class FlingListener extends GestureDetector.SimpleOnGestureListener{ @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { String msg = "e1:"+e1.getX()+","+e1.getY()+"e2:"+e2.getX()+","+e2.getY(); Log.i("MotionSlide", msg); if (e1.getX() - e2.getX() > 120) { mFlipper.setInAnimation(AnimationUtils.loadAnimation(getApplicationContext(), R.anim.push_left_in)); mFlipper.setOutAnimation(AnimationUtils.loadAnimation(getApplicationContext(), R.anim.push_left_out)); mFlipper.showNext(); return true; } else if (e1.getX() - e2.getX() < -120) { mFlipper.setInAnimation(AnimationUtils.loadAnimation(getApplicationContext(), R.anim.push_right_in)); mFlipper.setOutAnimation(AnimationUtils.loadAnimation(getApplicationContext(), R.anim.push_right_out)); mFlipper.showPrevious(); return true; } return false; } } }
在實際的項目開發中會遇到這樣同樣問題。
好比。上面 例子添加的ImageView默認也許不處理事件。因此 能夠 正常的滑動。
可是在個人實際的開發中,的發現如ViewFlipper上面有一個GridView,GridView上面排列有Button.而後滑動手勢
的事件就不會傳播到ViewFlipper中去啊。因而我開始是在GridView上面 設置 一個margin
在margin區域裏滑動事件 就會傳遞給ViwFlipper。(嚴格來講應該是mDetecotor.onTouchEvent()中去。
而後我就在想這個事件 傳播的問題,而後我想到由於其實主要調用mDetecotor的時候,
也是在Activity中的OnTouchEvent(MotionEvent)方法 中。
中將這個MotionEvent事件以這樣return mDetector.onTouchEvent(event)方法處理返回 。
因而 想在button中事件中的ACTION_MOVE中也調用mDetector.OnTouchEvent()
可是結果 不行。後來我就不區分ACTION_MOVE等等了。
因而,最後,我在對button和gridView作了以下處理。
button.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { return mDetector.onTouchEvent(event); } });
gridView.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { return mDetector.onTouchEvent(event); } });我想,由於Fliing這樣事件不只僅是ACTION_MOVE他還有開始的OnDown等等一系列事件組合起來的。