【Touch&input 】检测常见手势(4)

当用户将一个或多个手指放在触摸屏上时发生“触摸手势”,并且您的应用程序将该触摸图案解释为特定手势。手势检测有相应的两个阶段:

  1. 收集有关触摸事件的数据。
  2. 解释数据以查看它是否符合您的应用支持的任何手势标准。

请参阅以下相关资源:

支持库类

本课中的例子使用GestureDetectorCompatMotionEventCompat类。这些类位于 支持库中。您应该尽可能使用支持库类,以提供与运行Android 1.6和更高版本的设备的兼容性。请注意,MotionEventCompat是不是为替代MotionEvent类。相反,它提供了静态实用程序方法,您可以通过它传递MotionEvent对象以便接收与该事件相关的所需操作。

收集资料


当用户在屏幕上放置一个或多个手指时,会触发onTouchEvent() 收到触摸事件的View上的回调。对于最终被识别为手势的每个触摸事件序列(位置,压力,大小,另外的手指的添加等), onTouchEvent()被触发多次。

手势在用户第一次触摸屏幕时开始,随着系统跟踪用户手指的位置而继续,并且通过捕获用户手指离开屏幕的最后事件而结束。在整个交互过程中,MotionEvent交付给onTouchEvent() 每个交互的细节。您的应用可以使用由其提供的数据MotionEvent 来确定是否发生了关心的手势。

捕获活动或视图的触摸事件

要拦截活动或视图中的触摸事件,请覆盖onTouchEvent()回调。

以下片段用于 getActionMasked() 提取用户从event参数执行的操作。这为您提供了需要确定您关心的手势是否发生的原始数据:

public class MainActivity extends Activity {
...
// This example shows an Activity, but you would use the same approach if
// you were subclassing a View.
@Override
public boolean onTouchEvent(MotionEvent event){

    int action = MotionEventCompat.getActionMasked(event);

    switch(action) {
        case (MotionEvent.ACTION_DOWN) :
            Log.d(DEBUG_TAG,"Action was DOWN");
            return true;
        case (MotionEvent.ACTION_MOVE) :
            Log.d(DEBUG_TAG,"Action was MOVE");
            return true;
        case (MotionEvent.ACTION_UP) :
            Log.d(DEBUG_TAG,"Action was UP");
            return true;
        case (MotionEvent.ACTION_CANCEL) :
            Log.d(DEBUG_TAG,"Action was CANCEL");
            return true;
        case (MotionEvent.ACTION_OUTSIDE) :
            Log.d(DEBUG_TAG,"Movement occurred outside bounds " +
                    "of current screen element");
            return true;
        default :
            return super.onTouchEvent(event);
    }
}

然后,您可以对这些事件进行自己的处理,以确定是否发生了手势。这是您需要为自定义手势进行的处理。但是,如果您的应用使用双击,长按,投掷等常用手势,则可以利用该GestureDetector课程。GestureDetector使您可以轻松检测常见手势,而无需亲自处理单个触摸事件。这在下面的检测手势中讨论。

捕获单个视图的触摸事件

作为替代方法onTouchEvent(),您可以使用该方法将View.OnTouchListener对象附加到任何View对象setOnTouchListener()。这使得监听触摸事件成为可能,而无需对现有的事件进行子类化View。例如:

扫描二维码关注公众号,回复: 1468445 查看本文章
View myView = findViewById(R.id.my_view);
myView.setOnTouchListener(new OnTouchListener() {
    public boolean onTouch(View v, MotionEvent event) {
        // ... Respond to touch events
        return true;
    }
});

当心创建返回监听器false的 ACTION_DOWN事件。如果你这样做,这个监听器将不会被调用以后的事件ACTION_MOVE 和ACTION_UP字符串。这是因为 ACTION_DOWN是所有触摸事件的起点。

如果您正在创建自定义视图,则可以覆盖 onTouchEvent(),如上所述。

检测手势


Android提供了GestureDetector用于检测常见手势的类。一些手势它支持包括onDown(),onLongPress(), onFling(),等等。您可以GestureDetector结合上述 onTouchEvent() 方法使用。

检测所有支持的手势

当你实例化一个GestureDetectorCompat 对象时,它所需要的参数之一是一个实现该GestureDetector.OnGestureListener接口的类 。 GestureDetector.OnGestureListener在发生特定触摸事件时通知用户。为了使 GestureDetector对象能够接收事件,可以覆盖View或Activity的onTouchEvent()方法,并将所有观察到的事件传递给检测器实例。

在下面的代码片段中,true来自各个 方法的返回值表示您已经处理了触摸事件。返回值将事件向下传递到视图堆栈,直到成功处理触摸为止。on<TouchEvent>false

运行以下代码片段,以了解与触摸屏进行交互时触发动作的方式,以及MotionEvent每个触摸事件的内容。即使简单的交互,你也会意识到生成了多少数据。

public class MainActivity extends Activity implements
        GestureDetector.OnGestureListener,
        GestureDetector.OnDoubleTapListener{

    private static final String DEBUG_TAG = "Gestures";
    private GestureDetectorCompat mDetector;

    // Called when the activity is first created.
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // Instantiate the gesture detector with the
        // application context and an implementation of
        // GestureDetector.OnGestureListener
        mDetector = new GestureDetectorCompat(this,this);
        // Set the gesture detector as the double tap
        // listener.
        mDetector.setOnDoubleTapListener(this);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event){
        if (this.mDetector.onTouchEvent(event)) {
            return true;
        }
        return super.onTouchEvent(event);
    }

