繁体   English   中英

将触摸事件传递给父视图

[英]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。 有用。

你也可以插入一个呼叫处理toucheventdispatchTouchEvent ,但在这种情况下,你必须也覆盖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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM