2011-06-16 89 views
32

我有一個自定義ViewSwitcher其中我實現了觸摸事件,因此我可以使用觸摸屏在屏幕上滾動。將觸摸事件傳遞給父視圖

我的佈局,層次結構如下所示:

<ViewSwitcher> 

    <LinearLayout> 
     <ListView /> 
    </LinearLayout> 

    <LinearLayout> 
     <ListView /> 
    </LinearLayout> 

</ViewSwitcher> 

現在的問題是,觸摸事件正在由 ListViews消耗,我不能切換的意見。當我 沒有ListViews時它工作正常。我需要能夠滾動瀏覽 的視圖並滾動ListView

我該如何解決這個問題?

編輯:我還需要ListView項目可點擊。

在此先感謝!

回答

74

謝謝大家回答這個問題。但我能夠以一種更簡單的方式解決問題。由於我的ViewSwitcher未檢測到觸摸事件,因此我截獲了觸摸事件,稱爲onTouchEvent(),並返回false。在這裏:

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

通過重寫onInterceptTouchEvent(),我能夠在活動中攔截觸摸事件。然後我撥打ViewSwitcher中的onTouchEvent()來處理ListViews的切換。最後通過返回false,確保ViewGroup不消耗該事件。

+0

假設我想在gridView的單元格內有一個horizo​​ntalScrollView,那麼如何使用這個解決方案在這種情況下不能很好地工作,並且允許我同時執行水平滾動和單擊/長按GridView的單元格? – 2014-01-18 14:32:54

+1

這幫助我解決了一個ViewPager問題,我認爲我會爲後代拋出這個問題。我在ViewPager內部有必須附加OnClickListener/OnTouchListener的視圖。這些消耗運動事件導致父ViewPager不滾動。通過將這個技巧應用於包含視圖尋呼機的佈局,我可以將所有觸摸事件轉發給尋呼機(滾動器),而不管子是否將該事件用作點擊。 – mszaro 2015-03-13 21:10:52

+5

我不認爲這是在onInterceptTouchEvent()中調用onTouchEvent()的「官方」方式,除非這是指某種破解。因爲如果從onInterceptTouchEvent()返回true,onTouchEvent()將被調用。 – KarolDepka 2016-01-16 20:36:03

0

您是否嘗試將ListView項目設置爲不可點擊的狀態,如下所示:listView.setClickable(false);這應該向上傳播點擊事件。

+0

這因此未修復它。而且我還需要listview的項目是可點擊的。 – 2011-06-16 17:21:58

0

如果您的視圖想要傳遞事件,請確保您在onTouchEvent中返回false。否則,平臺認爲您已使用該事件,無需進一步處理。

1

我不認爲有這樣一個簡單的方法。

這並不複雜,但您需要創建自己的視圖來擴展ListView。然後你可以重寫onTouch處理程序並決定(取決於觸摸事件)是否要處理它(並返回true)或將其傳遞給父視圖。

的問題還在於,一旦視圖處理觸摸事件,它是一個將得到所有剩餘的...

Android documentation

onTouch() - 這返回一個布爾值爲 指示您的聽衆 是否消耗此事件。重要的是 的事情是這個事件可以有 多個行動,其他每個 。因此,如果您在 收到關閉操作事件時返回false,則您的 表示您沒有在該事件的後續操作中使用 事件並且也不感興趣 。 因此,你將不會被要求對事件中的任何 其他操作,如 的手指手勢,或最終 後續行動事件

因此,舉例來說,如果你想擁有垂直移動到在列表中滾動並且在相同的觸摸事件期間(不用擡起手指),您想要水平移動來切換視圖,這將是相當具有挑戰性的。

但是,如果您可以使用手勢作爲示例或處理自定義視圖中的所有內容,並根據MotionEvent的內容將命令發送到ViewSwitcher。

0

我所做的就是在viewwitcher的listview上設置toucheventlistener,處理事件,檢測fling動作並調用viewswitcher的metchod。有用。

4

通過孩子視圖的的TouchEvent到父視圖最簡單的方法是添加這孩子的看法:

@Override 
public boolean onTouchEvent(MotionEvent event) { 
    super.onTouchEvent(event); 
    return false; 
} 
+0

這是我爲RecyclerView工作的唯一解決方案。看起來你必須擴展RecyclerView,覆蓋onTouchEvent,並禁用任何進一步的交互,並繼續事件鏈。 – Georgi 2017-03-30 19:03:30

