Android手勢學習之單點手勢

最後更新: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等等一系列事件組合起來的。
相關文章
相關標籤/搜索