[Android event processing] TouchListener PK OnTouchEvent + multi touch

Posted by feelay on Tue, 01 Feb 2022 23:09:03 +0100

TouchListener PK OnTouchEvent + multi touch

Introduction to this section

For example, this section brings you the comparison between TouchListener and OnTouchEvent, as well as the knowledge points of multi touch!

TouchListener is based on listening, while OnTouchEvent is based on callback!

Here are two simple examples to deepen your understanding!

1. TouchListener based on monitoring

Code example

Implementation effect diagram:

Implementation code: main xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    xmlns:tools="http://schemas.android.com/tools"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    android:paddingLeft="@dimen/activity_horizontal_margin"  
    android:paddingRight="@dimen/activity_horizontal_margin"  
    android:paddingTop="@dimen/activity_vertical_margin"  
    android:paddingBottom="@dimen/activity_vertical_margin"  
    tools:context=".MyActivity">  
  
    <ImageView  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:id="@+id/imgtouch"  
        android:background="@drawable/touch"/>  
</RelativeLayout> 

MainAcitivity.java

public class MyActivity extends ActionBarActivity {  
  
    // Declaration component
    private ImageView imgtouch;  
  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_my);  
        // Get component
        imgtouch = (ImageView)findViewById(R.id.imgtouch);  
        // Add setOnTouchListener listener
        imgtouch.setOnTouchListener(new View.OnTouchListener() {  
            @Override  
            public boolean onTouch(View v, MotionEvent event) {  
                Toast.makeText(getApplicationContext(),"You pass listener mode:OnTouchListener Touched the picture
                               ~",Toast.LENGTH_LONG).show();  
                return true;  
            }  
        });  
    }  
}

Code analysis:

Simply set an ImageView, setOnTouchListener and override the onTouch method! Very simple. In fact, there is an example in the section of frame layout.

Back to top

OnTouchListener related methods and properties

onTouch(View v, MotionEvent event): the parameters in this sequence are the components that trigger the touch event. The touch event encapsulates the details of the trigger event, including the event type, trigger time and other information. For example, event getX(),event. getY()
We can also judge the action type of touch, using event Getaction() to judge; For example:
event.getAction == MotionEvent.ACTION_DOWN: press event
event.getAction == MotionEvent.ACTION_MOVE: move event
event.getAction == MotionEvent.ACTION_UP: pop up event

2. onTouchEvent() method based on callback

It is also a touch event, but onTouchEvent is more used for customized views. This method is rewritten in all view classes, and this touch event is based on callback, that is, if the value returned is false, the event will continue to propagate outward and be processed by the external container or Activity! Of course, it also involves gesture, which we will explain in detail later! onTouchEvent is actually similar to onTouchListener, but the processing mechanism is not used. The former is callback and the latter is listening mode!

Code example: define a simple view and draw a small blue circle that can follow your fingers

Implementation code: MyView java

public class MyView extends View{  
    public float X = 50;  
    public float Y = 50;  
  
    //Create brush  
    Paint paint = new Paint();  
  
    public MyView(Context context,AttributeSet set){  
        super(context,set);  
    }  
  
    @Override  
    public void onDraw(Canvas canvas) {  
        super.onDraw(canvas); 
        // Set color
        paint.setColor(Color.BLUE);  
        // Draw a small circle
        canvas.drawCircle(X,Y,30,paint);  
    }  
  
    // onTouchEvent callback method
    @Override  
    public boolean onTouchEvent(MotionEvent event) {  
        this.X = event.getX();  
        this.Y = event.getY();  
        //Notify components to redraw  
        this.invalidate();  
        return true;  
    }  
}

main.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    xmlns:tools="http://schemas.android.com/tools"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    tools:context=".MyActivity">  
    <example.jay.com.touch2.MyView  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content" />  
</RelativeLayout> 

Implementation effect diagram:

Touch with your fingers to move~

Back to top

3. Multi touch

Principles

The so-called multi touch means that multiple fingers operate on the screen. It is estimated that the most used function is the zoom in and zoom out function. For example, many image browsers support zoom! Theoretically, the Android system itself can handle the touch of up to 256 fingers, which of course depends on the support of mobile phone hardware; However, mobile phones that support multi touch generally support 2-4 points, of course, some more! We found that MotionEvent is useful for the first two points. MotionEvent represents a touch event; Before, we can according to

