ToB企服应用市场:ToB评测及商务社交产业平台

标题: 安卓多点触控 [打印本页]

作者: 愛在花開的季節    时间: 2024-10-31 22:27
标题: 安卓多点触控
对于普通的点击变乱,调用View对象的setOnClickListener()方法注册点击变乱的监听即可,但是如果要处理更加复杂的触控变乱时,这种方式就无法满足我们的要求了,此时我们就可以监听所有触摸变乱,自行处理触摸变乱。
1. 注册触摸变乱监听

调用View对象的setOnTouchListener()方法注册触控变乱的监听,即可监听触控变乱。然后实现View.OnTouchListener接口,在接口的onTouch()方法中处理触摸变乱。
2. 触摸变乱的种类

重要触摸变乱及触发时间如下(以下时间都在MotionEvent中定义):
变乱类型触发时间ACTION_DOWN屏幕上唯逐一个手指按下时触发ACTION_POINTER_DOWN屏幕上任一非唯一手指按下时触发ACTION_POINTER_UP屏幕上任一非唯一手指抬起时触发ACTION_UP屏幕上最后一个手指抬起时触发ACTION_MOVE任意手指移动时触发 注:ACTION_POINTER_1_UP、ACTION_POINTER_1_DOWN、ACTION_POINTER_2_UP、ACTION_POINTER_2_DOWN、ACTION_POINTER_3_UP、ACTION_POINTER_3_DOWN已经被废弃,不发起使用。
3. MotionEvent相干方法说明

方法说明getAction()返回触摸变乱的种类。不发起使用,发起用getActionMasked()代替getActionMasked()返回触摸变乱的种类getActionIndex()获取当前触摸变乱的索引。对ACTION_MOVE变乱无效,因为ACTION_MOVE变乱的getActionIndex()始终返回0getPointerId(pointerIndex)获取pointerIndex索引对应的pointerIdfindPointerIndex(pointerId)获取pointerId对应的索引pointerIndexgetX(pointerIndex)获取pointerIndex相对于当前view左上角的x坐标getX()等价于getX(0)getY(pointerIndex)获取pointerIndex相对于当前view左上角的y坐标getY()等价于getY(0)getRawX(pointerIndex)获取pointerIndex相对于屏幕左上角的x坐标getRawX()等价于getRawX(0)getRawY(pointerIndex)获取pointerIndex相对于屏幕左上角的y坐标getRawY()等价于getRawY(0) 4. pointerIndex与pointerId

对于一个触摸变乱,我们最关心的是触摸点位置和该触摸点对应的手指,对于ACTION_DOWN、ACTION_POINTER_DOWN、ACTION_POINTER_UP、ACTION_UP,通过getActionIndex()即可获取变乱索引pointerIndex,然后通过getPointerId(pointerIndex)即可获取当前变乱的手指id。但是对于ACTION_MOVE变乱,我们无法通过getActionIndex()获取当前变乱的索引pointerIndex,因为ACTION_MOVE变乱中,getActionIndex()始终返回0。
为了将ACTION_MOVE变乱的触摸点与pointerId关联起来,我们必要保存当前屏幕上所有的pointerId,然后用findPointerIndex(pointerId)获取pointerId对应的pointerIndex,然后使用getX(pointerIndex)、getY(pointerIndex)等方法获取触点位置。
pointerIndex与pointerId天生与变化规则
pointerId
天生规则
手指按下时,从0开始递增寻找,以第一个未被使用的数字作为pointerId。
变化规则
在手指移动过程中不会发生变化,直得手指抬起,回收该pointerId。
pointerIndex
天生规则
初始pointerIndex = pointerId。
变化规则
当有手指抬起时,该手指的pointerIndex后的所有手指的pointerIndex -= 1;当有手指按下时,由于pointerIndex = pointerId,所有pointerIndex >= pointerId的手指的pointerIndex += 1。
总的来说,pointerIndex与pointerId天生与变化规则可以用以下代码来明确:
  1. package com.example.study.controller;
  2. import java.util.ArrayList;
  3. import java.util.Iterator;
  4. import java.util.List;
  5. public class PointerCollection {
  6.     private List<Pointer> pointers;
  7.     public PointerCollection() {
  8.         pointers = new ArrayList<>();
  9.     }
  10.     /**
  11.      * 手指按下时,给当前触控点生成pointerId
  12.      *
  13.      * @return 生成的pointerId
  14.      */
  15.     public int pressDown() {
  16.         int index = 0;
  17.         for (; index < pointers.size(); index++) {
  18.             if (pointers.get(index).pointerId != index) {
  19.                 break;
  20.             }
  21.         }
  22.         pointers.add(index, new Pointer(index));
  23.         return index;
  24.     }
  25.     /**
  26.      * 手指抬起时,回收触控点
  27.      *
  28.      * @param pointerId 触控点Id
  29.      * @return 回收的触控点
  30.      */
  31.     public int pressUp(int pointerId) {
  32.         Iterator<Pointer> iterator = pointers.iterator();
  33.         while (iterator.hasNext()) {
  34.             Pointer pointer = iterator.next();
  35.             if (pointer.pointerId == pointerId) {
  36.                 iterator.remove();
  37.                 break;
  38.             }
  39.         }
  40.         return pointerId;
  41.     }
  42.     /**
  43.      * 获取pointerId对应的索引pointerIndex
  44.      *
  45.      * @param pointerId pointerId
  46.      * @return pointerIndex
  47.      */
  48.     public int findPointerIndex(int pointerId) {
  49.         for (int index = 0; index < pointers.size(); index++) {
  50.             if (pointers.get(index).pointerId == pointerId) {
  51.                 return index;
  52.             }
  53.         }
  54.         return -1;
  55.     }
  56.     class Pointer {
  57.         int pointerId;
  58.         public Pointer(int pointerId) {
  59.             this.pointerId = pointerId;
  60.         }
  61.     }
  62.     public String toString() {
  63.         StringBuilder sb = new StringBuilder();
  64.         for (int pointerIndex = 0; pointerIndex < pointers.size(); pointerIndex++) {
  65.             sb.append("{pointerId: " + pointers.get(pointerIndex).pointerId + ", pointerIndex:" + pointerIndex + "}  ");
  66.         }
  67.         return sb.toString();
  68.     }
  69. }
