将触摸事件传递给父视图
我有一个自定义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()
调用了处理ListViews
切换的onTouchEvent()
。 最后,通过返回false
,确保ViewGroup
不会消耗事件。
将子视图的TouchEvent传递给父视图最简单的方法是将其添加到子视图中:
@Override public boolean onTouchEvent(MotionEvent event) { super.onTouchEvent(event); return false; }
我不认为有这样一个简单的方法。
这并不复杂,但是您需要创build自己的视图来扩展ListView。 然后,您可以重写onTouch
处理程序并决定(取决于触摸事件)是否要处理它(并返回true)或将其传递给父视图。
问题也是,一旦一个视图处理触摸事件,它将得到所有其余的…
从Android文档 :
onTouch() – 这将返回一个布尔值来指示您的侦听器是否使用此事件。 重要的是,这个事件可以有多个相互关联的动作。 因此,如果您在收到向下操作事件时返回false,则表明您没有使用该事件,并且对此事件的后续操作也不感兴趣。 因此,你不会被要求在事件中的任何其他行动,如手指手势,或最终的行动事件
因此,例如,如果您想要垂直移动以滚动列表,并且在同一个触摸事件(无需抬起手指)的情况下,您需要横向移动来切换视图,这将是相当具有挑战性的。
但是,如果您可以使用手势或处理自定义视图中的所有内容,并根据MotionEvent的内容,将命令发送到ViewSwitcher。
你尝试设置ListView项目是不可点击的像这样:listView.setClickable(false); 这应该向上传播点击事件。
如果您的视图想要传递事件,请确保您在onTouchEvent中返回false。 否则,该平台认为你消耗了事件,不需要进一步的处理。
我所做的就是在视图切换器的listview上设置toucheventlistener,处理事件,检测fling动作并调用viewswitcher的metchod。 有用。
您还可以插入一个调用来处理touchevent
中的touchevent
,但是在这种情况下,您也必须重写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" />
和class级:
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; }
在我的父级布局中,我发现阻止孩子捕捉触摸事件的唯一方法是通过重写onInterceptTouchEvent返回true。
@Override public boolean onInterceptTouchEvent(MotionEvent ev) { return true; }
有必要用autoLink =“three”来处理父视图中的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; } };