博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
3.2 安卓触摸事件
阅读量:37445 次
发布时间:2020-12-04

本文共 9802 字,大约阅读时间需要 32 分钟。

文章目录

一、安卓触摸事件概述

1、触摸分类

(1)单点触摸

  • 单点触控,只能识别和支持每次一个手指的触控、点击,若同时有两个以上的点被触碰,就不能做出正确反应。很多医院、图书馆等的大厅都有这种触控技术的电脑,支持触摸屏的手机、MP3、数码相机也多采用这种单点触控技术。

(2)多点触摸

  • 多点触控(又称多重触控、多点感应、多重感应,英文MultitouchMulti-Touch)是采用人机交互技术与硬件设备共同实现的技术,能在没有传统输入设备(如鼠标、键盘等)。下进行计算机的人机交互操作。多点触摸技术,能构成一个触摸屏(屏幕,桌面,墙壁等)或触控板,都能够同时接受来自屏幕上多个点进行计算机的人机交互操作。

2、触摸动作

动作 常量
按下 MotionEvent.ACTION_DOWN
移动 MotionEvent.ACTION_MOVE
放开 MotionEvent.ACTION_UP

3、触摸监听器

  • 触摸监听器 - onTouchListener - 接口

4、触摸方法

  • onTouch()抽象 方法里,我们可以根据不同动作编写不同事件处理代码

5、触点个数与坐标

  • 通过MotionEvent对象的getX()getY()方法可以获得触摸点的坐标。如果是多点触摸,通过getPointerCount()获取触点个数,然后通过getX(pointerIndex)与getY(pointerIndex)获得某个触点的坐标。

6、安卓触摸事件处理机制

  • 触摸事件从view树的根节点开始一直传递到最下层,直到某个onTouchEvent()接收处理此事件。每个部分对触摸事件的处理过程如下:
    Activity的处理过程: Activity.dispatchTouchEvent()最先被调用,其作用是调用RootView(通常是一个ViewGroup)的dispatchTouchEvent(),即负责分发事件。ViewGroup中的dispatch会调用其他孩子的dispatchTouchEvent()。注意:Activity中的onTouchEvent()是整个View的触摸事件传递链条的终点,不过前提是整个过程中没有view的touchEvent对此事件感兴趣。
    View的处理过程: 检查是否有TouchListener()注册在这个View中,如果有则查看其是否想要消费此次事件,如果不消费事件,那么接下来该View的onTouchEvent()就要被调用了,如果未返回true,事件就会返回视图树的上一层。
  • ViewGroup的处理过程: 根据触摸发生的位置来判断哪些孩子可能会触发触摸事件,如果有重叠部分则按照被加入到ViewGroup中顺序的逆序来依次处理。ViewGroup可以引发一个中断(onInterceptTouchEvent())来强制把事件交给自己处理,当子视图的事件被剥夺时,子视图会收到ACTION_CANCEL事件,子视图可以用requestDisallowTouchIntercept()方法来屏蔽这个事件。
    由此可见,Touch事件是层层向下传递的,如果某个视图接收了此事件则接下来的视图就无法再次接收,但ViewGroup可以强制从子视图手中剥夺一个触摸事件。

二、案例演示:通过单点触摸移动米老鼠

1、创建安卓应用

在这里插入图片描述

2、准备图片素材

在这里插入图片描述

3、字符串资源文件

通过触摸移动米老鼠

4、主布局资源文件

将约束布局改成线性布局,再添加一个图像控件显示米老鼠

  • 预览效果
    在这里插入图片描述

5、主界面类实现功能

  • 声明变量和常量

    在这里插入图片描述

  • 通过资源标识符获取控件实例

    在这里插入图片描述

  • 让根布局获取焦点

    在这里插入图片描述

  • 米老鼠图像控件的布局参数

    在这里插入图片描述

  • 给线性根布局注册触摸监听器

    在这里插入图片描述

  • 完整代码

