12

AppBarLayout とツールバーの最も基本的な例を使用すると、さらにスクロールしようとすると、オーバースクロール アニメーション (下または上からのグロー) が表示されません。ただし、コンテンツを投げると表示されます。

コードは次のとおりです (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>

単純なアクティビティ クラスが続きます。

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);
}

スクロールを消費する親が 1 つある限り、dispatchNestedScroll (NestedScrollingChild API の一部) の javadoc でわかるように、RecyclerView はオーバースクロール アニメーション (エッジ グロー) を適用しません。

AppBarLayout はスクロールを消費します。具体的には、onStartNestedScroll で true を返す NestedScrollingParent がある限り、オーバースクロール アニメーションは発生しません。

CoordinatorLayout は NestedScrollingParent ですが、true を返す CoordinatorLayout.Behavior がない限り、true を返しません。AppBarLayout のデフォルトの動作は、このメソッドを実装して、垂直スクロールがあり、AppBarLayout にスクロールするものがあり、ビューがスクロールするのに十分な大きさである場合に true を返します。

// 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 に似たものがある場合、オーバースクロール アニメーションが発生することは望ましくありません。ただし、動作が x/y 量のスクロールを消費してアニメーションの発生を停止できるようにする方法があります。スクロールとフリンジの両方のコードが異なるのも奇妙です。

于 2015-11-21T03:17:41.300 に答える