日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android 触摸手势基础 官方文档概览

發布時間:2023/12/10 Android 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android 触摸手势基础 官方文档概览 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

觸摸手勢檢測基礎

  手勢檢測一般包含兩個階段:

  1.獲取touch事件數據

  2.解析這些數據,看它們是否滿足你的應用所支持的某種手勢。

  相關API:

  MotionEvent

  兼容版的:

  MotionEventCompat?

  (Note that?MotionEventCompat?is not a replacement for the?MotionEvent?class. Rather, it provides static utility methods to which you pass your?MotionEvent?object in order to receive the desired action associated with that event.)

?

一般的Activity或View中的touch事件處理

  Activity或View類的onTouchEvent()?回調函數會接收到touch事件。

  為了截獲touch事件,你需要覆寫Activity或View的onTouchEvent方法。

?

  View中還可以使用setOnTouchListener()方法添加點擊事件的?View.OnTouchListener?監聽對象。這樣就可以不繼承View而處理點擊事件。

  但是如果需要處理雙擊、長按、fling(快滑)等手勢,你需要利用?GestureDetector類。

?

onTouchEvent方法的返回值

  onTouchEvent方法的返回值,如果返回true,意味著你已經處理過了touch事件;如果返回false,將會繼續通過view stack傳遞事件,直到事件被處理。

  這里需要注意?ACTION_DOWN?事件,如果返回false,則該listener將不會被告知后面的一系列?ACTION_MOVE和?ACTION_UP?事件。

?

檢測手勢

  Android提供了GestureDetector?類來檢測一般的手勢。

  基本使用:

  1.生成GestureDetector?對象(或GestureDetectorCompat對象),構造時的參數傳入監聽器對象。

  監聽器對象實現GestureDetector.OnGestureListener?接口。

  如果你僅僅是想利用其中的一些手勢而不是全部,那么你可以選擇繼承GestureDetector.SimpleOnGestureListener類,這是一個適配器模式,即這個類實現了GestureDetector.OnGestureListener?接口,為其中所有的方法提供了空實現(返回值都是false),當繼承GestureDetector.SimpleOnGestureListener類時,子類只需要覆寫感興趣的方法,其他方法是空實現。

  2.為了讓?GestureDetector對象接收到事件,需要覆寫View或Activity中的?onTouchEvent()方法,將事件傳遞給detector對象。

  一個例子:

package com.example.hellogesturedetector;import android.os.Bundle; import android.app.Activity; import android.util.Log; import android.view.GestureDetector; import android.view.GestureDetector.OnDoubleTapListener; import android.view.GestureDetector.OnGestureListener; import android.view.Menu; import android.view.MotionEvent; import android.view.ViewGroup; import android.widget.TextView;public class HelloGestureDetectorActivity extends Activity {private static final String LOG_TAG = "HelloGesture";private GestureDetector mGestureDetector = null;private TextView mGestureTextView = null;private TextView mDoubleTapTextView = null;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_hello_gesture_detector);mGestureTextView = (TextView) findViewById(R.id.gesture);mDoubleTapTextView = (TextView) findViewById(R.id.doubleTap);// 構造GestureDetector對象,傳入監聽器對象mGestureDetector = new GestureDetector(this, mOnGestureListener);// 傳入雙擊監聽器對象mGestureDetector.setOnDoubleTapListener(mDoubleTapListener);}@Overridepublic boolean onTouchEvent(MotionEvent event) {// 在onTouchEvent方法中將事件傳遞給手勢檢測對象,否則手勢監聽對象中的回調函數是不會被調用的mGestureDetector.onTouchEvent(event);return super.onTouchEvent(event);}private OnGestureListener mOnGestureListener = new OnGestureListener() {@Overridepublic boolean onSingleTapUp(MotionEvent e) {Log.i(LOG_TAG, "onSingleTapUp: " + e.toString());mGestureTextView.setText("onSingleTapUp: ");return false;}@Overridepublic void onShowPress(MotionEvent e) {Log.i(LOG_TAG, "onShowPress: " + e.toString());mGestureTextView.setText("onShowPress: ");}@Overridepublic boolean onScroll(MotionEvent e1, MotionEvent e2,float distanceX, float distanceY) {Log.i(LOG_TAG, "onScroll: " + e1.toString() + ", " + e2.toString());mGestureTextView.setText("onScroll ");return false;}@Overridepublic void onLongPress(MotionEvent e) {Log.i(LOG_TAG, "onLongPress: " + e.toString());mGestureTextView.setText("onLongPress: ");}@Overridepublic boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,float velocityY) {Log.i(LOG_TAG, "onFling: " + e1.toString() + ", " + e2.toString());mGestureTextView.setText("onFling ");return false;}@Overridepublic boolean onDown(MotionEvent e) {Log.i(LOG_TAG, "onDown: " + e.toString());mGestureTextView.setText("onDown: ");return false;}};private OnDoubleTapListener mDoubleTapListener = new OnDoubleTapListener() {@Overridepublic boolean onSingleTapConfirmed(MotionEvent e) {Log.i("LOG_TAG", "onSingleTapConfirmed: " + e.toString());mDoubleTapTextView.setText("onSingleTapConfirmed: ");return false;}@Overridepublic boolean onDoubleTapEvent(MotionEvent e) {Log.i("LOG_TAG", "onDoubleTapEvent: " + e.toString());mDoubleTapTextView.setText("onDoubleTapEvent: ");return false;}@Overridepublic boolean onDoubleTap(MotionEvent e) {Log.i("LOG_TAG", "onDoubleTap: " + e.toString());mDoubleTapTextView.setText("onDoubleTap: ");return false;}}; }

