将Android NestedScrollView的水平滑动传递给父视图

9

我正试图制作一个左右滑动的卡片系统(类似于Tinder),其中卡片上有一个嵌套的ScrollView。目标是如果用户只向上或向下滑动,NestedScrollView会滚动,但如果用户向左或向右滑动,卡片将使用该滑动。

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="4dp"
    card_view:cardUseCompatPadding="true">

    <android.support.v4.widget.NestedScrollView
        android:id="@+id/nested_scroll_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:padding="4dp">

            <TextView
                android:id="@+id/text_view"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />

            <android.support.v7.widget.RecyclerView
                android:id="@+id/recycler"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />

        </LinearLayout>

    </android.support.v4.widget.NestedScrollView>

</android.support.v7.widget.CardView>

我正在使用的卡片库是 https://github.com/wenchaojiang/AndroidSwipeableCardStack
compile 'com.github.wenchaojiang:AndroidSwipeableCardStack:0.1.5'

当我在NestedScrollView上放置margin_top并在该margin内触摸时,CardStack正确地获取我的输入并使卡片向左或向右移动,但是如果我在其他任何地方触摸和拖动,NestedScrollView无论方向都会获取我的输入。
我应该扩展/覆盖哪个类/onTouchEvent来实现这种效果,或者可能有更简单的方法吗?
谢谢!

我也在尝试弄清楚这个问题,考虑并尝试以下几点:1)在父类中使用onInterceptTouch(可能记录步骤并分派?)2)修改库以实现NestedChildHelper 3)使用ItemTouchHelper的Recyclerview... 目前为止还是相当困难的。不确定是否有影响,但目前我正在尝试的库是Meetic Shuffle和Swipestack。https://github.com/Meetic/Shuffle和https://github.com/flschweiger/SwipeStack - nAndroid
使用这些库之一比使用RecyclerView更好,因为它们可以做很多事情。 - nAndroid
我相信你要找的方法是 onInterceptTouchEvent()。请参见 https://developer.android.com/reference/android/view/ViewGroup.html#onInterceptTouchEvent(android.view.MotionEvent)。 - varsha-venkatesh
@varsha-venkatesh 哎呀,我刚意识到这个问题是反过来的;我的一些滑动堆栈中的上下滚动条在外面。 - nAndroid
请参考此链接。如果有用,请点赞。点击此链接,添加手势监听功能。 - Ronak Gadhia
2个回答

0

是的,您应该通过在Java代码中实现CardStack.CardEventListener并将其设置为监听器mCardStack.setListener(yourListener)来完成此操作。它在项目的自述文件中有说明。请尝试以下操作:

Class YourListener extends CardStack.CardEventListener{
    //implement card event interface
    @Override
    public boolean swipeEnd(int direction, float distance) {
        //if "return true" the dismiss animation will be triggered 
        //if false, the card will move back to stack
        //distance is finger swipe distance in dp


        return (distance>300)? true : false;
    }

    @Override
    public boolean swipeStart(int direction, float distance) {

        return true;
    }

    @Override
    public boolean swipeContinue(int direction, float distanceX, float distanceY) {

        return true;
    }

    @Override
    public void discarded(int id, int direction) {
       //this callback invoked when dismiss animation is finished. 
    }

    @Override
    public void topCardTapped() {
         //this callback invoked when a top card is tapped by user. 
    }
}

mmeloti - 这个没有起作用是因为 swipestack 没有与这个库正常工作。 - nAndroid
问题出在 swipestack 上吗?我不知道,看起来像是你的 xml 中出现了问题,但没有 Java 代码,无法追踪问题... - mmelotti
mmeloti - 任何情况下,您都可以在滚动视图中使用swipestack,两者都可以正常工作。请参见https://github.com/neiljaywarner/TestSwipeStack - nAndroid

0

我为我的应用程序做了2个接口。使用GestureDetector并在onFling(MotionEvent event1, MotionEvent event2, float velocityX, float velocityY)中检查水平速度。超过一定阈值后,传递或拦截触摸事件以供视图使用。您可以从Touch API中检查如何拦截或传递事件。

这是一个通用解决方案,与您使用的ViewGroups或Views无关,它有效。您可以在布局或自定义视图之前消耗事件。

触摸事件会传播

  1. Activity.dispatchTouchEvent()
  2. ViewGroup.dispatchTouchEvent()
  3. View.dispatchTouchEvent()
  4. View.onTouchEvent()
  5. ViewGroup.onTouchEvent()
  6. Activity.onTouchEvent()

如果你在Activity的dispatchTouchEvent()方法中使用GestureDetector,你将能够正确地消耗或传播事件到ViewGroups或Views。

@Override
public boolean dispatchTouchEvent(MotionEvent event) {
    gestureDetector.onTouchEvent(event);
    // Be sure to call the superclass implementation
    return super.dispatchTouchEvent(event);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接