Android - 向其他视图发送触摸事件

Android - Send touch event to other views

我正在尝试实现滚动效果,我认为可以实现,因为我看到一些应用程序实现了这一点。

我有一个 FrameLayout,在这个布局中我有: - 回收者观点 - 浮动视图

<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.RecyclerView
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <LinearLayout // float layout here
        android:layout_width="match_parent"
        android:layout_height="100dp">
    </LinearLayout>
</FrameLayout>

当我滚动回收站视图时,我也可以看到浮动视图滚动,但是当它到达屏幕顶部时,我希望它停在那里。我已经成功实施了这一点,但之后我面临一个新问题。因为浮动视图在回收器视图上方,所以触摸和滚动浮动视图时我无法滚动。在这种情况下,浮动视图似乎消耗了触摸事件,因此回收器什么都不做。

我想要实现的是当用户想要滚动回收视图时应该使用它。 我正在考虑将浮动视图的触摸事件发送到回收器视图。

谢谢。

我前段时间发现了同样的问题。这是我的解决方案(有点老套,但没有找到更好的解决方案)。放入您的自定义 FrameLayout class:

public class CustomFrameLayout extends FrameLayout {

    ... 

    @InjectView(R.id.rv_details)
    RecyclerView recyclerView;

    @InjectView(R.id.ll_details_action_bar_wrapper)
    ViewGroup actionBarWrapperViewGroup;

    private List<MotionEvent> cachedEventList = new ArrayList<>();

    private boolean touchIsFromActionBar;

    private boolean yTranslationThresholdPassed;

    // Pawel Janeczek
    // Those two overrides is for forwarding touch events, that started on action bar, to recyclerview.
    // But you may ask, why there are so many lines? it should by only recyclerView.dispatchTouchEvent(ev) and it should be fine
    // It is because RecyclerView when it is starting scrolling it sends parent.requestDisallowInterceptTouchEvent which disables sending onInterceptTouchEvent to parent
    // In such case we must set a flag touchIsFromActionBar when motion event starts and is in action bar, and then when this flag is set we remove calling super on requestDisallowInterceptTouchEvent
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        int action = ev.getAction();
        if (action == MotionEvent.ACTION_DOWN && viewUtils.isWithinViewBounds(actionBarWrapperViewGroup, ev.getRawX(), ev.getRawY())) {
            touchIsFromActionBar = true;
        }
        if (touchIsFromActionBar && shouldDispatchEventToRecyclerView(ev)) {
            if (!listUtils.isEmpty(cachedEventList)) {
                for (MotionEvent motionEvent : cachedEventList) {
                    recyclerView.dispatchTouchEvent(motionEvent);
                }
                cachedEventList.clear();
            }
            recyclerView.dispatchTouchEvent(ev);
        }
        if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {
            cachedEventList.clear();
            yTranslationThresholdPassed = false;
            touchIsFromActionBar = false;
        }
        return false;
    }

    private boolean shouldDispatchEventToRecyclerView(MotionEvent event) {
        if (yTranslationThresholdPassed) {
            return true;
        } else if (listUtils.isEmpty(cachedEventList)) {
            cachedEventList.add(MotionEvent.obtain(event));
            return false;
        }

        int yTranslationThreshold = 2;

        MotionEvent lastEvent = listUtils.getLast(cachedEventList);
        if (Math.abs(lastEvent.getY() - event.getY()) > yTranslationThreshold) {
            yTranslationThresholdPassed = true;
            return true;
        } else {
            cachedEventList.add(MotionEvent.obtain(event));
            return false;
        }
    }

    @Override
    public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
        if (!touchIsFromActionBar) {
            super.requestDisallowInterceptTouchEvent(disallowIntercept);
        }
    }
    ...
}

名为 actionBarWrapperViewGroup 的 ViewGroup 是您示例中的流式布局。

对于 CustomFrameLayout xml:

<merge xmlns:android="http://schemas.android.com/apk/res/android">
    <RecyclerView
            android:id="@+id/rv_details"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            />

    <LinearLayout
            android:id="@+id/ll_details_action_bar_wrapper"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

        ...

        <FrameLayout
            android:id="@+id/ll_details_action_bar_container"
            android:orientation="horizontal"
            android:layout_width="match_parent"
            android:layout_height="@dimen/default_bar_height"
            android:background="?colorPrimary"/>

        ...
    </LinearLayout>
</merge>

它是从我的项目中实时复制的,因此名称可能会产生误导,但我认为这是可以理解的。如果您有任何问题,请继续。