复制代码
5. 多点触控示例

Listener类
  1. package org.tao.hetools.listeners;
  2. import android.util.Log;
  3. import android.view.MotionEvent;
  4. import android.view.View;
  5. import java.util.HashMap;
  6. import java.util.Locale;
  7. import java.util.Map;
  8. public class MulTouchListener implements View.OnTouchListener {
  9.     private Map<Integer, float[]> pointerMap = new HashMap<>();
  10.     @Override
  11.     public boolean onTouch(View view, MotionEvent event) {
  12.         updatePointer(event);
  13.         return true;
  14.     }
  15.     private void updatePointer(MotionEvent event) {
  16.         int actionMasked = event.getActionMasked();
  17.         int actionIndex = event.getActionIndex();
  18.         int pointerId = event.getPointerId(actionIndex);
  19.         switch (actionMasked) {
  20.             case MotionEvent.ACTION_DOWN:
  21.                 pointerMap.clear();
  22.             case MotionEvent.ACTION_POINTER_DOWN:
  23.                 pointerMap.put(pointerId, new float[]{event.getX(actionIndex), event.getY(actionIndex)});
  24.                 Log.i("记录按压事件", String.format("第%d根手指按下", pointerId));
  25.                 return;
  26.             case MotionEvent.ACTION_POINTER_UP:
  27.                 pointerMap.remove(pointerId);
  28.                 Log.i("记录按压事件", String.format("第%d根手指抬起", pointerId));
  29.                 return;
  30.             case MotionEvent.ACTION_UP:
  31.                 pointerMap.clear();
  32.                 Log.i("记录按压事件", String.format("所有手指抬起", pointerId));
  33.                 return;
  34.             case MotionEvent.ACTION_MOVE:
  35.                 break;
  36.             default:
  37.                 return;
  38.         }
  39.         StringBuilder sb = new StringBuilder("所有手指位置信息如下    ");
  40.         for (Map.Entry<Integer, float[]> entry : pointerMap.entrySet()) {
  41.             int pointerIndex = event.findPointerIndex(entry.getKey());
  42.             float[] currentPointer = {event.getX(pointerIndex), event.getY(pointerIndex)};
  43.             entry.setValue(currentPointer);
  44.             sb.append(String.format(Locale.CHINESE, "%d:(%1.4f, %1.4f)  ", entry.getKey(),
  45.                     event.getX(pointerIndex),
  46.                     event.getY(pointerIndex)));
  47.         }
  48.         Log.i("记录移动事件", sb.toString());
  49.     }
  50. }
复制代码
Activity类
  1. package org.tao.hetools.activities;
  2. import android.os.Bundle;
  3. import android.view.View;
  4. import androidx.activity.ComponentActivity;
  5. import androidx.annotation.Nullable;
  6. import org.tao.hetools.R;
  7. import org.tao.hetools.listeners.MulTouchListener;
  8. public class TouchListenerActivity extends ComponentActivity {
  9.     private View view;
  10.     @Override
  11.     protected void onCreate(@Nullable Bundle savedInstanceState) {
  12.         super.onCreate(savedInstanceState);
  13.         this.setContentView(R.layout.activity_touch_listener);
  14.         view = findViewById(R.id.touch_listener_view);
  15.         view.setOnTouchListener(new MulTouchListener());
  16.     }
  17. }
复制代码
Activity布局
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3.     android:layout_width="match_parent"
  4.     android:layout_height="match_parent">
  5.     <FrameLayout
  6.         android:layout_width="match_parent"
  7.         android:layout_height="match_parent">
  8.         <SurfaceView
  9.             android:id="@+id/touch_listener_view"
  10.             android:layout_width="match_parent"
  11.             android:layout_height="match_parent"
  12.             android:background="@color/white" />
  13.     </FrameLayout>
  14. </RelativeLayout>
复制代码
参考文章


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4