![](/img/trans.png)
[英]How to prevent a custom view passing touch events to parent viewpager
[英]Passing touch events to the parent view
我有一個自定義ViewSwitcher
,我在其中實現了觸摸事件,因此我可以使用觸摸屏滾動屏幕。
我的布局層次結構如下所示:
<ViewSwitcher>
<LinearLayout>
<ListView />
</LinearLayout>
<LinearLayout>
<ListView />
</LinearLayout>
</ViewSwitcher>
現在,問題是ListViews
正在使用觸摸事件,我無法切換視圖。 當我沒有ListViews
時,它工作正常。 我需要能夠滾動視圖並滾動ListView
。
我該如何解決這個問題?
編輯 :我還需要ListView
項目可點擊。
提前致謝!
謝謝大家回答這個問題。 但我能夠以更簡單的方式解決這個問題。 由於我的ViewSwitcher
沒有檢測到觸摸事件,我攔截了觸摸事件,稱為onTouchEvent()
並返回false
。 這里:
@Override
public boolean onInterceptTouchEvent(MotionEvent ev)
{
onTouchEvent(ev);
return false;
}
通過重寫onInterceptTouchEvent()
,我能夠攔截活動中的觸摸事件。 然后我稱為onTouchEvent()
在ViewSwitcher
它處理的切換ListViews
。 最后返回false
,確保ViewGroup
不消耗該事件。
將子視圖的TouchEvent傳遞給父視圖的最簡單方法是將其添加到子視圖:
@Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
return false;
}
在我的父布局中,我發現阻止子進程捕獲觸摸事件的唯一方法是重寫onInterceptTouchEvent以返回true。
@Override
public boolean onInterceptTouchEvent(MotionEvent ev)
{
return true;
}
我認為沒有一種簡單的方法可以做到這一點。
它並不復雜,但您需要創建自己的視圖來擴展ListView。 然后,您可以覆蓋onTouch
處理程序並決定(取決於觸摸事件)是否要處理它(並返回true)或將其傳遞給父視圖。
問題還在於,一旦View處理觸摸事件,它就會獲得所有剩余的事件......
從Android文檔 :
onTouch() - 返回一個布爾值,指示您的偵聽器是否使用此事件。 重要的是這個事件可以有多個相互跟隨的動作。 因此,如果在收到向下操作事件時返回false,則表示您尚未使用該事件,並且對此事件的后續操作也不感興趣。 因此,您不會在事件中調用任何其他操作,例如手指手勢或最終的上行動作事件
因此,例如,如果您希望垂直移動以滾動列表並在同一觸摸事件期間(不抬起手指),您希望水平移動切換視圖,這將是非常具有挑戰性的。
但是,如果您可以使用手勢或處理自定義視圖中的所有內容,並根據MotionEvent的內容,將命令發送到ViewSwitcher。
我所做的是在viewswitcher的listview上設置toucheventlistener,處理事件,檢測fling動作並調用viewswitcher的metchod。 有用。
你也可以插入一個呼叫處理touchevent
在dispatchTouchEvent
,但在這種情況下,你必須也覆蓋onTouchEvent
返回true,否則只有第一個MotionEvent
手勢的DOWN將被傳遞。
這是可觸摸的包裝容器:
<?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
}
};
使用Ant來加載可觸摸的容器片段和包含的片段:
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;
}
有必要在父視圖中使用autoLink =“三”來處理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;
}
};
您是否嘗試將ListView項設置為不可單擊,如下所示:listView.setClickable(false); 這應該向上傳播click事件。
如果您的視圖想要傳遞事件,請確保在onTouchEvent中返回false。 否則,平台認為您使用了該事件,無需進一步處理。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.