View.OnTouchListener()不适用于父布局

时间:2014-01-21 01:00:33

标签: android android-layout android-listview android-linearlayout android-gesture

我在父布局上设置了View.OnTouchListener,但它似乎不起作用。

以下是UI的XML:

<LinearLayout 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:baselineAligned="false"
    android:orientation="vertical"
    android:id="@+id/mainActivityLinearLayout"
    android:background="@drawable/listviewborder"
    tools:context=".MainActivity" >

    <View
        android:id="@+id/lineView"
        android:layout_width="match_parent"
        android:layout_height="2dp"
        android:background="@color/gray" />

    <ListView
        android:id="@+id/gameListView"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="2"
        android:dividerHeight="2dp" />

</LinearLayout>

这是在父布局上设置的OnTouchListener:

mainActivityView = this.findViewById(R.id.mainActivityLinearLayout);
mainActivityView.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            System.out.println("Touch test activity");
            return true;
        }
    });

onTouch()永远不会被调用,字符串永远不会打印出来。

不是说我已经为ListView实现了OnItemClick,我只是希望能够检测整个布局上的触摸。

我也试过

gameListView = (ListView) findViewById(R.id.gameListView);
gameListView.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            System.out.println("Touch test list");
            return true;
        }
    });

虽然这也不起作用。

为什么父布局没有触及事件?我怎样才能让它发挥作用?

3 个答案:

答案 0 :(得分:1)

通过在onTouch()中返回true,您将使用触摸事件;不会调用父视图的OnTouchListener。 The documentation states

  

public abstract boolean onTouch(View v,MotionEvent event)

     

[...]

     

<强>返回
  如果侦听器已使用该事件,则为true,否则为false。

您可能感兴趣的是让父ViewGroup通过onInterceptTouchEvent()as detailed in this guide拦截来自其子女的触摸事件。

答案 1 :(得分:1)

  1. 让此类检测手势监听器

       class MyGestureDetector extends SimpleOnGestureListener {
    
        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
                float velocityY) {
            try {
                if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH)
                    return false;
                // right to left swipe
                if (e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE
                        && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
                    Log.d("asdsa", "left");
                    // Toast.makeText(SelectFilterActivity.this, "Left Swipe",
                    // Toast.LENGTH_SHORT).show();
                } else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE
                        && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
                    Log.d("asdsa", "right");
                    Fragment fr = getActivity().getSupportFragmentManager()
                            .findFragmentByTag("list_items");
                    if (fr != null) {
                        Log.d("asdsa", "not null");
                        if (fr.isVisible()) {
                            Log.d("asdsa", "visible");
                            getActivity().getSupportFragmentManager()
                                    .beginTransaction()
                                    .setCustomAnimations(0, R.anim.right_out)
                                    .remove(fr).commit();
                        }
                    }
                    // Toast.makeText(SelectFilterActivity.this, "Right Swipe",
                    // Toast.LENGTH_SHORT).show();
                }
            } catch (Exception e) {
                // nothing
            }
    
            return false;
        }
    
  2. 在活动中声明此变量:

    private static final int SWIPE_MIN_DISTANCE = 120;
    
    private static final int SWIPE_MAX_OFF_PATH = 250;
    private static final int SWIPE_THRESHOLD_VELOCITY = 200;
    private GestureDetector gestureDetector;
    View.OnTouchListener gestureListener;
    
  3. 现在,您在活动onCreate中执行此操作:

    gestureDetector = new GestureDetector(getActivity(), new MyGestureDetector());
    gestureListener = new View.OnTouchListener() {
        public boolean onTouch(View v, MotionEvent event) {
            return gestureDetector.onTouchEvent(event);
        }
    };
    listView.setOnTouchListener(gestureListener);
    
  4. 最后检查手势是否发生,对我而言,它完美无缺。

答案 2 :(得分:0)

我刚刚遇到同样的问题。 我认为这是因为触摸事件永远不会到达LinearLayout。 我为解决这个问题所做的是拦截cutom视图的触摸事件

public class MyPager extends ViewPager {

    public RecentsPager(Context context) {
        super(context);
    }

    public RecentsPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        // Do not allow swiping to switch between child pager pages
        return false;
    }
}

当你想要触摸时,返回true。如果返回false,则触摸事件将传递给子视图。

希望这有助于寻找它的人。

修改 您还可以尝试为父布局添加属性android:clickable="true"。这可能会影响点击子视图(我在某些情况下使用它但不确定它适用于所有人)