Android 的觸摸事件詳解及範例程式碼_Android

來源:互聯網
上載者:User

由於觸摸(Touch)而觸發的事件

Android的事件:onClick, onScroll,onFling等等,都是由許多個Touch組成的。其中Touch的第一個狀態肯定是ACTION_DOWN,表示按下了螢幕。之後,touch將會有後續事件,可能是:

ACTION_MOVE //表示為移動手勢

ACTION_UP //表示為離開螢幕

ACTION_CANCEL //表示取消手勢,不會由使用者產生,而是由程式產生的

一個Action_DOWN, n個ACTION_MOVE, 1個ACTION_UP,就構成了Android中眾多的事件。

對於ViewGroup類的控制項,有一個很重要的方法,就是onInterceptTouchEvent(),用於處理事件並改變事件的傳遞方向,它的傳回值是一個布爾值,決定了Touch事件是否要向它包含的子View繼續傳遞,這個方法是從父View向子View傳遞。

而方法onTouchEvent(),用於接收事件並處理,它的傳回值也是一個布爾值,決定了事件及後續事件是否繼續向上傳遞,這個方法是從子View向父View傳遞。

touch事件在onInterceptTouchEvent()和onTouchEvent以及各個childView間的傳遞機制完全取決於onInterceptTouchEvent()和onTouchEvent()的傳回值。傳回值為true表示事件被正確接收和處理了,傳回值為false表示事件沒有被處理,將繼續傳遞下去。

ACTION_DOWN事件會傳到某個ViewGroup類的onInterceptTouchEvent,如果返回false,則DOWN事件繼續向子ViewGroup類的onInterceptTouchEvent傳遞,如果子View不是ViewGroup類的控制項,則傳遞給它的onTouchEvent。

如果onInterceptTouchEvent返回了true,則DOWN事件傳遞給它的onTouchEvent,不再繼續傳遞,並且之後的後續事件也都傳遞給它的onTouchEvent。

如果某View的onTouchEvent返回了false,則DOWN事件繼續向其父ViewGroup類的onTouchEvent傳遞;如果返回了true,則後續事件會直接傳遞給其onTouchEvent繼續處理。(後續事件只會傳遞給對於必要事件ACTION_DOWN返回了true的onTouchEvent)

總結一下就是:onInterceptTouchEvent可以接受到所有的Touch事件,而onTouchEvent則不一定。

對於android 自訂控制項的事件 android提供了一個GestureDetector的類和GestureDetector.OnGestureListener的介面來判斷使用者在介面上做出怎麼樣的動作。

Android裡有兩個類

  android.view.GestureDetector
  android.view.GestureDetector.SimpleOnGestureListener
  (另外android.widget.Gallery好像是更牛x的OnGestureListener )

  1) 建立一個類繼承SimpleOnGestureListener,HahaGestureDetectorListener 

     可以實現以下event事件。
  boolean onDoubleTap(MotionEvent e)
  解釋:雙擊的第二下Touch down時觸發
  boolean onDoubleTapEvent(MotionEvent e)
  解釋:雙擊的第二下Touch down和up都會觸發,可用e.getAction()區分。
  boolean onDown(MotionEvent e)
  解釋:Touch down時觸發
  boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,float velocityY)
  解釋:Touch了滑動一點距離後,up時觸發。
  void onLongPress(MotionEvent e)
  解釋:Touch了不移動一直Touch down時觸發
  boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,float distanceY)
  解釋:Touch了滑動時觸發。
  void onShowPress(MotionEvent e)
  解釋:Touch了還沒有滑動時觸發
  (與onDown,onLongPress比較
  onDown只要Touch down一定立刻觸發。
  而Touchdown後過一會沒有滑動先觸發onShowPress再是onLongPress。
  所以Touchdown後一直不滑動,onDown->onShowPress->onLongPress這個順序觸發。
  )
  boolean onSingleTapConfirmed(MotionEvent e)
  boolean onSingleTapUp(MotionEvent e)
  解釋:上面這兩個函數都是在touchdown後又沒有滑動(onScroll),又沒有長按(onLongPress),然後Touchup時觸發。
  點擊一下非常快的(不滑動)Touchup:
  onDown->onSingleTapUp->onSingleTapConfirmed
  點擊一下稍微慢點的(不滑動)Touchup:
  onDown->onShowPress->onSingleTapUp->onSingleTapConfirmed 

