折叠工具栏布局无法识别滚动甩动

我创建了一个简单的折叠工具栏布局,它就像一个魅力。我的问题是,如果我尝试在嵌套的滚动视图上使用甩动滚动,它就会在我松开手指时停止。正常滚动的工作方式与预期类似。

我的活动代码未更改 = >自动生成的空活动。(我刚刚在Android工作室中单击了创建新的空活动并编辑了XML)。

我在这里读到,图像视图本身的滚动手势是错误的,但不是滚动本身是错误的:看到这里

我尝试通过Java代码激活“平滑滚动”。似乎如果我滚动得足够远,图像视图不再可见,那么抛掷手势就会被识别出来。

TLDR:为什么只要图像视图可见,甩动手势就不起作用?我的 XML 代码如下所示:

    <android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/profile_app_bar_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        android:fitsSystemWindows="true">

        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/profile_collapsing_toolbar_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_scrollFlags="scroll|exitUntilCollapsed"
            app:contentScrim="?attr/colorPrimary"
            app:expandedTitleMarginStart="48dp"
            app:expandedTitleMarginEnd="64dp"
            android:fitsSystemWindows="true">

            <ImageView
                android:id="@+id/image"
                android:layout_width="match_parent"
                android:layout_height="420dp"
                android:scaleType="centerCrop"
                android:fitsSystemWindows="true"
                android:src="@drawable/headerbg"
                android:maxHeight="192dp"

                app:layout_collapseMode="parallax"/>

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
                app:layout_collapseMode="pin" />

        </android.support.design.widget.CollapsingToolbarLayout>

    </android.support.design.widget.AppBarLayout>

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        app:layout_anchor="@id/profile_app_bar_layout"
        app:layout_anchorGravity="bottom|right|end"
        android:layout_height="@dimen/fab_size_normal"
        android:layout_width="@dimen/fab_size_normal"
        app:elevation="2dp"
        app:pressedTranslationZ="12dp"
        android:layout_marginRight="8dp"
        android:layout_marginEnd="8dp"/>

    <android.support.v4.widget.NestedScrollView
        android:id="@+id/profile_content_scroll"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clipToPadding="false"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        android:layout_gravity="fill_vertical"
        android:minHeight="192dp"
        android:overScrollMode="ifContentScrolls"
        >

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="@string/LoremIpsum"/>

        </RelativeLayout>

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

</android.support.design.widget.CoordinatorLayout>

答案 1

我在CollapsingToolbarLayout上遇到了完全相同的问题,里面有ImageViewNestedScrollView。松开手指时,抛掷滚动停止。

但是,我注意到了一些奇怪的事情。如果您使用 OnClickListener(例如 Button)从视图中开始用手指滚动,则甩动滚动效果很好。

因此,我用一个奇怪的解决方案修复了它。在 NestedScrollView 的直接子项上设置 OnClickListener(不执行任何操作)。然后它完美地工作!

<android.support.v4.widget.NestedScrollView 
   xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   app:layout_behavior="@string/appbar_scrolling_view_behavior">

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

    <!-- Page Content -->

  </LinearLayout>

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

为直接子项 (LinearLayout) 指定一个 id,并在“活动”中设置 OnClickListener

ViewGroup mContentContainer = (ViewGroup) findViewById(R.id.content_container);    
mContentContainer.setOnClickListener(this);

@Override
public void onClick(View view) {
    int viewId = view.getId();
}

笔记:

使用支持设计库 25.0.1 进行测试

CollapsingToolbarLayout with scrollFlags="scroll|enterAlwaysCollapsed"

答案 2

我知道这个问题在一年多前就被问到了,但这个问题似乎仍然没有在支持/设计库中得到解决。您可以为此问题加注星标,使其在优先级队列中向上移动。

也就是说,我尝试了大多数已发布的解决方案,包括patrick-iv的解决方案,但没有成功。我能够开始工作的唯一方法是模仿甩动,并在 中检测到一组特定条件时以编程方式调用它。在我调试的几个小时里,我注意到 从来没有在向上(向下滚动)甩动时调用过,并且似乎过早地消耗了。我不能100%肯定地说这将适用于100%的实现,但它对我的使用来说足够好,所以我最终解决了这个问题,即使它非常笨拙,绝对不是我想做的。onPreNestedScroll()onNestedFling()

public class NestedScrollViewBehavior extends AppBarLayout.Behavior {

    // Lower value means fling action is more easily triggered
    static final int MIN_DY_DELTA = 4;
    // Lower values mean less velocity, higher means higher velocity
    static final int FLING_FACTOR = 20;

    int mTotalDy;
    int mPreviousDy;
    WeakReference<AppBarLayout> mPreScrollChildRef;

    @Override
    public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child,
                                  View target, int dx, int dy, int[] consumed) {
        super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed);
        // Reset the total fling delta distance if the user starts scrolling back up
        if(dy < 0) {
            mTotalDy = 0;
        }
        // Only track move distance if the movement is positive (since the bug is only present
        // in upward flings), equal to the consumed value and the move distance is greater
        // than the minimum difference value
        if(dy > 0 && consumed[1] == dy && MIN_DY_DELTA < Math.abs(mPreviousDy - dy)) {
            mPreScrollChildRef = new WeakReference<>(child);
            mTotalDy += dy * FLING_FACTOR;
        }
        mPreviousDy = dy;
    }

    @Override
    public boolean onStartNestedScroll(CoordinatorLayout parent, AppBarLayout child,
                                       View directTargetChild, View target, int nestedScrollAxes) {
        // Stop any previous fling animations that may be running
        onNestedFling(parent, child, target, 0, 0, false);
        return super.onStartNestedScroll(parent, child, directTargetChild, target, nestedScrollAxes);
    }

    @Override
    public void onStopNestedScroll(CoordinatorLayout parent, AppBarLayout abl, View target) {
        if(mTotalDy > 0 && mPreScrollChildRef != null && mPreScrollChildRef.get() != null) {
            // Programmatically trigger fling if all conditions are met
            onNestedFling(parent, mPreScrollChildRef.get(), target, 0, mTotalDy, false);
            mTotalDy = 0;
            mPreviousDy = 0;
            mPreScrollChildRef = null;
        }
        super.onStopNestedScroll(parent, abl, target);
    }
}

并将其应用于应用栏

AppBarLayout scrollView = (AppBarLayout)findViewById(R.id.appbar);
CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams)scrollView.getLayoutParams();
params.setBehavior(new NestedScrollViewBehavior());

CheeseSquare 演示:之前之后


推荐