您的位置:华清远见教育科技集团 >> Android资料 >> Android触摸事件处理  
 
Android触摸事件处理
分享到:

Android界面框架支持对触摸事件的监听,并能够将触摸事件的详细信息传递给处理方法,不过需要设置触摸事件的监听器,并重载onTouch ()方法。

设置触摸事件的监听器,并重载onTouch ()方法的代码如代码清单1所示。

代码清单1 设置触摸事件的监听器,并重载onTouch ()方法

touchView.setOnTouchListener(new View.OnTouchListener(){
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        //过程代码…
        return true/false;
    }

在上述代码中,第1行代码是设置控件的触摸事件监听器;在第3行的onTouch()方法中,第1个参数View表示产生触摸事件的界面控件;第2个参数MontionEvent表示触摸事件的详细信息,如产生时间、坐标和触点压力等;第5行是onTouch()方法的返回值。

TouchEventDemo是一个说明如何处理触摸事件的示例,TouchEventDemo用户界面如图1所示。


图1 TouchEventDemo用户界面

由图1可以看出,上半部分的浅蓝色区域是可以接受触摸事件的区域,用户可以在Android模拟器中使用鼠标点击屏幕用以模拟触摸手机屏幕;下方黑色区域是显示区域,用来显示触摸事件类型、相对坐标、绝对坐标、触点压力、触点尺寸和历史数据量等信息。

在用户界面中使用了线性布局,并加入了3个TextView控件:第1个TextView(ID为touch_area)用来标识触摸事件的测试区域;第2个TextView(ID为history_label)用来显示触摸事件的历史数据量;第3个TextView(ID为event_label)用来显示触摸事件的详细信息,包括类型、相对坐标、绝对坐标、触点压力和触点尺寸。

XML文件的代码如代码清单2所示。

代码清单2 XML文件

<?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="//schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView android:id="@+id/touch_area"
        android:layout_width="match_parent"
        android:layout_height="300dip"
        android:background="#80A0FF "
        android:textColor="#FFFFFF"
        android:text="触摸事件测试区域">
    </TextView>
        <TextView android:id="@+id/history_label"
                            android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="历史数据量:" >
    </TextView>
    <TextView android:id="@+id/event_label"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="触摸事件:" >
    </TextView>
    </LinearLayout>

在上述代码中,第9行代码定义了TextView的背景颜色,#80A0FF是颜色代码;第10行代码定义了TextView的字体颜色。

在代码中为了能够引用XML文件中声明的界面元素,使用了代码清单3所示的代码。

代码清单3 在代码中引用XML文件中声明的界面元素

TextView labelView = null;
    labelView = (TextView)findViewById(R.id.event_label);
    TextView touchView = (TextView)findViewById(R.id.touch_area);
    final TextView historyView = (TextView)findViewById(R.id.history_label);

当手指接触到触摸屏、在触摸屏上移动或离开触摸屏时,分别会引发ACTION_DOWN、ACTION_UP和ACTION_MOVE触摸事件,而无论是哪种触摸事件,都会调用onTouch()方法进行处理。事件类型包含在onTouch()方法的MotionEvent参数中,可以通过getAction()方法获取到触摸事件的类型,然后根据触摸事件的不同类型进行不同的处理。为了能够使屏幕上方的TextView处理触摸事件,需要使用setOnTouchListener()方法在代码中设置触摸事件监听器,并在onTouch()方法添加触摸事件的处理过程。代码如代码清单4所示。

代码清单4 onTouch()

touchView.setOnTouchListener(new View.OnTouchListener(){
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            int action = event.getAction();
            switch (action) {
                case (MotionEvent.ACTION_DOWN):
                Display("ACTION_DOWN",event);
                break;
                case (MotionEvent.ACTION_UP):
                int historySize = ProcessHistory(event);
                historyView.setText("历史数据量:"+historySize);
                Display("ACTION_UP",event);
                break;
                case (MotionEvent.ACTION_MOVE):
                Display("ACTION_MOVE",event);
                break;
            }
            return true;
        }
    });

