Android进阶之路Android开发Android技术进阶

Android之触点事件处理【教学】

2022-11-02  本文已影响0人  谁动了我的代码

知识点:

1、 Android开发中的运动事件:触摸屏(TouchScreen)和滚动球(TrackBall)

2、对运动事件的处理:MotionEvent

3、触摸时必发的三个MotionEvent动作常量:

注:一个正常的触摸事件有ACTION_DOWN开始,中间可以存在0个或几个ACTOIN_MOVE,最后以ACTION_UP结束,开始触摸-->(移动)-->停止触摸。

4、其他MotionEvent常量:

MotionEvent.ACTION_CANCEL:此事件不由用户触发,而是由系统在需要的时候触发,例如当父view打断触摸事件(onInterceptTouchEvent()返回true),从子view拿回处理事件的控制权时,就会给子view发一个ACTION_CANCEL事件,子view就再也不会收到后续事件了。

MotionEvent.ACTION_OUTSIDE:触摸超出正常UI边界时触发

MotionEvent.ACTION_SCROLL:非触摸滚动,主要由鼠标、滚轮、轨迹球触发

有多个触摸点时触发:

MotionEvent.ACTION_POINTER_DOWN:当屏幕上至少有一个点被触摸时,此事如果再新按下一个触摸点,就会触发该事件

MotionEvent.ACTION_POINTER_UP:当屏幕上至少有两个点被触摸时,松开其中的一个触摸点,该事件就会被触发

5、MotionEvent类常用的方法:

拓展:getAction()和getActionMasked()的区别:

对单点触控: getAction()返回值和getActionMasked()是相同的。对多点触控,getAction()返回值和getActionMasked()返回值稍有不同。

多点触控: 多点触控时因为增加了本次触摸的索引,所以改用16位二进制数,如0x0001,低8位代表动作类型信息,高8位代表触摸点的索引信息(触控点的位置信息)

例如: 值为0x0000,表示是第一个触控点的ACTION_DOWN操作;值是0x0100,表示是第二个触控点的ACTION_DOWN操作;第三个ACTION_DOWN操作:0x0200。

6、设置触摸事件的方式有两种:

代码如下:

1、java源码:

 1 package com.example.movetest;
 2 
 3 import android.app.Activity;
 4 import android.os.Bundle;
 5 import android.util.Log;
 6 import android.view.MotionEvent;
 7 import android.view.View;
 8 import android.view.View.OnTouchListener;
 9 import android.widget.TextView;
10 //触摸事件的处理方式二:自定义类实现OnTouchListener接口
11 public class MainActivity extends Activity{
12     TextView textView; 
13     @Override
14     protected void onCreate(Bundle savedInstanceState) {
15         super.onCreate(savedInstanceState);
16         setContentView(R.layout.activity_main);
17         textView=(TextView)findViewById(R.id.textview);
18         //设置监听:
19         textView.setOnTouchListener(new MyView());
20     }
21     
22     //自定义类实现OnTouchListener接口
23     public class MyView implements OnTouchListener{
24         @Override
25         public boolean onTouch(View arg0, MotionEvent arg1) {
26             //String string="X="+String.valueOf(arg1.getX())+",Y="+String.valueOf(arg1.getY());
27             //textView.setText(string);
28             switch (arg1.getAction()) {
29             case MotionEvent.ACTION_DOWN:
30                 textView.setText("ACTION_DOWN");
31                 break;
32             default:
33                 break;
34             }
35             return false;
36         }
37     }
38 }
39 
40 /*
41 //触摸事件处理方式一:创建OnTouchListener监听器
42 public class MainActivity extends Activity {
43     @Override
44     protected void onCreate(Bundle savedInstanceState) {
45         super.onCreate(savedInstanceState);
46         setContentView(R.layout.activity_main);
47         final TextView textView=(TextView)findViewById(R.id.textview);
48         textView.setOnTouchListener(new OnTouchListener() {
49             @Override
50             public boolean onTouch(View arg0, MotionEvent arg1) {
51                 Log.d("TAG","onTouch action"+arg1.getAction()); //打印日志
52                 //将textview显示的数据换成触摸点的位置坐标
53                 String string="X="+String.valueOf(arg1.getX())+",Y="+String.valueOf(arg1.getY());
54                 textView.setText(string);//重置TextView文本显示
55                 return false;
56             }
57         });
58     }
59 }
60 */ 

2、activity_main.xml代码如下:

 1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:tools="http://schemas.android.com/tools"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:paddingBottom="@dimen/activity_vertical_margin"
 6     android:paddingLeft="@dimen/activity_horizontal_margin"
 7     android:paddingRight="@dimen/activity_horizontal_margin"
 8     android:paddingTop="@dimen/activity_vertical_margin"
 9     tools:context="com.example.movetest.MainActivity" >
10 
11     <TextView
12         android:id="@+id/textview"
13         android:layout_width="wrap_content"
14         android:layout_height="wrap_content"
15         android:text="触摸事件" />
16 
17 </RelativeLayout>

3、AndroidManifest.xml代码:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.movetest"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="18"
        android:targetSdkVersion="22" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

教学案例——通过单点触摸移动米老鼠

(一)运行效果

(二)涉及知识点

1、线性布局(LinearLayout) 2、图像视图(ImageView) 3、单点触摸事件(MotionEvent…getX(), getY())

(三)实现步骤

1、创建安卓应用【MoveMickeyByTouch】

2、准备背景图片与米老鼠图片,拷贝到drawable目录里

3、布局资源文件activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/root"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="@drawable/background" >

    <ImageView
        android:id="@+id/ivMickey"
        android:layout_width="100dp"
        android:layout_height="120dp"
        android:scaleType="fitXY"
        android:src="@drawable/mickey" />