?

?

  根據官網上說:

  關于onDown()方法的返回值,最好是返回true,因為所有的手勢都是從onDown()信息開始的。

  如果像?GestureDetector.SimpleOnGestureListener?默認實現一樣返回false,系統就會認為你想要忽略之后的其他手勢,然后GestureDetector.OnGestureListener?的其他方法就不會被調用。

  但是實際程序驗證的時候,發現返回true還是false好像沒有什么影響。(??)

?

跟蹤運動 速度

  有很多不同的方法來記錄手勢中的運動,比如pointer的起始位置和終止位置;pointer運動的方向;手勢的歷史(通過?getHistorySize()方法得到);還有pointer的運動速度。

  Android提供了VelocityTracker?類和VelocityTrackerCompat類,來記錄touch事件的速度。

  代碼例子:

public class MainActivity extends Activity {private static final String DEBUG_TAG = "Velocity";...private VelocityTracker mVelocityTracker = null;@Overridepublic boolean onTouchEvent(MotionEvent event) {int index = event.getActionIndex();int action = event.getActionMasked();int pointerId = event.getPointerId(index);switch(action) {case MotionEvent.ACTION_DOWN:if(mVelocityTracker == null) {// Retrieve a new VelocityTracker object to watch the velocity of a motion.mVelocityTracker = VelocityTracker.obtain();}else {// Reset the velocity tracker back to its initial state.mVelocityTracker.clear();}// Add a user's movement to the tracker.mVelocityTracker.addMovement(event);break;case MotionEvent.ACTION_MOVE:mVelocityTracker.addMovement(event);// When you want to determine the velocity, call // computeCurrentVelocity(). Then call getXVelocity() // and getYVelocity() to retrieve the velocity for each pointer ID. mVelocityTracker.computeCurrentVelocity(1000);// Log velocity of pixels per second// Best practice to use VelocityTrackerCompat where possible.Log.d("", "X velocity: " + VelocityTrackerCompat.getXVelocity(mVelocityTracker, pointerId));Log.d("", "Y velocity: " + VelocityTrackerCompat.getYVelocity(mVelocityTracker,pointerId));break;case MotionEvent.ACTION_UP:case MotionEvent.ACTION_CANCEL:// Return a VelocityTracker object back to be re-used by others.mVelocityTracker.recycle();break;}return true;} }

?

滾動手勢

  如果一個標準的布局有可能會超出它的容器的邊界,可以把它嵌套在一個ScrollView中,這樣就會得到一個可以滾動的布局,由framewok處理。

  實現一個自定義的scroller應該只在一些特殊情況下需要。

  Scroller用來隨時間制造滾動動畫,使用平臺標準的滾動物理參數(摩擦力、速度等)。

