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.
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~
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); } }