问题描述
给定:视图 A,包含视图 B。
动作:我用手指 1 触摸并按住视图 A,然后用手指 2 触摸视图 B。然后释放并执行相同的操作,但首先视图 B,然后视图 A。我希望在这两种情况下,视图都会收到类似的事件。
发生了什么:当我用手指 1 触摸并按住 A,然后用手指 2 触摸并按住 B 时,A 和 B 正在接收两个单独的 MotionEvents,它们每个都持有一个指针的 ACTION_MOVE 坐标:
Logcat:
-----first finger down on view A-------
ACTION_DOWN[#0 (pid 0)=897,392]
----action move for first finger----
ACTION_MOVE[#0 (pid 0)=897,392]
ACTION_MOVE[#0 (pid 0)=897,392]
ACTION_MOVE[#0 (pid 0)=895,392]
ACTION_MOVE[#0 (pid 0)=896,393]
ACTION_MOVE[#0 (pid 0)=896,394]
ACTION_MOVE[#0 (pid 0)=896,395]
ACTION_MOVE[#0 (pid 0)=896,396]
ACTION_MOVE[#0 (pid 0)=895,396]
---second finger down on view B-------
ACTION_DOWN[#0 (pid 1)=224,87]
---action move for 1st finger----
ACTION_MOVE[#0 (pid 0)=895,396]
---action move for 2nd finger----
ACTION_MOVE[#0 (pid 1)=224,87]
--first--
ACTION_MOVE[#0 (pid 0)=895,396]
--second--
ACTION_MOVE[#0 (pid 1)=224,87]
etc . . .
ACTION_MOVE[#0 (pid 0)=895,397]
ACTION_MOVE[#0 (pid 1)=224,87]
ACTION_MOVE[#0 (pid 0)=895,397]
ACTION_MOVE[#0 (pid 1)=223,397]
...
但是,当我首先触摸 B,然后是 A - Android 认为这是一个 多点触摸 事件并开始发送 MotionEvent 对象,该对象包含 2 个 ACTION_MOVE 坐标仅指向视图 B。
Logcat:
----------holding finger at view B------------------
event ACTION_MOVE[#0 (pid 0)=65,33]
event ACTION_MOVE[#0 (pid 0)=62,33]
event ACTION_MOVE[#0 (pid 0)=60,33]
event ACTION_MOVE[#0 (pid 0)=58,33]
event ACTION_MOVE[#0 (pid 0)=56,32]
event ACTION_MOVE[#0 (pid 0)=55,32]
event ACTION_MOVE[#0 (pid 0)=54,32]
event ACTION_MOVE[#0 (pid 0)=53,32]
event ACTION_MOVE[#0 (pid 0)=52,32]
event ACTION_MOVE[#0 (pid 0)=51,33]
----------press on view A with 2nd finger,while holding B with first finger-------------
event ACTION_POINTER_DOWN(pid 1); [#0 (pid 0)=51,33; #1 (pid 1)=1050,-226]
---------action move obj that holds coords for 2 pointers...---------
event ACTION_MOVE[#0 (pid 0)=50,33;#1 (pid 1)=1055,-225]
event ACTION_MOVE[#0 (pid 0)=48,34;#1 (pid 1)=1068,-223]
event ACTION_MOVE[#0 (pid 0)=47,34;#1 (pid 1)=1082,-224]
event ACTION_MOVE[#0 (pid 0)=45,35;#1 (pid 1)=1106,-221]
event ACTION_MOVE[#0 (pid 0)=42,35;#1 (pid 1)=1131,-219]
event ACTION_MOVE[#0 (pid 0)=38,35;#1 (pid 1)=1157,-217]
event ACTION_MOVE[#0 (pid 0)=34,35;#1 (pid 1)=1178,-215]
event ACTION_MOVE[#0 (pid 0)=27,36;#1 (pid 1)=1195,-213]
event ACTION_MOVE[#0 (pid 0)=20,37;#1 (pid 1)=1211,-213]
event ACTION_MOVE[#0 (pid 0)=11,39;#1 (pid 1)=1228,-212]
我想要的是:我想要在两种情况下(先是 A,然后是 B;先是 B,然后是 A)中的单独 MotionEvents(第一种情况)
我是如何解决这个问题的:
-
我尝试在视图 B 的
onTouch()
处仅处理 1 组坐标,然后返回 false,然后在视图 A 处消费事件,但在这种情况下,我在视图处除了 ACTION_DOWN 之外什么都没有收到B. -
我尝试在
dispatchTouchEvent()
方法中分派活动中的事件,然后手动调用视图 A 和视图 BdispatchTouchEvent()
方法,但没有成功。我试图传递给 ViewGroup(父布局)但它也没有成功 =( onTouch 没有被调用。
但是我认为这 2 次尝试是 HACK,我想让操作系统从多点触控切换回单独的触控事件。你知道怎么做吗?
解决方法
我刚刚创建了一个新项目,将布局设置为您的布局,然后为两个视图设置不同的“onTouch()”事件。我无法重现你的情况。如果两个“onTouch()”事件都返回 TRUE,则结果如下:
//DOWN for A
onTouchA(MotionEvent { action=ACTION_DOWN,actionButton=0,id[0]=0,x[0]=382.0,y[0]=175.0,toolType[0]=TOOL_TYPE_FINGER,buttonState=0,metaState=0,flags=0x0,edgeFlags=0x0,pointerCount=1,historySize=0,eventTime=10987450,downTime=10987450,deviceId=5,source=0x1002 })
onTouchA(MotionEvent { action=ACTION_MOVE,x[0]=365.0,y[0]=186.0,eventTime=10993036,source=0x1002 })
//DOWN for B
onTouchB(MotionEvent { action=ACTION_DOWN,id[0]=1,x[0]=409.0,y[0]=260.0,eventTime=10995795,x[0]=363.0,y[0]=184.0,source=0x1002 })
onTouchB(MotionEvent { action=ACTION_MOVE,y[0]=256.0,eventTime=10995888,x[0]=409.8291,y[0]=254.1709,historySize=1,eventTime=10995909,source=0x1002 })
//UP for A
onTouchA(MotionEvent { action=ACTION_UP,x[0]=361.0,y[0]=191.0,eventTime=10998121,x[0]=410.0,y[0]=234.0,eventTime=10998156,y[0]=235.0,eventTime=10998285,eventTime=10998460,x[0]=408.0,eventTime=10998530,source=0x1002 })
//UP for B
onTouchB(MotionEvent { action=ACTION_UP,x[0]=405.0,eventTime=10998846,source=0x1002 })
=================================
//DOWN for B
onTouchB(MotionEvent { action=ACTION_DOWN,x[0]=241.0,y[0]=195.0,eventTime=11125227,downTime=11125227,x[0]=221.0,y[0]=196.0,eventTime=11126010,x[0]=220.0,eventTime=11126044,source=0x1002 })
//DOWN for A
onTouchA(MotionEvent { action=ACTION_DOWN,x[0]=347.0,y[0]=156.0,eventTime=11128089,x[0]=216.0,eventTime=11129071,x[0]=343.0,eventTime=11130531,x[0]=219.91565,y[0]=194.0,eventTime=11132305,x[0]=337.0,eventTime=11133099,y[0]=157.0,eventTime=11133228,eventTime=11133240,source=0x1002 })
XML:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="300dp"
android:layout_height="400dp"
android:background="@color/teal_200"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.495"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.498" />
<TextView
android:id="@+id/textView2"
android:layout_width="200dp"
android:layout_height="200dp"
android:text="Hello World!"
android:background="@color/teal_700"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
主活动代码:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView cTextView = findViewById(R.id.textView);
cTextView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v,MotionEvent event) {
Log.e(TAG,"onTouchA("+event.toString()+")");
return true;
}
});
TextView cTextView2 = findViewById(R.id.textView2);
cTextView2.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v,"onTouchB("+event.toString()+")");
return false;
}
});
}
,
为了防止多点触控问题,您可以简单地关闭 ViewGroup 中的 splitMotionEvents 或 windowEnableSplitTouch 属性