Android手勢操作

likeo 9年前發布 | 18K 次閱讀 Android Android開發 移動開發

前言

利用手勢操作在現在的APP中越來越普及,大多數時候使用Fling,Scroll等Gesture能大幅度提高用戶的操作體驗,特別是大屏手機返回鍵程越來越大的現狀下。
在Android系統下,手勢識別是通過GestureDetector.OnGestureListener接口實現的,不過官方的文檔可能覺得這部分 太基礎和簡單了,所以官方的API文檔中對手勢的講解描述的都很簡單,API Demo中也沒有提供一個清楚的例子,所以自己總結一下,其中還是涉及不少的基礎知識和一些官方文檔中說明不清的地方,如果不能好好掌握這些基礎知識,做 起事情來難免要吃一些苦頭。言歸正傳,下面我們開始:

基礎知識

我們先來明確一些概念,首先,Android的事件處理機制是基于Listener(監聽器)來實現的,比我們今天所說的觸摸屏相關的事件,就是通 過onTouchListener。其次,所有View的子類都可以通過setOnTouchListener()、 setOnKeyListener()等方法來添加對某一類事件的監聽器。第三,Listener一般會以Interface(接口)的方式來提供,其中 包含一個或多個abstract(抽象)方法,我們需要實現這些方法來完成onTouch()、onKey()等等的操作。這樣,當我們給某個view設 置了事件Listener,并實現了其中的抽象方法以后,程序便可以在特定的事件被dispatch到該view的時候,通過callbakc函數給予適 當的響應。

這篇文章簡單介紹了事件觸發的過程:Android事件分發圖解

實作

我們現在實作一個使用手勢的例子。
我們給RelativeView的實例my_view設定了一個onTouchListener,因為GestureTest類實現了 OnTouchListener 接口,所以簡單的給一個this作為參數即可。onTouch方法則是實現了OnTouchListener中的抽象方法,我們只要在這里添加邏輯代碼即 可在用戶觸摸屏幕時做出響應,

public class MainActivity extends ActionBarActivity implements View.OnTouchListener,GestureDetector.OnGestureListener{
GestureDetector gestureDetector = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    gestureDetector = new GestureDetector(this);
    gestureDetector.setIsLongpressEnabled(true);
    View v = findViewById(R.id.my_view);
    v.setOnTouchListener(this);
}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}

@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
    Log.i("HYY","onTouch present");

    return gestureDetector.onTouchEvent(motionEvent);
}

@Override
public boolean onDown(MotionEvent motionEvent) {
    Log.i("HYY","onDown present");
    return true;
}

@Override
public void onShowPress(MotionEvent motionEvent) {
    Log.i("HYY","onShowPress present");
}

@Override
public boolean onSingleTapUp(MotionEvent motionEvent) {
    Log.i("HYY","onSingleTapUp present");
    return false;
}

@Override
public boolean onScroll(MotionEvent motionEvent, MotionEvent motionEvent2, float v, float v2) {
    Log.i("HYY","onScroll present");
    return false;
}

@Override
public void onLongPress(MotionEvent motionEvent) {
    Log.i("HYY","onLongPress present");

}

@Override
public boolean onFling(MotionEvent motionEvent, MotionEvent motionEvent2, float v, float v2) {
    Log.i("HYY","onFling present");
    return false;
}
}

特別提示

這里有一點需要特別注意:要觸發onScroll和onFling,必須讓監聽器的onDown的返回值設為true

那么為什么如果不把onDown的返回值設為true的話,onScroll和onFiling就都不會被觸發呢?我們來看一下源碼中的介紹

/**
         * Notified when a scroll occurs with the initial on down {@link MotionEvent} and the
         * current move {@link MotionEvent}. The distance in x and y is also supplied for
         * convenience.
         *
         * @param e1 The first down motion event that started the scrolling.
         * @param e2 The move motion event that triggered the current onScroll.
         * @param distanceX The distance along the X axis that has been scrolled since the last
         *              call to onScroll. This is NOT the distance between {@code e1}
         *              and {@code e2}.
         * @param distanceY The distance along the Y axis that has been scrolled since the last
         *              call to onScroll. This is NOT the distance between {@code e1}
         *              and {@code e2}.
         * @return true if the event is consumed, else false
         */
        boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY);

        /**
         * Notified of a fling event when it occurs with the initial on down {@link MotionEvent}
         * and the matching up {@link MotionEvent}. The calculated velocity is supplied along
         * the x and y axis in pixels per second.
         *
         * @param e1 The first down motion event that started the fling.
         * @param e2 The move motion event that triggered the current onFling.
         * @param velocityX The velocity of this fling measured in pixels per second
         *              along the x axis.
         * @param velocityY The velocity of this fling measured in pixels per second
         *              along the y axis.
         * @return true if the event is consumed, else false
         */
        boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY);

onScroll和onFling方法的注釋上寫的很清楚,要判定為onScroll或onFling必須要建立在onDown被消費的前提下(即onDown返回true)。

來自:http://blog.csdn.net/yuyuanhuang/article/details/45068619

 本文由用戶 likeo 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!