  Scroller自己本身實際上并不繪制任何東西。

  Scroller記錄滾動的偏移值,但是它并不會將這些位置應用到你的View,你需要自己動手。

  詳見:http://developer.android.com/training/gestures/scroll.html

?

多點觸摸手勢

  當多個pointer同時觸摸屏幕,系統會生成如下事件:

  • ACTION_DOWN—For the first pointer that touches the screen. This starts the gesture. The pointer data for this pointer is always at index 0 in the?MotionEvent.
  • ACTION_POINTER_DOWN—For extra pointers that enter the screen beyond the first. The pointer data for this pointer is at the index returned by?getActionIndex().
  • ACTION_MOVE—A change has happened during a press gesture.
  • ACTION_POINTER_UP—Sent when a non-primary pointer goes up.
  • ACTION_UP—Sent when the last pointer leaves the screen.

  你可以依靠每一個pointer的index和ID來追蹤每一個pointer:

  IndexMotionEvent會把每一個pointer的信息放在一個數組里,index即是這個數組索引。大多數你用的MotionEvent方法是以這個index作為參數的。

  ID:每一個pointer還有一個ID映射,在touch事件中保持恒定一致(persistent),這樣就可以在整個手勢中跟蹤一個單獨的pointer。

?

  pointer在一個motion event中出現的順序是未定的,所以pointer的index在不同的事件中是可變的,但是只要pointer保持active,它的ID是保持不變的。

  通過getPointerId()獲得ID,這樣就可以在多個motion event中追蹤pointer。然后對于連續的motion event,可以使用findPointerIndex()方法來獲得指定ID的pointer在當前事件中的index。

  比如:

private int mActivePointerId;public boolean onTouchEvent(MotionEvent event) {....// Get the pointer IDmActivePointerId = event.getPointerId(0);// ... Many touch events later...// Use the pointer ID to find the index of the active pointer // and fetch its positionint pointerIndex = event.findPointerIndex(mActivePointerId);// Get the pointer's current positionfloat x = event.getX(pointerIndex);float y = event.getY(pointerIndex); }

?

?

  獲取MotionEvent的動作應該使用getActionMasked()方法(或者是兼容版的MotionEventCompat.getActionMasked())。

  與舊版的getAction()不同,getActionMasked()?方法是被設計為可以多個pointer工作的。

  它會返回帶掩模的動作,不帶pointer用于index的那些位。

  你可以使用getActionIndex()來得到index。

?

拖動和縮放

  拖動一個對象:

  如果是Android 3.0以上,可以使用View的新接口View.OnDragListener參見:Drag and Drop。

  其他參見:http://developer.android.com/training/gestures/scale.html

?

  縮放可以使用?ScaleGestureDetector

  ScaleGestureDetector可以和GestureDetector一起使用。

?

ViewGroup中的Touch事件處理

  處理?ViewGroup的touch事件要麻煩一些,因為很可能各種touch事件的目標不是ViewGroup而是它的child。

  為了確保每一個child正確地接收到touch events,需要覆寫ViewGroup的onInterceptTouchEvent()方法。

?

  如果onInterceptTouchEvent()方法返回true,說明MotionEvent被截獲了,它將不會被傳遞給child,而是傳遞給parent的?onTouchEvent()方法。

  如果你在parent的onInterceptTouchEvent()方法中返回了true,先前還在處理touch event的child view將會接收到一個?ACTION_CANCEL,之后的事件就會全傳遞到parent的onTouchEvent中。

  如果?onInterceptTouchEvent()?方法返回false,則事件繼續順著view結構向下傳遞,parent不會截獲事件,也不會調用parent的onTouchEvent()方法。

?

  另:

  ViewConfiguration提供一些常量。

  TouchDelegate類可以用來設置View的觸摸區域。

  用法見:http://developer.android.com/training/gestures/viewgroup.html

?

參考資料

  Training: Using Touch Gestures

  http://developer.android.com/training/gestures/index.html

轉載于:https://www.cnblogs.com/Free-Thinker/p/5504125.html

總結

以上是生活随笔為你收集整理的Android 触摸手势基础 官方文档概览的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。