event. getAction() & MotionEvent. ACTION_ In addition to the three single point operations described above, there are two multi-point special operations:

  • MotionEvent.ACTION_POINTER_DOWN: triggered when a point on the screen has been pressed and held, and then other points are pressed.
  • MotionEvent.ACTION_POINTER_UP: triggered when multiple points on the screen are pressed and released (i.e. not when the last point is released).

The simple process is as follows:

  • When we touch the screen with one finger - > trigger ACTION_DOWN event
  • Then another finger also touches the screen - > trigger action_ POINTER_ The down event will continue to be triggered if there are other finger touches
  • One finger leaves the screen - > trigger action_ POINTER_ The up event continues to be triggered when a finger leaves
  • When the last finger leaves the screen - > trigger ACTION_UP event
  • And in the whole process, action_ The move event will be triggered continuously

We can use event GeTx (int) or event Gety (int) to get the location of different touch points: such as event GeTx (0) can obtain the X coordinate of the first contact point, event GeTx (1) obtains the X coordinate of the second contact point, so... In addition, we can call the getPointerCount() method of MotionEvent object to judge how many fingers are touching at present~

Code example

Well, let's write an example of the most common one finger drag picture and two finger zoom picture:

Implementation effect diagram:

Implementation code:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <ImageView
        android:id="@+id/img_test"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="matrix"
        android:src="@drawable/pic1" />

</RelativeLayout>

MainActivity.java

package com.jay.example.edittextdemo;

import android.app.Activity;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.os.Bundle;
import android.util.FloatMath;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ImageView;

public class MainActivity extends Activity implements OnTouchListener {

    private ImageView img_test;

    // Zoom control
    private Matrix matrix = new Matrix();
    private Matrix savedMatrix = new Matrix();

    // Representation of different states:
    private static final int NONE = 0;
    private static final int DRAG = 1;
    private static final int ZOOM = 2;
    private int mode = NONE;

    // Define the first pressing point, the focus of the two contact points, and the initial pressing distance of the two fingers:
    private PointF startPoint = new PointF();
    private PointF midPoint = new PointF();
    private float oriDis = 1f;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // Get component
        img_test = (ImageView) this.findViewById(R.id.img_test);
        // Set listening
        img_test.setOnTouchListener(this);
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        ImageView view = (ImageView) v;
        switch (event.getAction() & MotionEvent.ACTION_MASK) {
        // Single finger
        case MotionEvent.ACTION_DOWN:
            matrix.set(view.getImageMatrix());
            savedMatrix.set(matrix);
            startPoint.set(event.getX(), event.getY());
            mode = DRAG;
            break;
        // Double finger
        case MotionEvent.ACTION_POINTER_DOWN:
            oriDis = distance(event);
            if (oriDis > 10f) {
                savedMatrix.set(matrix);
                midPoint = middle(event);
                mode = ZOOM;
            }
            break;
        // Finger release
        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_POINTER_UP:
            mode = NONE;
            break;
        // Single finger sliding event
        case MotionEvent.ACTION_MOVE:
            if (mode == DRAG) {
                // It's a finger drag
                matrix.set(savedMatrix);
                matrix.postTranslate(event.getX() - startPoint.x, event.getY() - startPoint.y);
            } else if (mode == ZOOM) {
                // Two fingers sliding
                float newDist = distance(event);
                if (newDist > 10f) {
                    matrix.set(savedMatrix);
                    float scale = newDist / oriDis;
                    matrix.postScale(scale, scale, midPoint.x, midPoint.y);
                }
            }
            break;
        }
        // Set the Matrix of ImageView
        view.setImageMatrix(matrix);
        return true;
    }

    // Calculate the distance between two touch points
    private float distance(MotionEvent event) {
        float x = event.getX(0) - event.getX(1);
        float y = event.getY(0) - event.getY(1);
        return FloatMath.sqrt(x * x + y * y);
    }

    // Calculate the midpoint of the two touch points
    private PointF middle(MotionEvent event) {
        float x = event.getX(0) + event.getX(1);
        float y = event.getY(0) + event.getY(1);
        return new PointF(x / 2, y / 2);
    }

}

Back to top

Topics: Android