publicclassGestureActivityextendsActivityimplementsOnTouchListener,    OnGestureListener {  GestureDetector detector;  publicGestureActivity(){    detector = new GestureDetector(this);  }    publicvoidonCreate(BundlesavedInstanceState) {       super.onCreate(savedInstanceState);       setContentView(R.layout.main);       TextView tv = (TextView) findViewById(R.id.TextView001);      //設定tv的監聽器       tv.setOnTouchListener(this);       tv.setFocusable(true);      //必須,view才能夠處理不同於Tap(輕觸)的hold      tv.setClickable(true);       tv.setLongClickable(true);       detector.setIsLongpressEnabled(true);   }          publicbooleanonTouch(View v,MotionEvent event) {     returndetector.onTouchEvent(event);   }    // 使用者輕觸觸控螢幕,由1個MotionEventACTION_DOWN觸發   publicbooleanonDown(MotionEventarg0) {     Log.i("MyGesture","onDown");     Toast.makeText(this, "onDown",Toast.LENGTH_SHORT).show();     returntrue;   }        publicvoidonShowPress(MotionEvent e) {     Log.i("MyGesture","onShowPress");     Toast.makeText(this, "onShowPress",Toast.LENGTH_SHORT).show();   }      // 使用者(輕觸觸控螢幕後)鬆開,由一個1個MotionEventACTION_UP觸發   publicbooleanonSingleTapUp(MotionEvent e) {     Log.i("MyGesture","onSingleTapUp");     Toast.makeText(this, "onSingleTapUp",Toast.LENGTH_SHORT).show();     returntrue;   }      // 使用者按下觸控螢幕、快速移動後鬆開,由1個MotionEventACTION_DOWN, 多個ACTION_MOVE, 1個ACTION_UP觸發   publicbooleanonFling(MotionEvente1, MotionEvent e2, float velocityX, float velocityY) {     Log.i("MyGesture","onFling");         // 參數解釋:     // e1:第1個ACTION_DOWNMotionEvent     // e2:最後一個ACTION_MOVEMotionEvent     // velocityX:X軸上的移動速度,像素/秒     // velocityY:Y軸上的移動速度,像素/秒        // 觸發條件 :     // X軸的座標位移大於FLING_MIN_DISTANCE,且移動速度大於FLING_MIN_VELOCITY個像素/秒          finalintFLING_MIN_DISTANCE = 100,FLING_MIN_VELOCITY = 200;     if (e1.getX() - e2.getX() >FLING_MIN_DISTANCE &&Math.abs(velocityX) > FLING_MIN_VELOCITY){       // Flingleft       Log.i("MyGesture","Fling left");       Toast.makeText(this, "FlingLeft",Toast.LENGTH_SHORT).show();     } elseif (e2.getX() - e1.getX() >FLING_MIN_DISTANCE &&Math.abs(velocityX) > FLING_MIN_VELOCITY){       // Flingright       Log.i("MyGesture","Fling right");       Toast.makeText(this, "FlingRight",Toast.LENGTH_SHORT).show();     } elseif(e2.getY()-e1.getY()>FLING_MIN_DISTANCE && Math.abs(velocityY)>FLING_MIN_VELOCITY) {      // Flingdown       Log.i("MyGesture","Fling down");       Toast.makeText(this, "Flingdown",Toast.LENGTH_SHORT).show();    } elseif(e1.getY()-e2.getY()>FLING_MIN_DISTANCE && Math.abs(velocityY)>FLING_MIN_VELOCITY) {      // Fling up       Log.i("MyGesture","Fling up");       Toast.makeText(this, "Flingup",Toast.LENGTH_SHORT).show();    }             returnfalse;      }      // 使用者按下觸控螢幕,並拖動,由1個MotionEventACTION_DOWN, 多個ACTION_MOVE觸發   publicbooleanonScroll(MotionEvente1, MotionEvent e2, float distanceX, float distanceY) {     Log.i("MyGesture","onScroll");     Toast.makeText(this, "onScroll",Toast.LENGTH_LONG).show();     returntrue;   }      // 使用者長按觸控螢幕,由多個MotionEventACTION_DOWN觸發   publicvoidonLongPress(MotionEvent e) {     Log.i("MyGesture","onLongPress");     Toast.makeText(this, "onLongPress",Toast.LENGTH_LONG).show();   }   }

  2)在view的建立一個GestureDetector的對象。

  建構函式裡

  gestureDetector = new GestureDetector(newHahaGestureDetectorListener());

  然後在View的onTouchEvent裡以下這樣用,就可以在剛才1)弄的事件裡寫自己的代碼了。

  @Override  public boolean onTouchEvent(MotionEvent event) {  gestureDetector.onTouchEvent(event);  }  mTouchListener = new OnTouchListener() {   @Override   public boolean onTouch(View v, MotionEvent event) {   // TODO Auto-generated method stub   float x =event.getXPrecision()*event.getX()+event.getX();   float y =event.getYPrecision()*event.getY()+event.getY();   switch (event.getAction()) {   case MotionEvent.ACTION_DOWN:     break;   case MotionEvent.ACTION_MOVE:   mTouchTimes++;   if (mTouchTimes > TOUCH_TIMES) {  // 根據方向計算角度   if (mCurrentOrientation==DeviceOrientation.Landscape) {   mAngle = Math.toDegrees(Math.atan2(y - 480 / 2, x))+90;   } else {   mAngle = -Math.toDegrees(Math.atan2(y - 480 / 2,320-x))+90;   }     Log.w("angle", "mangle:"+mAngle);   }   break;   case MotionEvent.ACTION_UP:   if (mTouchTimes > TOUCH_TIMES) {     } else {     }   mTouchTimes = 0;   break;   default:   break;  }   return true;   }   };  mView.setOnTouchListener(mTouchListener); 

通過此文,希望能協助開發Android應用使用觸摸事件的朋友,謝謝大家對本站的支援!

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.