3

我在父佈局上設置了View.OnTouchListener,但它看起來不起作用。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; 
     } 
    }); 

雖然這也不能工作。

爲什麼父級佈局沒有獲得觸摸事件?我怎樣才能使它工作?

+0

是否存在LinearLayout的任何部分?如果一個ListView在它上面,並且處理的點擊,你的LinearLayout將不會得到它。 – MikeHelland

+0

從您的代碼中,我發現佈局中填充了2個灰度,然後是所有列表視圖,這意味着沒有可實際觸及的父佈局空間。你可能想要添加填充到你的父母,以便你可以捕捉觸摸事件 –

+0

@MazeHatter我知道,是的,listview是在整個佈局的頂部。只是想知道是否有這樣的設計,以便LinearLayout即使在它下面也能捕獲觸摸事件。 –

回答

1

通過在onTouch()中返回true,您將消耗觸摸事件;父視圖的OnTouchListener將不會被調用。 The documentation states

公共抽象布爾onTouch(視圖V,MotionEvent事件)

[...]

返回
真要是聽衆已經消耗的情況下,否則爲false。

您可以改爲興趣在其子女的父或母的ViewGroup攔截觸摸事件通過onInterceptTouchEvent()as detailed in this guide

+0

我有同樣的問題。我有一個容器和一個覆蓋所有容器的EditText。我擴展了EditText並覆蓋了onTouchEvent,我調用了父類,但總是返回false。所以我讓正常的EditText事件像往常一樣工作。 (如向上和向下滾動)以及容器中的自定義手勢檢測器添加到它。 (在我的例子中左右滑動)只有一個問題,那真是糟糕的表現!當我這樣做時,上下滾動很慢,但是滑動(爲我的容器定義)效果很好。任何想法爲什麼這樣做? – Reza

+0

我通過將容器eventListener的滑動檢測邏輯移動到我的自定義EditText來解決性能問題。所以在onTouchEvent方法中,我將一個事件副本發送給我的手勢檢測器,並將另一個副本發送給supper方法。然後,我使用界面進行EditText和活動之間的通信,因此當向左或向右滑動時,編輯文本會告訴活動。即使我的解決方案工作得很好,我仍然更喜歡你提到的第一種方法。順便說一句,謝謝你的回答!我被放養了幾個小時!它幫助了很多。 – Reza

0

剛纔我遇到了同樣的問題。 我認爲這是因爲touch事件永遠不會到達LinearLayout。 我做了什麼來解決這個問題是攔截觸摸事件的對自定義視圖

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"。這可能會影響到孩子的意見咔嗒雖然(我用它在某些情況下,但不知道它適用於所有)

+0

這是否工作?我甚至無法在我的活動中添加此覆蓋功能。 –

+0

@RethinavelPillai你應該有這個視圖。在我的情況下,這是一個ViewPager – xialin

+0

請你分享一些代碼。這將是非常有幫助的。 –

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. 最後檢查手勢是否發生,對我來說它工作完美。