package net.ls.movemickeybytouch;import androidx.appcompat.app.AppCompatActivity;import android.annotation.SuppressLint;import android.os.Bundle;import android.util.Log;import android.view.MotionEvent;import android.view.View;import android.widget.ImageView;import android.widget.LinearLayout;public class MainActivity extends AppCompatActivity {
private ImageView ivMickey; //米老鼠图像控件 private LinearLayout root; //线性根布局 private LinearLayout.LayoutParams layoutParams; //布局参数 private static final String TAG = "move_mickey_by_touch"; //标记常量 @Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); root=findViewById(R.id.root); ivmickey = findViewById(R.id.iv_mickey); //让根布局成为焦点 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://0,触点按下 Log.d(TAG,"ACTION_DOWN("+event.getX()+","+event.getY()+")"); break; case MotionEvent.ACTION_MOVE://2,触点移动 Log.d(TAG,"ACTION_MOVE("+event.getX()+","+event.getY()+")"); break; case MotionEvent.ACTION_UP://1,触点放开 Log.d(TAG,"ACTION_UP("+event.getX()+","+event.getY()+")"); break; } // 根据变化的触点坐标来更新米老鼠图像控件的布局参数 layoutParams.leftMargin = (int) event.getX(); layoutParams.topMargin = (int) event.getY(); // 重新设置米老鼠图像控件的布局参数 ivMickey.setLayoutParams(layoutParams); return true; // 设置为true,三个事件:down-->move-->up才会依次执行 } }); }}
  • 查看效果
    在这里插入图片描述

6、优化主界面类

  • 以上代码可完成移动米老鼠的任务,但触摸中心点在左上角,现在优化代码让触摸点在米老鼠中心
    不采用图像控件的布局参数,直接调用图像控件的setX()和setY()方法,分别传入触点横坐标event.getX()和纵坐标event.getY(),如果希望触点在米老鼠控件中央,那么分别传入event.getX() - ivMickey.getWidth() / 2与event.getY() - ivMickey.getHeight() / 2
    在这里插入图片描述
package net.ls.movemickeybytouch;import androidx.appcompat.app.AppCompatActivity;import android.annotation.SuppressLint;import android.os.Bundle;import android.util.Log;import android.view.MotionEvent;import android.view.View;import android.widget.ImageView;import android.widget.LinearLayout;public class MainActivity extends AppCompatActivity {
private ImageView ivmickey; //米老鼠图像控件 private LinearLayout root; //线性根布局 private LinearLayout.LayoutParams layoutParams; //布局参数 private static final String TAG = "move_mickey_by_touch"; //标记常量 @Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); root=findViewById(R.id.root); ivmickey = findViewById(R.id.iv_mickey); //让根布局成为焦点 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://0,触点按下 Log.d(TAG,"ACTION_DOWN("+event.getX()+","+event.getY()+")"); break; case MotionEvent.ACTION_MOVE://2,触点移动 Log.d(TAG,"ACTION_MOVE("+event.getX()+","+event.getY()+")"); break; case MotionEvent.ACTION_UP://1,触点放开 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; } }); }}

7、效果

在这里插入图片描述

三、案例演示:通过多点触摸缩放米老鼠

1、创建安卓应用

  • 基于Empty Activity模板创建安卓应用 - ZoomMickeyByTouch
    在这里插入图片描述

2、准备图片素材

在这里插入图片描述

3、字符串资源文件

在这里插入图片描述

4、主布局资源文件

在这里插入图片描述

将约束布局改成线性布局,再添加一个图像控件显示米老鼠

5、主界面类实现功能

  • 声明变量

    在这里插入图片描述

  • 通过资源标识符获取控件实例,让根布局获取焦点,让根布局获取焦点

    在这里插入图片描述

  • 给根布局注册触摸监听器

    在这里插入图片描述

  • 完整代码

package net.ls.zoommickeybytouch;import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle;import android.view.MotionEvent;import android.view.View;import android.widget.ImageView;import android.widget.LinearLayout;public class MainActivity extends AppCompatActivity {
private LinearLayout root; private ImageView ivMickey; private float x1,y1;//第一个触点的坐标 private float x2,y2;//第二个触点的坐标 private float nextX1,nextY1;//第一个触点的下一次坐标 private float nextX2,nextY2;//第二个触点的下一次坐标 private float distance; //两个触点间的距离 private float nextDistance;//两个触点的下一次距离 private LinearLayout.LayoutParams layoutParams; @Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); root = findViewById(R.id.root); ivMickey = findViewById(R.id.iv_mickey); root.setFocusable(true); root.requestFocus(); layoutParams = (LinearLayout.LayoutParams) ivMickey.getLayoutParams(); //给根布局注册触摸监听器,实现触摸监听器接口,编写触摸事件方法 root.setOnTouchListener(new View.OnTouchListener() {
@Override public boolean onTouch(View v, MotionEvent event) {
//判断触点个数 if (event.getPointerCount()==1){
//单点触摸 - 移动米老鼠 layoutParams.leftMargin = (int)(event.getX() - ivMickey.getWidth()/2); layoutParams.topMargin = (int)(event.getY() - ivMickey.getHeight()/2); }else if (event.getPointerCount()==2){
//两点触摸 - 缩放米老鼠 //判断触点动作 switch (event.getAction()){
case MotionEvent.ACTION_DOWN: //获取第一个触点的坐标 x1 = event.getX(0); y1 = event.getY(0); //获取第二个触点的坐标 x2 = event.getX(1); x2 = event.getY(1); distance =(float) Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); break; case MotionEvent.ACTION_MOVE: //获取第一个触点下一次的坐标 nextX1 = event.getX(0); nextY1 = event.getY(0); //获取第二个触点下一次的坐标 nextX2 = event.getX(1); nextY2 = event.getY(1); //计算两个触点的下一次距离 nextDistance = (float) Math.sqrt((nextX1-nextX2)*(nextX1-nextX2)+(nextY1-nextY2)*(nextY1-nextY2)); break; case MotionEvent.ACTION_UP: break; } //修改米老鼠图像控件的布局参数 if (nextDistance>distance){
if (layoutParams.width<1000){
layoutParams.width = (int) (layoutParams.width*1.05); layoutParams.height = (int) (layoutParams.height*1.05);} } else {
if (layoutParams.width>10) {
layoutParams.width = (int) (layoutParams.width / 1.05); layoutParams.height = (int) (layoutParams.height / 1.05); } } //第一个触点坐标进行迭代 x1 = nextX1; y1 = nextY1; x2 = nextX2; y2 = nextY2; distance=(float) Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); } ivMickey.setLayoutParams(layoutParams); return true; } }); }}

转载地址:http://ybpowy.baihongyu.com/

你可能感兴趣的文章
linux php mkdir失败,linux – mkdir错误:参数无效
查看>>
config.php渗透,phpMyAdmin 渗透利用总结
查看>>
java list 合并 重复的数据_Java ArrayList合并并删除重复数据3种方法
查看>>
android volley 上传图片 和参数,android - 使用android中的volley将图像上传到multipart中的服务器 - 堆栈内存溢出...
查看>>
android开发的取消清空按钮,Android开发实现带清空按钮的EditText示例
查看>>
android gp服务,ArcGIS Runtime SDK for Android开发之调用GP服务(异步调用)
查看>>
mysql整体会滚_滚mysql
查看>>
向mysql数据库中添加批量数据类型_使用JDBC在MySQL数据库中快速批量插入数据
查看>>
最全的mysql 5.7.13_最全的mysql 5.7.13 安装配置方法图文教程(linux) 强烈推荐!
查看>>
mssql连接mysql数据库文件_在本地 怎么远程连接MSSQL数据库
查看>>
mssql 远程无法连接mysql_解决SQLServer远程连接失败的问题
查看>>
linux mysql c++编程_Linux下进行MYSQL的C++编程起步手记
查看>>
Maria数据库怎么复制到mysql_MySQL、MariaDB数据库的AB复制配置过程
查看>>
mysql5.6 icp mrr bak_【mysql】关于ICP、MRR、BKA等特性
查看>>
mysql utf8跟utf8mb4_MySQL utf8 和 utf8mb4 的区别
查看>>
docker mysql开机自启动_Docker学习4-学会如何让容器开机自启服务【坑】
查看>>
在mysql中删除表正确的是什么_在MySQL中删除表的操作教程
查看>>
mysql有3个共同好友_共同好友mysql
查看>>
代理查询 mysql_查询数据库代理设置
查看>>
mysql dif_mysqldiff实现MySQL数据表比较
查看>>