Pro Android学习笔记(一四二):触摸屏(1):MotionEvents

2024-01-28 12:08

本文主要是介绍Pro Android学习笔记(一四二):触摸屏(1):MotionEvents,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章转载只能用于非商业性质,且不能带有虚拟货币、积分、注册等附加条件。转载须注明出处http://blog.csdn.net/flowingflying/以及作者@恺风Wei。


MotionEvent对象用于告诉APP用户正在如何使用触摸屏幕。我们可以为view设置触摸回调函数,而view本身也带有触摸回调函数。

为view设置触摸回调函数onTouch()

public class MainActivity extends Activity implements OnTouchListener{
   @Override 
    protected void onCreate(Bundle savedInstanceState) {  
        ……             
        RelativeLayout layout1 = (RelativeLayout)findViewById(R.id.layout1);
        layout1.setOnTouchListener(this);          
        Button trueButton1 = (Button)findViewById(R.id.trueButton1);
        trueButton1.setOnTouchListener(this);        
    } 

    @Override //onTouchListener的回调函数onTouch()
    public boolean onTouch(View v, MotionEvent event)
 { 
        String tag = v.getTag().toString();  //在layout xml中设置android:tag属性,可通过getTag()获取 
        Log.i(tag,"Got view " + v.getTag().toString() + " in touch");
        Log.i(tag,MainActivity.describeEvent(v, event)); 
        return super.onTouchEvent(event);
 
    }    
}

自定义view,重写触摸回调函数onTouchEvent()

public class MyButton extends Button
    protected boolean myValue = false;  
     
    public BooleanButton(Context context, AttributeSet as){ 
        super(context,as); 
    } 

    @Override //对TextView的onTouchEvent()重写
    public boolean onTouchEvent(MotionEvent event) {
  
        String tag = this.getTag().toString();  
        Log.d(tag,MainActivity.describeEvent(this, event));  
        Log.d(tag,"Now return " + myValue);          
        return myValue; 
    }  
    
}

我们可以在layout xml中使用自定义的MyButton,方式如下:

<cn.wei.flowingflying.testtouchscreen.MyButton android:id="@+id/trueButton1"
            android:text="Return true" 
            android:layout_width="wrap_content" 
            android:layout_height="wrap_content" 
            android:tag="trueButtonTop" />

MotionEvent可获取的信息

当用户触摸屏幕是,会生成一个MotionEvent对象,含有触摸的信息,应用可以获得这个对象,例如自定义控件中的onTouchEvent()。MotionEvent可以获得很多信息,包括动作类型,如ACTION_DOWN等,触摸的位置,触摸相应的时间,触摸的压力,触摸的大小。前面的小例子中通过静态函数MainActivity.describeEvent(v, event)来显示详细信息,下面是相关代码:

protected static String describeEvent(View view, MotionEvent event) { 
    String result = "Action: " + getActionName(event.getAction()) + "\n"
            + "Location: " + event.getX() + "," + event.getY() + "\n"; // X,Y是距离view左上角的值
     
    if(event.getX() < 0 || event.getX() > view.getWidth() || event.getY() < 0 || event.getY() > view.getHeight()){
        result += ">>> Touch has left the view <<<\n" ; 
    } 
    /*【1】getEdgeFlags()获取是否触摸到触屏的边框,但是这个可能永远返回0,例如模拟器和某些手机。在编程中,我们不能依赖这个值,可以自行通过位置计算,通过setEdgeFlage()来设定flags。
     *【2】压力和size的范围是0-1,每款设备的检测值有差异,每个绝对值并没有具体的衡量,很难说0.8以上的就是压力大,某款设备可能检测值不会有0.8以上,所有这些数值最好是自己和自己进行比较,获知轻重的变化。在某款手机上,size的值一直为0。*/ 
    result += "Edge Flag: " + event.getEdgeFlags() + "\n"
            + "Pressure : " + event.getPressure() + "\n" 
            + "Size : " + event.getSize() + "\n"   
            + "Down time :" + event.getDownTime() + "ms\n" 
            + "Event time :" + event.getEventTime() + "ms\n" 
            + "Eclapsed: " + (event.getEventTime() - event.getDownTime()) + "ms\n";
    
    return result; 


private static String getActionName(int code){      
    if(code == MotionEvent.ACTION_DOWN) 
        return "ACTION_DOWN"; 
    
    if(code == MotionEvent.ACTION_MOVE) 
        return "ACTION_MOVE";      
    ……     
    return ""+code; 
}
 

当手指在某个view中按下,移动,离开,将会依次触发ACTION_DOWN,ACTION_MOVE(0~N个)和ACTION_UP。从DOWN开始,到UP结束,这是一组动作,event.getDownTime()给出的时间是一样的,我们可以通过当前时间event.getEventTime()进行比对,获得动作的持续时间。

除了这三个常见动作事件外,还有ACTION_CANCEL和ACTION_OUTSIDE。

触发的逻辑

用户的一个动作实际是可以分解为若干小动作处理,这一系列动作,从Down开始,在MotionEvent中具有getDownTime(),一般以Up结束。每个事件发生时,可能会有若干个回调函数,这些回调函数是有缺省的顺序,如果回调函数返回false,将触发事件传递到下一个回调函数进行处理,如果回调函数返回true,说明已经全部处理完,不在继续向下传递。这里比较特别的是,如果是最后一个回调函数,如果返回false,则下一个动作不会触发,因此,如果我们明确已经全部处理完,则返回true,否则返回super处理方法的值。

例子说明

以我们之前的代码为例,有一个自定义的button在RelativeLayout上,通过setTouchListener()为这个view都设置了触摸监听器,这个自定义的button,重写了onTouchEvent()。用户按button,触发的顺序如下:

通过setTouchListener()注册的监听器优先于view的onTouchEvent()。如果view在某个view group中,view的触摸触发优先于view group的触摸触发。

如果传递到RelativeLayout的onTouch(),我们看到Event的Y坐标有变化,因为Layout的左上角和Button的左上角位置不同。

如果我们在手指Button出按下,然后滑出Button,然后离开屏幕,这属于一个动作。我们会看到ACTION_DOWN,然后很多ACTION_MOVE,以及最后的ACTION_UP。在这个连续动作中,即使我们的手指已经滑出Button,我们仍可以在Button.onTouch()和Button.onTouchEvent()收到MotionEvent。通过检查具体的X、Y值,可判断是否离开view。无论手指滑到哪里,ACTION_DOWN顺序触发的各回调方法,是接下来这动作组的其他动作触发的顺序。例如我们有两个RelativeLayout,手指从其中要给滑到另一个,因为一开始ACTION_DOWN是在第一个RelativeLayout,所以只会触发到第一个RelativeLayout的回调函数,不会触发到第二个RelativeLayout的触屏回调函数。

一般而言,如果自定义view,我们返回super.onTouchEvent()即可。例如自定义Button,实际上Button接收到DOWN的时候,会改变Button的颜色,而UP的时候,再次变回来,因此需要提供Button缺省的处理。如果,我们确定不将其继续往下传递,可以在return true;之前增加super.onTouchEvent()的处理。如果我们在Button onTouch()就返回true,我们是不会看到Button的颜色有变化,当然我们可以添加view.onTouchEvent(event)来处理,或直接return view.onTouchEvent(event)。

安装会从AndroidManifest中获知信息,如果应用必须要求支持触摸,我们以加上说明。一些运行Android的机顶盒以TV作为屏幕,而TV是不支持触摸屏。

<uses-configuration android:reqTouchScreen="finger" />

android:onClick和触屏回调函数的关系

我们可以在layout.xml文件中对Button控件加入android:onClick=“doClick”,来跟踪按Button的情况。doClick()将在Button的ACTION_UP事件后触发,但是前提是:1、能收到ACTION_UP事件,而且范围在Button内(不滑出);2、能执行button.onTouchEvent(),如果我们重写该方法,要确保执行super.onTouchEvent();

相关小例子代码:Pro Android学习:touch screen小例子

这篇关于Pro Android学习笔记(一四二):触摸屏(1):MotionEvents的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/653589

相关文章

Java进阶学习之如何开启远程调式

《Java进阶学习之如何开启远程调式》Java开发中的远程调试是一项至关重要的技能,特别是在处理生产环境的问题或者协作开发时,:本文主要介绍Java进阶学习之如何开启远程调式的相关资料,需要的朋友... 目录概述Java远程调试的开启与底层原理开启Java远程调试底层原理JVM参数总结&nbsMbKKXJx

Android WebView无法加载H5页面的常见问题和解决方法

《AndroidWebView无法加载H5页面的常见问题和解决方法》AndroidWebView是一种视图组件,使得Android应用能够显示网页内容,它基于Chromium,具备现代浏览器的许多功... 目录1. WebView 简介2. 常见问题3. 网络权限设置4. 启用 JavaScript5. D

Android如何获取当前CPU频率和占用率

《Android如何获取当前CPU频率和占用率》最近在优化App的性能,需要获取当前CPU视频频率和占用率,所以本文小编就来和大家总结一下如何在Android中获取当前CPU频率和占用率吧... 最近在优化 App 的性能,需要获取当前 CPU视频频率和占用率,通过查询资料,大致思路如下:目前没有标准的

Android开发中gradle下载缓慢的问题级解决方法

《Android开发中gradle下载缓慢的问题级解决方法》本文介绍了解决Android开发中Gradle下载缓慢问题的几种方法,本文给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录一、网络环境优化二、Gradle版本与配置优化三、其他优化措施针对android开发中Gradle下载缓慢的问

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

Android里面的Service种类以及启动方式

《Android里面的Service种类以及启动方式》Android中的Service分为前台服务和后台服务,前台服务需要亮身份牌并显示通知,后台服务则有启动方式选择,包括startService和b... 目录一句话总结:一、Service 的两种类型:1. 前台服务(必须亮身份牌)2. 后台服务(偷偷干

Java深度学习库DJL实现Python的NumPy方式

《Java深度学习库DJL实现Python的NumPy方式》本文介绍了DJL库的背景和基本功能,包括NDArray的创建、数学运算、数据获取和设置等,同时,还展示了如何使用NDArray进行数据预处理... 目录1 NDArray 的背景介绍1.1 架构2 JavaDJL使用2.1 安装DJL2.2 基本操

如何在本地部署 DeepSeek Janus Pro 文生图大模型

《如何在本地部署DeepSeekJanusPro文生图大模型》DeepSeekJanusPro模型在本地成功部署,支持图片理解和文生图功能,通过Gradio界面进行交互,展示了其强大的多模态处... 目录什么是 Janus Pro1. 安装 conda2. 创建 python 虚拟环境3. 克隆 janus

Android kotlin语言实现删除文件的解决方案

《Androidkotlin语言实现删除文件的解决方案》:本文主要介绍Androidkotlin语言实现删除文件的解决方案,在项目开发过程中,尤其是需要跨平台协作的项目,那么删除用户指定的文件的... 目录一、前言二、适用环境三、模板内容1.权限申请2.Activity中的模板一、前言在项目开发过程中,尤

Android数据库Room的实际使用过程总结

《Android数据库Room的实际使用过程总结》这篇文章主要给大家介绍了关于Android数据库Room的实际使用过程,详细介绍了如何创建实体类、数据访问对象(DAO)和数据库抽象类,需要的朋友可以... 目录前言一、Room的基本使用1.项目配置2.创建实体类(Entity)3.创建数据访问对象(DAO