0

你也可以插入一個呼叫處理toucheventdispatchTouchEvent,但在這種情況下,你必須還覆蓋onTouchEvent返回true,否則只有第一個MotionEvent手勢的向下將被傳遞。

這是可觸摸的包裝容器:

<?xml version="1.0" encoding="utf-8"?> 
<view xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/pager" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    class="com.example.myapp.FragmentContainer$TouchableWrapper" /> 

和類:

public static class TouchableWrapper extends FrameLayout { 
    private GestureDetector gestureDetector; 
    public void setGestureDetector(GestureDetector gestureDetector) { 
     this.gestureDetector = gestureDetector; 
    } 

    // these constructors for the XML inflater 
    public TouchableWrapper(Context context) { 
     super(context); 
    } 
    public TouchableWrapper(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 
    public TouchableWrapper(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
    } 

    @Override 
    public boolean onInterceptTouchEvent(MotionEvent event) { 
     Log.d(TAG, "onInterceptTouchEvent " + event.toString()); 
     return false; // true for intercept, false è default and pass on to children View 
    } 
    @Override 
    public boolean dispatchTouchEvent(MotionEvent event) { 
     Log.d(TAG, "dispatchTouchEvent " + event.toString()); 
     gestureDetector.onTouchEvent(event); 
     return super.dispatchTouchEvent(event); 
    } 
    @Override 
    public boolean onTouchEvent(MotionEvent event) { 
     Log.d(TAG, "onTouchEvent " + event.toString()); 
     return true; //return super.onTouchEvent(event); 
    } 
} 

這是GestureDetector參考:

private GestureDetector gestureDetector; 

此所述GestureListener

private GestureDetector.SimpleOnGestureListener sOGL = new GestureDetector.SimpleOnGestureListener() { 
    private static final int SWIPE_THRESHOLD = 100; 
    private static final int SWIPE_VELOCITY_THRESHOLD = 100; 

    @Override 
    public boolean onDown(MotionEvent e) { 
     return true; 
    } 

    @Override 
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { 
     boolean result = false; 
     try { 
      float diffY = e2.getY() - e1.getY(); 
      float diffX = e2.getX() - e1.getX(); 
      if (Math.abs(diffX) > Math.abs(diffY)) { 
       if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) { 
        if (diffX > 0) { 
         goToRight(); // onSwipeRight(); 
        } else { 
         goToLeft(); // onSwipeLeft(); 
        } 
       } 
       result = true; 
      } else if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) { 
       if (diffY > 0) { 
        // onSwipeBottom(); 
       } else { 
        // onSwipeTop(); 
       } 
      } 
      result = true; 

     } catch (Exception exception) { 
      exception.printStackTrace(); 
     } 
     return result; // return false indicate event not handled 
    } 
}; 

螞蟻這種加載可觸摸容器片段和包含片段:

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
    Log.d(TAG, "onCreateView()"); 
    View view = inflater.inflate(R.layout.fragmentcontainer, container, false); 

    gestureDetector = new GestureDetector(view.getContext(), sOGL); 
    ((FragmentContainer.TouchableWrapper) view).setGestureDetector(gestureDetector); 

    FragmentManager fm = this.getFragmentManager(); 
    FragmentTransaction ft = fm.beginTransaction(); 
    ft.replace(R.id.pager, frag).commit(); 

    return view; 
} 
0

在我父母的佈局,我已經找到了防止兒童捕捉觸摸事件的唯一方法是通過覆蓋onInterceptTouchEvent返回真正。

@Override 
public boolean onInterceptTouchEvent(MotionEvent ev) 
{ 
    return true; 
} 
0

有必要以處理TextView的觸控與自動鏈接=父視圖「三化」 這樣做:

private LinearLayout mParentView; 
private TextView mTextView; 
private View.OnTouchListener mParentListener = new OnTouchListener() { 

    @Override 
    public boolean onTouch(View v, MotionEvent event) { 
     ...... 
     return false; 
    } 
}; 
mParentView.setOnTouchListener(mParentListener); 

mTextView.setOnTouchListener(new View.OnTouchListener() { 
    @Override 
    public boolean onTouch(View v, MotionEvent event) { 
     mParentListener.onTouch(mParentView, event); 
     return false; 
    } 
}; 
相關問題