Introduction à cette section :
Comme le titre l'indique, cette section vous présenteTouchListeneretOnTouchEventune comparaison, ainsi que les notions de multi-touch ! TouchListener est basé sur l'écoute, tandis que OnTouchEvent est basé sur les callbacks ! Ci-dessous, nous utiliserons deux exemples simples pour approfondir la compréhension de chacun !
1. TouchListener basé sur un listener
Exemple de code :
Schéma de l'effet d'implémentation :

Code d'implémentation : 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 {
private ImageView imgtouch;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
imgtouch = (ImageView)findViewById(R.id.imgtouch);
imgtouch.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
Toast.makeText(getApplicationContext(),"你通过监听器模式:OnTouchListener摸了伦家~",Toast.LENGTH_LONG).show();
return true;
}
});
}
}
Analyse du code :
Il suffit de configurer un ImageView, puis d'appeler setOnTouchListener et de redéfinir la méthode onTouch ! C'est très simple. En fait, il y avait déjà un exemple de ceci dans la section FrameLayout. Vous souvenez-vous de la jolie fille qui se déplace avec votre doigt ?
Méthodes et propriétés liées à OnTouchListener :
onTouch(View v, MotionEvent event) : Les paramètres ici sont respectivement le composant qui a déclenché l'événement tactile, et l'événement tactile `event` qui encapsule les informations détaillées de l'événement déclencheur, notamment le type d'événement, l'heure de déclenchement et d'autres informations. Par exemple, event.getX(), event.getY().
Nous pouvons également déterminer le type d'action tactile en utilisant event.getAction() pour le juger ; par exemple :
event.getAction == MotionEvent.ACTION_DOWN: Événement d'appui (ACTION_DOWN)
event.getAction == MotionEvent.ACTION_MOVE: Événement de déplacement (ACTION_MOVE)
event.getAction == MotionEvent.ACTION_UP: Événement de relâchement (ACTION_UP)
2. Méthode onTouchEvent() basée sur un rappel
C'est aussi un événement tactile, mais onTouchEvent est plus souvent utilisé dans les vues personnalisées. Toutes les classes de vue redéfinissent cette méthode, et cet événement tactile est basé sur un rappel. Autrement dit, si nous renvoyons false, l'événement continuera à se propager vers l'extérieur et sera géré par le conteneur externe ou l'Activity ! Bien sûr, cela implique aussi les gestes (Gesture), que nous expliquerons en détail plus tard ! onTouchEvent est en fait similaire à onTouchListener, sauf que le mécanisme de gestion est différent : le premier est basé sur un rappel, tandis que le second est basé sur un écouteur !
Exemple de code :Définissez une vue simple qui dessine un petit cercle bleu pouvant suivre le doigt pour se déplacer
Code d'implémentation : MyView.java
public class MyView extends View{
public float X = 50;
public float Y = 50;
//创建画笔
Paint paint = new Paint();
public MyView(Context context,AttributeSet set)
{
super(context,set);
}
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint.setColor(Color.BLUE);
canvas.drawCircle(X,Y,30,paint);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
this.X = event.getX();
this.Y = event.getY();
//通知组件进行重绘
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>
Schéma de l'effet d'implémentation :
Touchez avec votre doigt pour déplacer~
3. Multi-touch
Le principe derrière cela :
Le soi-disant multi-touch consiste à manipuler l'écran avec plusieurs doigts. L'utilisation la plus courante est probablement la fonction de zoom avant/arrière. Par exemple, de nombreuses visionneuses d'images prennent en charge le zoom ! En théorie, le système Android lui-même peut gérer le toucher jusqu'à 256 doigts, bien sûr cela dépend du support matériel du téléphone ; cependant, les téléphones qui prennent en charge le multi-touch prennent généralement en charge 2 à 4 points, bien que certains en prennent en charge davantage ! Nous avons remarqué que les deux points précédents utilisaient MotionEvent. MotionEvent représente un événement tactile ; nous pouvons utiliserevent.getAction() & MotionEvent.ACTION_MASKpour déterminer de quelle opération il s'agit. En plus des trois opérations monopoint mentionnées ci-dessus, il existe deux opérations spécifiques multipoint :
- MotionEvent.ACTION_POINTER_DOWN: Déclenché lorsqu'un point est déjà enfoncé sur l'écran et qu'un autre point est enfoncé à ce moment-là. (ACTION_POINTER_DOWN)
- MotionEvent.ACTION_POINTER_UP: Déclenché lorsque plusieurs points sont enfoncés sur l'écran et que l'un d'eux est relâché (c'est-à-dire lorsqu'un point autre que le dernier est relâché). (ACTION_POINTER_UP)
Le déroulement simple est à peu près le suivant :
- Lorsqu'un doigt touche l'écran ——> déclenche l'événement ACTION_DOWN
- Puis un autre doigt touche aussi l'écran ——> déclenche l'événement ACTION_POINTER_DOWN. Si d'autres doigts touchent, cela continue à se déclencher
- Un doigt quitte l'écran ——> déclenche l'événement ACTION_POINTER_UP. Si d'autres doigts continuent à quitter, cela se déclenche à nouveau
- Lorsque le dernier doigt quitte l'écran ——> déclenche l'événement ACTION_UP
- De plus, pendant tout le processus, l'événement ACTION_MOVE sera déclenché en continu
Nous pouvons utiliser event.getX(int) ou event.getY(int) pour obtenir les positions des différents points tactiles : Par exemple, event.getX(0) obtient la coordonnée X du premier point tactile, event.getX(1) obtient la coordonnée X du deuxième point tactile, et ainsi de suite... De plus, nous pouvons également appeler les méthodes de l'objet MotionEventgetPointerCount()méthode pour déterminer combien de doigts touchent actuellement~
Exemple de code :
Très bien, écrivons l'exemple le plus courant : faire glisser une image avec un seul doigt, et zoomer une image avec deux doigts :
Schéma de l'effet d'implémentation :
Code d'implémentation :
<?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.html" />
</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;
// 縮放控制
private Matrix matrix = new Matrix();
private Matrix savedMatrix = new Matrix();
// 不同状态的表示:
private static final int NONE = 0;
private static final int DRAG = 1;
private static final int ZOOM = 2;
private int mode = NONE;
// 定义第一个按下的点,两只接触点的重点,以及出事的两指按下的距离:
private PointF startPoint = new PointF();
private PointF midPoint = new PointF();
private float oriDis = 1f;
/*
* (non-Javadoc)
*
* @see android.app.Activity#onCreate(android.os.Bundle)
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
img_test = (ImageView) this.findViewById(R.id.img_test);
img_test.setOnTouchListener(this);
}
@Override
public boolean onTouch(View v, MotionEvent event) {
ImageView view = (ImageView) v;
switch (event.getAction() & MotionEvent.ACTION_MASK) {
// 单指
case MotionEvent.ACTION_DOWN:
matrix.set(view.getImageMatrix());
savedMatrix.set(matrix);
startPoint.set(event.getX(), event.getY());
mode = DRAG;
break;
// 双指
case MotionEvent.ACTION_POINTER_DOWN:
oriDis = distance(event);
if (oriDis > 10f) {
savedMatrix.set(matrix);
midPoint = middle(event);
mode = ZOOM;
}
break;
// 手指放开
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
break;
// 单指滑动事件
case MotionEvent.ACTION_MOVE:
if (mode == DRAG) {
// 是一个手指拖动
matrix.set(savedMatrix);
matrix.postTranslate(event.getX() - startPoint.x, event.getY() - startPoint.y);
} else if (mode == ZOOM) {
// 两个手指滑动
float newDist = distance(event);
if (newDist > 10f) {
matrix.set(savedMatrix);
float scale = newDist / oriDis;
matrix.postScale(scale, scale, midPoint.x, midPoint.y);
}
}
break;
}
// 设置ImageView的Matrix
view.setImageMatrix(matrix);
return true;
}
// 计算两个触摸点之间的距离
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);
}
// 计算两个触摸点的中点
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);
}
}
Résumé de cette section :
Très bien,En ce qui concerne TouchListeneret OnTouchEventainsi que le multi-touch, c'est tout pour le moment~