第7行代码的Display()是一个自定义方法,主要用来显示触摸事件的详细信息,方法的代码和含义将在后面进行介绍;第10行代码的ProcessHistory()也是一个自定义方法,用来处理触摸事件的历史数据;第11行代码是使用TextView显示历史数据的数量。

MotionEvent参数中不仅有触摸事件的类型信息,还有触点的坐标信息,获取方式是使用getX()和getY()方法,这两个方法获取到的是触点相对于父界面元素的坐标信息。如果需要获取绝对坐标信息,则可使用getRawX()和getRawY()方法。

触点压力是一个介于0和1之间的浮点数,用来表示用户对触摸屏施加压力的大小,接近0表示压力较小,接近1表示压力较大,获取触摸事件触点压力的方式是调用getPressure()方法。

触点尺寸指用户接触触摸屏的接触点大小,也是一个介于0和1之间的浮点数,接近0表示尺寸较小,接近1表示尺寸较大,可以使用getSize()方法获取。

Display()将MotionEvent参数中的事件信息提取出来,并显示在用户界面上。代码如代码清单5所示。

代码清单5 Display()

private void Display(String eventType, MotionEvent event){
        int x = (int)event.getX();
        int y = (int)event.getY();
        float pressure = event.getPressure();
        float size = event.getSize();
        int RawX = (int)event.getRawX();
        int RawY = (int)event.getRawY();
        String msg = "";
        msg += "事件类型:" + eventType + "\n";
        msg += "相对坐标:"+String.valueOf(x)+","+String.valueOf(y)+"\n";
        msg += "绝对坐标:"+String.valueOf(RawX)+","+String.valueOf(RawY)+"\n";
        msg += "触点压力:"+String.valueOf(pressure)+", ";
        msg += "触点尺寸:"+String.valueOf(size)+"\n";
        labelView.setText(msg);
    }

一般情况下,如果用户将手指放在触摸屏上,但不移动,然后抬起手指,应先后产生ACTION_DOWN和ACTION_UP两个触摸事件。但如果用户在屏幕上移动手指,然后再抬起手指,则会产生这样的事件序列:ACTION_DOWN → ACTION_MOVE → ACTION_MOVE → ACTION_MOVE → …→ ACTION_UP。

在手机上运行的应用程序,效率是非常重要的。如果Android界面框架不能产生足够多的触摸事件,则应用程序就不能够很精确地描绘触摸屏上的触摸轨迹。如果Android界面框架产生了过多的触摸事件,虽然能够满足精度的要求,但也降低了应用程序效率。

针对以上问题Android界面框架使用了“打包”的解决方法。在触点移动速度较快时会产生大量的数据,每经过一定的时间间隔便会产生一个ACTION_MOVE事件,在这个事件中,除了有当前触点的相关信息外,还包含这段时间间隔内触点轨迹的历史数据信息,这样既能够保持精度,又不至于产生过多的触摸事件。

通常情况下,在ACTION_MOVE的事件处理方法中,都先处理历史数据,然后再处理当前数据,代码如代码清单6所示。

代码清单6 ProcessHistory(MotionEvent event)

private int ProcessHistory(MotionEvent event)
    {
        int historySize = event.getHistorySize();
        for (int i = 0; i < historySize; i++) {
            long time = event.getHistoricalEventTime(i);
            float pressure = event.getHistoricalPressure(i);
            float x = event.getHistoricalX(i);
            float y = event.getHistoricalY(i);
            float size = event.getHistoricalSize(i);
            // 处理过程…
        }
        return historySize;
    }

在上述代码中,第3行代码获取了历史数据的数量;然后在第4行至12行中循环处理这些历史数据;第5行代码获取了历史事件的发生时间;第6行代码获取历史事件的触点压力;第7行和第8行代码获取历史事件的相对坐标;第9行获取历史事件的触点尺寸;在第14行返回历史数据的数量,主要是用于界面显示。

注:Android模拟器并不支持触点压力和触点尺寸的模拟,所有触点压力恒为1.0,触点尺寸恒为0.0。同时,Android模拟器上也无法产生历史数据,因此历史数据量一直显示为0。

 更多相关文章

·Android按键事件处理过程详解
·Android系统菜单之快捷菜单
·Android系统菜单之子菜单
·Android系统菜单之选项菜单
·Android系统控件TabHost