    @Override
    public boolean onDown(MotionEvent event) {
        Log.d(DEBUG_TAG,"onDown: " + event.toString());
        return true;
    }

    @Override
    public boolean onFling(MotionEvent event1, MotionEvent event2,
            float velocityX, float velocityY) {
        Log.d(DEBUG_TAG, "onFling: " + event1.toString() + event2.toString());
        return true;
    }

    @Override
    public void onLongPress(MotionEvent event) {
        Log.d(DEBUG_TAG, "onLongPress: " + event.toString());
    }

    @Override
    public boolean onScroll(MotionEvent event1, MotionEvent event2, float distanceX,
            float distanceY) {
        Log.d(DEBUG_TAG, "onScroll: " + event1.toString() + event2.toString());
        return true;
    }

    @Override
    public void onShowPress(MotionEvent event) {
        Log.d(DEBUG_TAG, "onShowPress: " + event.toString());
    }

    @Override
    public boolean onSingleTapUp(MotionEvent event) {
        Log.d(DEBUG_TAG, "onSingleTapUp: " + event.toString());
        return true;
    }

    @Override
    public boolean onDoubleTap(MotionEvent event) {
        Log.d(DEBUG_TAG, "onDoubleTap: " + event.toString());
        return true;
    }

    @Override
    public boolean onDoubleTapEvent(MotionEvent event) {
        Log.d(DEBUG_TAG, "onDoubleTapEvent: " + event.toString());
        return true;
    }

    @Override
    public boolean onSingleTapConfirmed(MotionEvent event) {
        Log.d(DEBUG_TAG, "onSingleTapConfirmed: " + event.toString());
        return true;
    }
}

检测支持的手势的子集

如果您只想处理几个手势,则可以扩展GestureDetector.SimpleOnGestureListener而不是实现GestureDetector.OnGestureListener接口。

GestureDetector.SimpleOnGestureListener通过返回 所有这些方法为所有方法提供实现。因此,您只能覆盖您关心的方法。例如,下面的代码段创建延伸的类和覆盖和。on<TouchEvent>falseGestureDetector.SimpleOnGestureListeneronFling()onDown()

无论您是否使用GestureDetector.OnGestureListener,最好实践一个onDown() 返回的 方法true。这是因为所有手势都以onDown()消息开头 。如果返回 false的onDown(),因为GestureDetector.SimpleOnGestureListener在默认情况下不,系统会假设你要忽略手势的其余部分,以及其他方法 GestureDetector.OnGestureListener永远不会被调用。这可能会导致您的应用程序出现意外问题。您应该返回唯一的一次false由 onDown() 是,如果你真的想忽略的整个姿态。

public class MainActivity extends Activity {

    private GestureDetectorCompat mDetector;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mDetector = new GestureDetectorCompat(this, new MyGestureListener());
    }

    @Override
    public boolean onTouchEvent(MotionEvent event){
        this.mDetector.onTouchEvent(event);
        return super.onTouchEvent(event);
    }

    class MyGestureListener extends GestureDetector.SimpleOnGestureListener {
        private static final String DEBUG_TAG = "Gestures";

        @Override
        public boolean onDown(MotionEvent event) {
            Log.d(DEBUG_TAG,"onDown: " + event.toString());
            return true;
        }

        @Override
        public boolean onFling(MotionEvent event1, MotionEvent event2,
                float velocityX, float velocityY) {
            Log.d(DEBUG_TAG, "onFling: " + event1.toString() + event2.toString());
            return true;
        }
    }
}
Lastest Update:2018.04.25

联系我

QQ:94297366
微信打赏:https://pan.baidu.com/s/1dSBXk3eFZu3mAMkw3xu9KQ

公众号推荐:

【Touch&input 】检测常见手势(4)

猜你喜欢

转载自blog.51cto.com/4789781/2124896