在Android中同时处理多个视图的触摸事件

考虑下图中的例子,

在这里输入图像说明

我正在寻找一个解决scheme,将触摸事件从canvas视图传递给Viewpager 。 这对于在两个视图中同时应用相同数量的缩放都是必需的。

这是关于正在发生的事情的技术说明,

(让我们把视图看作是ABC

A.父视图

B.查看

C.查看传呼机

在孩子( BC )上调用dispatchTouchEvent()之前, A.dispatchTouchEvent()将首先调用A.onInterceptTouchEvent()来查看视图组是否有兴趣截获事件。

所以如果A.onTouchEvent()返回false ,那么它回到B.onTouchEvent() 。 如果返回false ,则返回到C.onTouchEvent() ,调度继续。

一旦回来,

  1. ACTION_CANCEL将被分派给所有的孩子。

  2. 如果定义了事件监听器( OnTouchListener.onTouch() ),则所有后续的手势事件(直到ACTION_UP / ACTION_CANCEL )都将被使用,否则将在A的级别使用事件处理程序A.onTouchEvent()

在这一点上,我可以将事件从父项传递给子视图,但不能让2子视图B。C一起处理事件(在两个视图上应用相同的缩放量)。

有没有办法将触摸事件从父视图传递给子视图,以便他们可以同时处理事件?

这是我的布局设置,

<RelativeLayout android:id="@+id/layoutParent" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#FFFFFFFF"> <com.androidapp.NonSwipeableViewPager android:id="@+id/pager" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center" android:background="@color/transparent" /> <com.androidapp.DrawingView android:id="@+id/drawing" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/transparent" /> </RelativeLayout> 

Related of "在Android中同时处理多个视图的触摸事件"

如果我没有错,你想在顶部和底部视图上处理相同的触摸事件。 根据Android触摸架构,您无法同时处理来自多个视图的触摸事件。 要么你必须在onTouchEvent()方法内处理它,或者传递到下一个视图。 您还需要等待顶视图完成处理MotionEvent( )并让子视图处理。

这是一个使用RxAndroid方法的可能解决scheme,

在您的canvas视图的MotionEvent()

 @Override public boolean onTouchEvent(MotionEvent event) { // process all touch events (UP/DOWN/MOVE) //send events as observable RxBus.getInstance().sendMotionEvent(event); return true; } 

这将观察动作事件并通知所有观察者。

现在,在你的viewpager的onResume()订阅动作事件,以便每当从canvas上进行改变时,它立即传递事件。

 Subscription RxBus _rxBus = RxBus.getInstance(); subscription = _rxBus.getMotionEvent() .subscribe(new Action1<MotionEvent>() { @Override public void call(MotionEvent event) { // call the onTouchEvent of your widget eg ImageView and pass the received event // this will apply the same touch event that was applied in the canvas // .onTouchEvent(event) is important to override the onTouchEvent() of your widget that will use the touch event imageView.onTouchEvent(event); } }); 

RxBus类在下面给出,

 public class RxBus { private static RxBus instance; private final PublishSubject<MotionEvent> motion_event = PublishSubject.create(); public static RxBus getInstance() { if (instance == null) { instance = new RxBus(); } return instance; } public void sendMotionEvent(MotionEvent motionEvent) { motion_event.onNext(motion_event); } public Observable<MotionEvent> getMotionEvent() { return motion_event; } } 

通过使用callback实现起来相当容易。 只需用任何方法创build一个接口,然后在Viewpager中实现。 调用将根据您的触摸事件在您的View类中调用,响应将返回到Viewpager。 我在MainActivity中创build了一个ImageView的示例,并调用其大小从一个不同的片段改变,它的工作原理。 这里是我的代码如下:

 public interface ICallBackForResize { void resizeme(); void actionUp(); void actionDown(); } 

主要活动:

 public class MainActivity extends AppCompatActivity implements ICallBackForResize { ImageView img; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); img= (ImageView) findViewById(R.id.image); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } @Override public void resizeme() { Toast.makeText(MainActivity.this,"called",Toast.LENGTH_LONG).show(); img.getLayoutParams().height += 20; img.getLayoutParams().width += 20; img.requestLayout(); } @Override public void actionUp() { //do whatever } @Override public void actionDown() { //do whatever } } 

我的片段类有一个简单的button:

 public class MyFragmentButton extends Fragment { View view; ICallBackForResize callBackForResize; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); callBackForResize= (ICallBackForResize) getActivity(); } @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { view=inflater.inflate(R.layout.mybutton,container,false); Button btn= (Button) view.findViewById(R.id.button); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { callBackForResize.resizeme(); } }); return view; } } 

我相信你不需要XML文件。 我只是分享,如果有人需要:

activity_main:

 <?xml version="1.0" encoding="utf-8"?> 

 <android.support.design.widget.AppBarLayout android:layout_height="wrap_content" android:layout_width="match_parent" android:theme="@style/AppTheme.AppBarOverlay"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:popupTheme="@style/AppTheme.PopupOverlay" /> </android.support.design.widget.AppBarLayout> <include layout="@layout/content_main"/> </android.support.design.widget.CoordinatorLayout> 

content_main:

 <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" 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" app:layout_behavior="@string/appbar_scrolling_view_behavior" tools:showIn="@layout/activity_main" tools:context="nanofaroque.com.addlistener.MainActivity"> <ImageView android:id="@+id/image" android:text="Hello World!" android:layout_width="100dp" android:layout_gravity="center" android:src="@mipmap/ic_launcher" android:layout_height="100dp" /> <fragment android:name="nanofaroque.com.addlistener.MyFragmentButton" android:id="@+id/headlines_fragment" android:layout_width="100dp" android:layout_height="100dp" /> </FrameLayout> 

myButton的:

  <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:id="@+id/button" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>