</LinearLayout>

4、主界面类MainActivity

package net.hw.movemickey;

import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;

import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {
    protected static final String TAG = "move_mickey_by_touch";
    private ImageView ivMickey;
    private LinearLayout root;
    private LinearLayout.LayoutParams LayoutParams;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 利用布局资源文件设置用户界面
        setContentView(R.layout.activity_main);

        // 通过控件资源索引获得控件实例
        ivMickey = (ImageView) findViewById(R.id.ivMickey);
        root = (LinearLayout) findViewById(R.id.root);

        // 设置根布局可以获得焦点
        root.setFocusable(true);
        // 让根布局获得焦点
        root.requestFocus();

        // 获取图像控件的布局参数
        LayoutParams = (LinearLayout.LayoutParams) ivMickey.getLayoutParams();

        // 给根布局注册触摸监听器,实现触摸监听器接口,编写触摸事件代码
        root.setOnTouchListener(new View.OnTouchListener() {

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                // 根据触摸动作执行不同的操作
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN: // 触点按下
                        Log.d(TAG, "ACTION_DOWN(" + event.getX() + ", " + event.getY() + ")");
                        break;
                    case MotionEvent.ACTION_MOVE: // 触点移动
                        Log.d(TAG, "ACTION_MOVE(" + event.getX() + ", " + event.getY() + ")");
                        break;
                    case MotionEvent.ACTION_UP: // 触点放开
                        Log.d(TAG, "ACTION_UP(" + event.getX() + ", " + event.getY() + ")");
                }

                // 根据变化的触点坐标来更新图像控件的布局参数
                LayoutParams.leftMargin = (int) event.getX();
                LayoutParams.topMargin = (int) event.getY();

                // 重新设置图像控件的布局参数
                ivMickey.setLayoutParams(LayoutParams);

                return true; // 设置为真,三个事件:down-->move-->up才会依次执行
            }
        });
    }
}

5、启动应用,查看效果

启动后,米老鼠在屏幕左上角


在模拟器屏幕上,按下鼠标,移动鼠标,放开鼠标,之后在LogCat里可以看到上述上述三种动作的位置坐标。


录屏演示单点触摸移动米老鼠


从录屏动画可以看到,移动鼠标,确实可以让米老鼠跟着动起来,但是有一个体验不好,就是触点与米老鼠隔了一段距离,这个问题应该如何解决呢?同学们,先试一试,看看能否搞定。

6、修改主界面类MainActivity

7、启动应用,查看效果

从录屏动画可以看到,移动鼠标,确实可以让米老鼠跟着动起来,但触点是在米老鼠的左上角,怎么让触点在米老鼠的中心位置呢?

8、修改主界面类MainActivity

9、启动应用,查看效果

10、查看修改后的主界面源代码

采用图像控件的setX()和setY()方法来修改图像控件的位置,因此关于布局参数的代码就可以删除了。

package net.hw.movemickey;

import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;

import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "move_mickey_by_touch";
    private ImageView ivMickey;
    private LinearLayout root;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 利用布局资源文件设置用户界面
        setContentView(R.layout.activity_main);
    
        // 通过控件资源标识符获取控件实例
        ivMickey = findViewById(R.id.ivMickey);
        root = findViewById(R.id.root);
    
        // 设置根布局可以获得焦点
        root.setFocusable(true);
        // 让根布局获取焦点
        root.requestFocus();
    
        // 给根布局注册触摸监听器,实现触摸监听器接口,编写触摸事件代码
        root.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent event) {
                // 根据触摸动作执行不同的操作
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN: // 触点按下
                        Log.d(TAG, "ACTION_DOWN(" +event.getX() + ", " + event.getY() +")");
                        break;
                    case MotionEvent.ACTION_MOVE: // 触点移动
                        Log.d(TAG, "ACTION_MOVE(" +event.getX() + ", " + event.getY() +")");
                        break;
                    case MotionEvent.ACTION_UP: // 触点放开
                        Log.d(TAG, "ACTION_UP(" +event.getX() + ", " + event.getY() +")");
                        break;
                }
    
                // 设置图像控件的坐标
                ivMickey.setX(event.getX() - ivMickey.getWidth() / 2);
                ivMickey.setY(event.getY() - ivMickey.getHeight() / 2);
    
                return true; // 设置为真,三个事件:down-->move-->up才会依次执行
            }
        });
    }
}

教学案例 —— 通过多点触摸缩放米老鼠

(一)运行效果

(二)涉及知识点

1、线性布局(LinearLayout) 2、图像视图(ImageView) 3、多点触摸事件(MotionEvent…getX(pointerIndex)、getY(pointerIndex))

(三)实现步骤

1、创建安卓应用【ZoomMickeyByTouch】

2、准备背景图片与米老鼠图片,拷贝到drawable目录里

3、主布局资源文件activity_main.xml

4、主界面类MainActivity

声明变量

实例化控件

设置根布局

获取图像控件的布局参数

给根布局注册触摸监听器

5、运行程序,查看结果

以上就是Android开发中的触点事件处理过程学习了。如有其他问题可以点下方链接,
传送直达↓↓↓ https://docs.qq.com/doc/DUkNRVFFzTG96VHNi

文末

触摸事件肯定要先捕获才能传给窗口,因此,首先应该有一个线程在不断的监听屏幕,一旦有触摸事件,就将事件捕获;其次,还应该存在某种手段可以找到目标窗口,因为可能有多个APP的多个界面为用户可见,必须确定这个事件究竟通知那个窗口;最后才是目标窗口如何消费事件的问题。

上一篇下一篇

猜你喜欢

热点阅读