如何在父视图的touchlistener中使用子视图的触摸事件?

问题描述:

在我的应用程序中,我想要在我的父视图的onTouchListener中获取所有子视图的触摸事件,但我无法获取。如何在父视图的touchlistener中使用子视图的触摸事件?

实施例:

在我的活动的观点我有有一些按钮和edittexts在它的一点的布局。所以,无论何时我触摸按钮或编辑文本,我都希望在framlayout的onTouchListeners中获得此触摸事件。

这里是我的代码..

活动:

private FrameLayout rootView; 
    @Override 
    public void onCreate(Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     rootView = (FrameLayout) findViewById(R.id.rootview); 
     rootView.setOnTouchListener(new OnTouchListener() 
     { 
      @Override 
      public boolean onTouch(View v, MotionEvent event) 
      { 
       Log.e("Touch Event: ", " X: " + event.getX() + " Y: " + event.getY()); 
       return false; 
      } 
     }); 
     } 

的main.xml:

<?xml version="1.0" encoding="utf-8"?> 
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:padding="10dip" 
    android:id="@+id/rootview"> 

<LinearLayout 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:background="@android:color/white" 
    android:orientation="vertical" 
    android:layout_gravity="center" 
    android:padding="10dip"> 

    <TextView 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:layout_gravity="center" 
        android:padding="4dp" 
        android:text="Login" 
        android:textColor="@android:color/black" 
        android:textSize="16dp" 
        android:textStyle="bold" /> 

       <TextView 
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" 
        android:layout_marginTop="10dp" 
        android:text="Username" 
        android:textColor="@android:color/black" 
        android:textSize="14dp" 
        android:textStyle="bold" /> 

       <EditText 
        android:id="@+id/edttextusername" 
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" 
        android:imeOptions="flagNoExtractUi" 
        android:singleLine="true" /> 

       <TextView 
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" 
        android:layout_marginTop="10dp" 
        android:text="Password" 
        android:textColor="@android:color/black" 
        android:textSize="14dp" 
        android:textStyle="bold" /> 

       <EditText 
        android:id="@+id/edttextpassword" 
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" 
        android:imeOptions="flagNoExtractUi" 
        android:password="true" /> 

       <LinearLayout 
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" 
        android:layout_gravity="center" 
        android:gravity="center" 
        android:orientation="horizontal" 
        android:padding="10dp" > 

        <Button 
         android:id="@+id/btnlogin" 
         android:layout_width="0dip" 
         android:layout_height="40dip" 
         android:layout_marginRight="5dp" 
         android:layout_weight="1" 
         android:enabled="false" 
         android:text="Login" 
         android:padding="5dip" 
         android:textColor="@android:color/black" 
         android:textStyle="bold" 
         /> 

        <Button 
         android:id="@+id/btncall" 
         android:layout_width="0dip" 
         android:layout_height="40dip" 
         android:layout_marginLeft="5dp" 
         android:layout_weight="1" 
         android:padding="5dip" 
         android:text="Cancel" 
         android:textColor="@android:color/black" 
         android:textStyle="bold" /> 
       </LinearLayout> 


</LinearLayout> 

    </FrameLayout> 

问题:所以whenver我触摸按钮或EditText上在我的框架布局的onTouchLi中,我无法获得联系(不叫)。

注意:我不想为所有childView添加单独的onTouchListener。

在此先感谢。

我尝试过类似的设计(在根FrameLayout上只有一个onTouch监听器)并且它工作正常。如果onTouch返回true而不是false,我会得到所有要点。否则,我只是得到第一点。我无法找到这个“返回”问题的原因,因为我预料会出现相反的行为。

但是,根据我的经验,如果您设置任何子视图可点击,那么其父级的onTouch将无法工作。如果你有另一种解决方案,如果你分享,那会很棒。

您可以通过在布局中重写dispatchTouchEvent来实现该目标。

public class MyFrameLayout extends FrameLayout { 
    @Override 
    public boolean dispatchTouchEvent(MotionEvent e) { 
     // do what you need to with the event, and then... 
     return super.dispatchTouchEvent(e); 
    } 
} 

然后使用该布局代替通常的FrameLayout的:

<com.example.android.MyFrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:padding="10dip" 
    android:id="@+id/rootview"> 
    ... 

你也可以跳过超级呼叫完全,如果你需要,以防止孩子的意见接收事件,但我认为这会很少见。如果您需要重新创建一些,但不是所有的默认功能,还有很多改写:

http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.1.1_r1/android/view/ViewGroup.java#ViewGroup.dispatchTouchEvent%28android.view.MotionEvent%29

2个解决方案:

  1. 的ViewGroup中使用onInterceptTouchEvent,如图所示 here

  2. 避免让布局处理触摸事件,并且有一个视图是布局的子视图,它覆盖整个大小以处理触摸事件。

    它不像扩展类一样高效,但它更容易,不需要创建新的文件/类。

    例如:

    触摸事件,只是添加到视图,它会处理它们,而不是任何其他意见。

它可以通过使用“onInterceptTouchEvent”来实现。请尝试此操作,它可能会工作

@Override 
public boolean onInterceptTouchEvent(MotionEvent ev) { 
    onTouchEvent(ev); 
    return false; 
} 
+0

手动调用onTouchEvent方法不是一个好主意... – Crisic 2017-06-07 14:29:44