`
houniao1990
  • 浏览: 14085 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

【笔记】android捕获触摸事件

阅读更多

【摘】捕获触摸事件

 

重写onTouchEvent()回调函数

 

 

public class MainActivity extends Activity {

@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);
        }
}

 

 

然后,我们可以对这些事件做些自己的处理,以判断某个手势是否出现了。这种是针对自定义手势,我们所需要进行的处理。然而,如果我们的app仅仅需要一些常见的手势,如双击,长按,快速滑动(fling)等,那么我们可以使用GestureDetector类来完成。

 

 

 

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){
        this.mDetector.onTouchEvent(event);
        // Be sure to call the superclass implementation
        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 e1, MotionEvent e2, float distanceX,
            float distanceY) {
        Log.d(DEBUG_TAG, "onScroll: " + e1.toString()+e2.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> 型函数,其中,这些函数都返回false。因此,我们可以仅仅重写我们需要的函数。比如,下面的代码段中,创建了一个继承自GestureDetector.SimpleOnGestureListener 的类,并重写了 onFling() 和 onDown() 函数。

无论我们是否使用GestureDetector.OnGestureListener类,最好都实现 onDown() 函数并且返回 true。这是因为所有的手势都是由 onDown() 消息开始的。如果让 onDown() 函数返回 false,就像GestureDetector.SimpleOnGestureListener类中默认实现的那样,系统会假定我们想忽略剩余的手势,GestureDetector.OnGestureListener中的其他函数也就永远不会被调用。这可能会导致我们的app出现意想不到的问题。仅仅当我们真的想忽略全部手势时,我们才应该让 onDown() 函数返回 false

 

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;
        }
    }
}

 

根据应用的需求,有多种追踪手势移动的方式可以选择。比如:

  • 追踪手指的起始和终止位置(比如,把屏幕上的对象从A点移动到B点)
  • 根据x、y轴坐标,追踪手指移动的方向。
  • 追踪历史状态。我们可以通过调用MotionEventgetHistorySize()方法,来获得一个手势的历史尺寸。我们可以通过移动事件的getHistorical<Value>系列函数,来获得事件之前的位置、尺寸、时间以及按压力(pressures)。当我们需要绘制用户手指痕迹时,历史状态非常有用,比如触摸绘图。查看MotionEvent来了解更多细节。
  • 追踪手指在触摸屏上滑过的速度。Android提供了VelocityTracker类以及Support Library中的VelocityTrackerCompat类。VelocityTracker类可以帮助我们追踪触摸事件中的速度因素。
public class MainActivity extends Activity {
    private static final String DEBUG_TAG = "Velocity";
        ...
    private VelocityTracker mVelocityTracker = null;
    @Override
    public 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;
    }
}

 

 

 

追踪多点

当多个手指同时触摸屏幕时,系统会产生如下的触摸事件:

  • ACTION_DOWN - 针对触摸屏幕的第一个点。此事件是手势的开端。第一触摸点的数据在MotionEvent中的索引总是0。
  • ACTION_POINTER_DOWN - 针对第一点后,出现在屏幕上额外的点。这个点的数据在MotionEvent中的索引,可以通过getActionIndex()获得。
  • ACTION_MOVE - 在按下手势期间发生变化。
  • ACTION_POINTER_UP - 当非主要点(non-primary pointer)离开屏幕时,发送此事件。
  • ACTION_UP - 当最后一点离开屏幕时发送此事件。

 

拖拽一个对象

对于触摸手势来说,一个很常见的操作是在屏幕上拖拽一个对象。接下来的代码段让用户可以拖拽屏幕上的图片。需要注意以下几点:

  • 拖拽操作时,即使有额外的手指放置到屏幕上了,app也必须保持对最初的点(手指)的追踪。比如,想象在拖拽图片时,用户放置了第二根手指在屏幕上,并且抬起了第一根手指。如果我们的app只是单独地追踪每个点,它会把第二个点当做默认的点,并且把图片移到该点的位置。
  • 为了防止这种情况发生,我们的app需要区分初始点以及随后任意的触摸点。要做到这一点,它需要追踪处理多触摸手势章节中提到过的 ACTION_POINTER_DOWN  ACTION_POINTER_UP 事件。每当第二根手指按下或拿起时,ACTION_POINTER_DOWN  ACTION_POINTER_UP 事件就会传递给onTouchEvent()回调函数。
  • ACTION_POINTER_UP事件发生时,示例程序会移除对该点的索引值的引用,确保操作中的点的ID(the active pointer ID)不会引用已经不在触摸屏上的触摸点。这种情况下,app会选择另一个触摸点来作为操作中(active)的点,并保存它当前的x、y值。由于在ACTION_MOVE事件时,这个保存的位置会被用来计算屏幕上的对象将要移动的距离,所以app会始终根据正确的触摸点来计算移动的距离。

 

 

// The ‘active pointer’ is the one currently moving our object.
private int mActivePointerId = INVALID_POINTER_ID;

@Override
public boolean onTouchEvent(MotionEvent ev) {
    // Let the ScaleGestureDetector inspect all events.
    mScaleDetector.onTouchEvent(ev);

    final int action = MotionEventCompat.getActionMasked(ev);

    switch (action) {
    case MotionEvent.ACTION_DOWN: {
        final int pointerIndex = MotionEventCompat.getActionIndex(ev);
        final float x = MotionEventCompat.getX(ev, pointerIndex);
        final float y = MotionEventCompat.getY(ev, pointerIndex);

        // Remember where we started (for dragging)
        mLastTouchX = x;
        mLastTouchY = y;
        // Save the ID of this pointer (for dragging)
        mActivePointerId = MotionEventCompat.getPointerId(ev, 0);
        break;
    }

    case MotionEvent.ACTION_MOVE: {
        // Find the index of the active pointer and fetch its position
        final int pointerIndex =
                MotionEventCompat.findPointerIndex(ev, mActivePointerId);

        final float x = MotionEventCompat.getX(ev, pointerIndex);
        final float y = MotionEventCompat.getY(ev, pointerIndex);

        // Calculate the distance moved
        final float dx = x - mLastTouchX;
        final float dy = y - mLastTouchY;

        mPosX += dx;
        mPosY += dy;

        invalidate();

        // Remember this touch position for the next move event
        mLastTouchX = x;
        mLastTouchY = y;

        break;
    }

    case MotionEvent.ACTION_UP: {
        mActivePointerId = INVALID_POINTER_ID;
        break;
    }

    case MotionEvent.ACTION_CANCEL: {
        mActivePointerId = INVALID_POINTER_ID;
        break;
    }

    case MotionEvent.ACTION_POINTER_UP: {

        final int pointerIndex = MotionEventCompat.getActionIndex(ev);
        final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex);

        if (pointerId == mActivePointerId) {
            // This was our active pointer going up. Choose a new
            // active pointer and adjust accordingly.
            final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
            mLastTouchX = MotionEventCompat.getX(ev, newPointerIndex);
            mLastTouchY = MotionEventCompat.getY(ev, newPointerIndex);
            mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex);
        }
        break;
    }
    }
    return true;
}

 

分享到:
评论

相关推荐

    Android例子源码仿有道云笔记的原笔迹手写功能

    在Android平台上,实现类似有道云笔记的原笔迹手写功能是一项技术挑战,涉及到图形绘制、触摸事件处理以及手势识别等多个方面的知识。这个例子源码提供了一个完整的解决方案,可以帮助开发者理解和实现这样的功能。 ...

    android 学习笔记(全全整理)

    4. **事件处理**:学习Android中的触摸事件、键盘事件以及各种控件的监听事件,如OnClickListener、OnCheckedChangeListener等,以及如何通过Handler和Runnable实现异步消息处理。 5. **数据存储**:了解SQLite...

    Cocos2D-X开发学习笔记-触屏事件使用示例

    开发者可以通过重写`Layer`或`Scene`的触摸事件回调函数来捕获和处理这些事件。 一、单点触摸事件处理 1. `onTouchesBegan`: 当用户首次触摸屏幕时,这个回调会被调用。参数是一个`std::vector*&gt;`类型的数组,包含...

    Android开发教程笔记完全版(第6-10篇)

    7. **触摸事件处理(Touch Events)**:Android通过MotionEvent对象处理触摸事件,包括ACTION_DOWN、ACTION_UP、ACTION_MOVE等。学习如何在活动中捕获并处理这些事件,可以实现更丰富的用户交互。 8. **权限管理...

    Android高级应用源码-android的手写功能.rar

    用户在屏幕上触控时,应用需要捕获触摸事件,并通过`Canvas`将轨迹绘制出来。 3. **触摸事件处理**:Android的`MotionEvent`类用于处理触摸屏事件,包括ACTION_DOWN(按下)、ACTION_MOVE(移动)和ACTION_UP(抬起...

    android笔画回放

    在Android中,触摸事件(MotionEvent)是通过View或者Activity来捕获的。当用户在屏幕上滑动手指时,系统会生成一系列ACTION_DOWN、ACTION_MOVE和ACTION_UP等事件,开发者可以通过重写`onTouchEvent()`方法来处理...

    cocos2d-x学习笔记(10)--touchEvent.rar

    本学习笔记将深入探讨cocos2d-x中的触摸事件处理机制,以及如何在项目中有效地利用它们。 首先,cocos2d-x是一个跨平台的2D游戏开发框架,它支持多种操作系统,包括iOS、Android、Windows等。在这些平台上,触摸...

    Android核心知识点笔记V2020.03.30.pdf

    其中包括了自定义View的绘制流程,以及与触摸事件、手势识别、视图滑动等相关的处理。 2.8 进程 Android应用是由一个或多个进程构成的,进程的生命周期和多进程的管理都是重要的知识点。进程存活受系统资源分配影响...

    Android测试工具Monkey学习笔记

    - **--pct-touch**:设置触摸事件的比例。 - **--pct-motion**:设置运动事件的比例。 - **--pct-trackball**:设置轨迹球事件的比例。 - **--pct-syskeys**:设置系统按键事件的比例。 - **--pct-appswitch**:设置...

    仿印象笔记抽屉菜单效果.zip

    总的来说,仿印象笔记抽屉菜单效果的实现涉及了Android的基础知识,包括自定义视图、触摸事件处理、动画以及界面交互设计。这个过程不仅可以提升你的编程技能,也能帮助你理解如何在实际项目中构建动态、交互性强的...

    Android-Android画板控件可以写字画画并生成图片

    为了实现这样的功能,我们需要继承`View`类或`SurfaceView`类,并重写其`onTouchEvent`方法来捕获用户的触摸事件,以及`onDraw`方法来进行实际的绘图操作。 在`onTouchEvent`方法中,我们需要记录下每次触摸屏幕时...

    Android 高仿 QQ5.0 侧滑菜单效果 自定义控件来袭【学习鸿洋_视频博客笔记总结】

    2. **触摸事件处理**:监听用户的触摸事件,当用户在屏幕边缘滑动时,捕获这些事件并进行相应的响应。可以通过重写`onTouchEvent()`方法实现。 3. **动画效果**:为了使侧滑菜单的展开和收起更加平滑,可以使用`...

    基于QT开发的无触摸屏系统按键解决方案

    总的来说,通过QT开发的无触摸屏系统按键解决方案,不仅能够锻炼开发者对QT绘图和事件处理的理解,还能够展示如何在嵌入式系统中实现高效的人机交互。这在工程实践中具有很高的实用价值,特别是在那些物理按键或非...

    android 便签 手写签到demo

    通过研究这个"android 便签 手写签到demo",开发者可以学习到如何处理触摸事件、如何绘制和保存手写路径,以及如何将这些功能整合到实际应用中。这个项目对于初学者来说是一份很好的实践教程,对于有经验的开发者来...

    android 学习心得

    - **触摸事件**:包括点击、滑动、长按等。 - **按键事件**:如物理按键的按下、抬起等。 - **事件分发机制**:主要包括事件捕获、事件目标、事件响应三个阶段。 - **事件监听器**:通过为View设置监听器(如 `...

    Android Mouse实现过程详细笔记

    一旦QEMU捕获到鼠标事件,这些事件会被转换为Android的MotionEvent,并由InputDispatcher分发到相应的应用程序或服务。 在具体实现时,可能会遇到一些问题,比如在Emulator中,系统可能默认模拟电池状态为无电,...

    calabash-android学习笔记V0.2.docx

    3. **屏幕截图(Screenshots)**:可以捕获设备当前显示的视图,这对于对比测试结果和预期画面非常有用。 Calabash与Selenium WebDriver类似,但两者的主要区别在于,与桌面电脑上的Web应用交互相比,通过触摸屏与...

    Android开发教程(基础入门)

    学习如何添加监听器,捕获用户在屏幕上的触摸、按钮点击等事件,并编写相应的处理逻辑。此外,还要学习使用Adapter将数据绑定到ListView、RecyclerView等可滚动视图,实现数据的展示。 了解了基本的编程概念后,你...

    Android高级应用源码-橡皮擦与画笔的demo.zip

    - `MotionEvent`是Android中处理触摸事件的类。在`DrawView`中,你需要重写`onTouchEvent()`方法来捕获用户的触摸动作,如ACTION_DOWN、ACTION_MOVE和ACTION_UP,这些动作对应于手指触摸屏幕、移动和离开屏幕。 3....

Global site tag (gtag.js) - Google Analytics