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

相关文章

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

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

Ubuntu 24.04 LTS怎么关闭 Ubuntu Pro 更新提示弹窗?

《Ubuntu24.04LTS怎么关闭UbuntuPro更新提示弹窗?》Ubuntu每次开机都会弹窗提示安全更新,设置里最多只能取消自动下载,自动更新,但无法做到直接让自动更新的弹窗不出现,... 如果你正在使用 Ubuntu 24.04 LTS,可能会注意到——在使用「软件更新器」或运行 APT 命令时,

最便宜的8口2.5G网管交换机! 水星SE109 Pro拆机测评

《最便宜的8口2.5G网管交换机!水星SE109Pro拆机测评》水星SE109Pro价格很便宜,水星SE109Pro,外观、接口,和SE109一样,区别Pro是网管型的,下面我们就来看看详细拆... 听说水星SE109 Pro开卖了,PDD卖 220元,于是买回来javascript拆机看看。推荐阅读:水

Android WebView的加载超时处理方案

《AndroidWebView的加载超时处理方案》在Android开发中,WebView是一个常用的组件,用于在应用中嵌入网页,然而,当网络状况不佳或页面加载过慢时,用户可能会遇到加载超时的问题,本... 目录引言一、WebView加载超时的原因二、加载超时处理方案1. 使用Handler和Timer进行超

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]