12

使用 AppBarLayout 和 Toolbar 的最基本示例,当尝试滚动更多时,我看不到过度滚动动画(从底部或顶部发光)。但是,如果您投掷内容,它将显示它。

这是代码(nav_drawer_toolbar_layout.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">

    <!-- Replace fragments in this content frame, like a RecycleView -->
    <FrameLayout
        android:id="@+id/content_frame"
        app:layout_behavior="android.support.design.widget.AppBarLayout$ScrollingViewBehavior"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:minHeight="?attr/actionBarSize"
            app:titleTextAppearance="@style/Base.TextAppearance.AppCompat.Title"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
            app:layout_scrollFlags="scroll|enterAlways"/>
    </android.support.design.widget.AppBarLayout>

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

其次是简单的Activity类:

public class MyActivity extends AppCompatActivity implements {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.nav_drawer_toolbar_layout);

        // Setup the toolbar/actionbar
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        FragmentManager manager = getFragmentManager();
        manager.beginTransaction().replace(R.id.content_frame, new MyFragmentList).commit();
    }
}

MyFragmentList 是一个带有 RecycleView 的片段,其中包含滚动应用程序的内容。

但是,如果我从 xml 中删除 AppBarLayout 并使工具栏保持打开状态(只需注释 AppBarLayout 打开和关闭),它会在滚动时显示过度滚动动画(发光)。

或者,如果您删除layout_scrollFlags="scroll",则过度滚动有效,但滚动时无法隐藏操作栏。

有关更多信息,请调试 RecycleView,第 2272 行

if(this.mBottomGlow != null && !this.mBottomGlow.isFinished()) {

包含 AppBarLayout 时始终完成,不存在时未完成。是否有东西覆盖了它的触摸事件?

有谁知道谁用 AppBarLayout 显示过度滚动动画(发光)?

4

1 回答 1

3

编辑:这个错误似乎有一张。您可以肯定地做 artur.dr...@gmail.com 所做的事情并扩展 RecyclerView 以覆盖 RecyclerView#dispatchNestedScroll 以始终返回 false (他在报告中写了 true )您可以使过度滚动动画正常工作,尽管我很确定可能会破坏某些东西。

不幸的是,RecyclerView 是如何编码的以及 NestedScrollingChild API 是如何制作的,没有干净的方法来获得所需的行为。

这是来自方法 scrollByInternal 中的 RecyclerView(23.1.1,但我不相信在它解决问题之前的任何版本)。

if (dispatchNestedScroll(consumedX, consumedY, unconsumedX, unconsumedY, mScrollOffset)) {
    // Update the last touch co-ords, taking any scroll offset into account
    mLastTouchX -= mScrollOffset[0];
    mLastTouchY -= mScrollOffset[1];
    if (ev != null) {
        ev.offsetLocation(mScrollOffset[0], mScrollOffset[1]);
    }
    mNestedOffsets[0] += mScrollOffset[0];
    mNestedOffsets[1] += mScrollOffset[1];
} else if (ViewCompat.getOverScrollMode(this) != ViewCompat.OVER_SCROLL_NEVER) {
    if (ev != null) {
        pullGlows(ev.getX(), unconsumedX, ev.getY(), unconsumedY);
    }
    considerReleasingGlowsOnScroll(x, y);
}

正如我们在 dispatchNestedScroll(NestedScrollingChild API 的一部分)的 javadoc 中看到的,只要有一个父级消耗滚动,RecyclerView 就不会应用任何过度滚动动画(边缘发光)。

AppBarLayout 确实会消耗滚动,更具体地说,只要有一个在 onStartNestedScroll 上返回 true 的 NestedScrollingParent,就不会发生过度滚动动画。

CoordinatorLayout 是一个 NestedScrollingParent 但不会返回 true,除非有一个 CoordinatorLayout.Behavior 这样做。AppBarLayout 的默认行为确实实现了此方法以在垂直滚动时返回 true + AppBarLayout 有要滚动的内容 + 视图足够大以滚动。

// Return true if we're nested scrolling vertically, and we have scrollable children
// and the scrolling view is big enough to scroll
final boolean started = (nestedScrollAxes & ViewCompat.SCROLL_AXIS_VERTICAL) != 0
            && child.hasScrollableChildren()
            && parent.getHeight() - directTargetChild.getHeight() <= child.getHeight();

Flinging 采用稍微不同的方法,无论 NestedScrollingParent 是否正在消耗滚动,都允许发生过度滚动动画。

if (!dispatchNestedPreFling(velocityX, velocityY)) {
    final boolean canScroll = canScrollHorizontal || canScrollVertical;
    dispatchNestedFling(velocityX, velocityY, canScroll);

    if (canScroll) {
        velocityX = Math.max(-mMaxFlingVelocity, Math.min(velocityX, mMaxFlingVelocity));
        velocityY = Math.max(-mMaxFlingVelocity, Math.min(velocityY, mMaxFlingVelocity));
        mViewFlinger.fling(velocityX, velocityY);
        return true;
    }
}

老实说,我无法判断这是否是一个错误,因为这两种逻辑都有意义。如果您正在滚动到视图的顶部,并且您有类似于 CollapsingToolbar 的东西,那么您不希望发生 overscoll 动画。但是,有一种方法可以使行为可以消耗 x/y 滚动量来阻止动画的发生。滚动和投掷的代码不同也很奇怪。

于 2015-11-21T03:17:41.300 回答