web-dev-qa-db-ja.com

RecyclerViewをスムーズにスクロールさせる方法は?

これは一般的な質問に似ていますが、多くの検索と試行を行った後、なぜこれを達成するのが難しいのか理解できません。 これ は、見つけることができる最も近い答えですが、まだ実装できません。

具体的には、GridLayoutManagerでRecyclerViewを使用しています。私が望むのは、スムーズにスクロールするグリッドレイアウト(デフォルトのギャラリーアプリのような)で、何も派手なものではありませんが、グリッドレイアウトマネージャーのデフォルトの実装は、ビューを「ぎくしゃくした」方法でスクロールします。上記のリンクからメソッドを実装しようとしましたが、失敗しました。

LinearSmoothScrollerも実装しようとしましたが、computeScrollVectorForPositionメソッドを実装する方法がわかりません。 Googleのドキュメント computeScrollVectorForPositionの場合、文字通り0ワードです。

この3部構成のチュートリアル が見つかりましたが、ほとんど役に立ちませんでした。だから、私が尋ねたいのは、LinearSmoothScrollerに実装できる、またはRecyclerView.SmoothScrollerを拡張してスムーズなスクロールを実現できるテンプレートコードがあるのでしょうか?コードがgridlayoutのアイテムの数と行ごとのアイテムに依存している場合でも、簡単にそれを行うには何らかの方法が必要です。ここに何かが足りませんか?

22
rockfight

Android)の「ぎくしゃくした」スクロールの典型的な原因は、UIを更新するメインアプリケーションスレッドでアプリに時間がかかりすぎることです。RecyclerViewの場合、これはonBindViewHolder()またはおそらくonCreateViewHolder()で時間がかかりすぎます。それぞれがミリ秒未満の時間で戻る必要があるため、ディスクI/OまたはネットワークI/Oを実行できません。

私は問題を見つけたと思います。 Holder.photo.setImageBitmap(BitmapFactory.decodeFile(itemList.get(position).get‌ AbsolutePath()));を使用していますonBindViewHolder()で、画像ファイルはそれぞれ約100kbで、リストに約12個の画像があります

はい、メインアプリケーションスレッドでディスクI/Oと画像デコードを行います。これは、UIでのジャンク(つまり、「ぎくしゃくした」スクロール)を引き起こすほど遅くなります。

PicassoやUniversal Image Loaderなどの画像読み込みライブラリを使用することを検討してください。これらは、ビットマップからImageViewを非同期に取り込むことができます。

このサンプルアプリ は、Universal Image Loaderを使用して、RecyclerViewのコンテンツ(GridLayoutManagerを含む)にデータソースをデバイスで使用できるようにします。

33
CommonsWare

RecyclerViewまたはActivityFragmentを宣言した場所にこれを追加します

_RecyclerView mRecyclerview = (RecyclerView) findViewById(...);
mRecyclerview.setNestedScrollingEnabled(false);
_

setNestedScrollview(false)はあなたのために仕事をします。

33
Ahmed Raza

私はこの問題に直面したばかりで、ネストされたスクロールを無効にすると修正されました。次のようにします:

yourRecyclerview.setNestedScrollingEnabled(false);

または、RecyclerViewを定義したxmlファイルの値を変更できます。

<Android.support.v7.widget.RecyclerView
    Android:id="@+id/yourRecyclerView"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:nestedScrollingEnabled="false"/>
11

この問題に直面したばかりで、RecyclerViewScrollViewに入れるようになったので、RecyclerViewScrollViewの中に入れないでください。

mLayoutManager.findFirstVisibleItemPosition()

それは常に固定値を返します。また、確認してください

recyclerview.setNestedScrollingEnabled(false);
3
Shyam Sundar

calculateSpeedPerPixel(DisplayMetrics displayMetrics)メソッドをオーバーライドして、スクロールをスムーズにしました。

public class CustomLayoutManager extends LinearLayoutManager {

    protected CenterLayoutManager(Context context, int orientation, boolean reverseLayout) {
        super(context, orientation, reverseLayout);
    }

    @Override
    public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {
        RecyclerView.SmoothScroller smoothScroller = new CenterSmoothScroller(recyclerView.getContext());
        smoothScroller.setTargetPosition(position);
        startSmoothScroll(smoothScroller);
    }

    private class CenterSmoothScroller extends LinearSmoothScroller {

        CenterSmoothScroller(Context context) {
            super(context);
        }

        @Override
        public int calculateDtToFit(int viewStart, int viewEnd, int boxStart, int boxEnd, int snapPreference) {
            return (boxStart + (boxEnd - boxStart) / 2) - (viewStart + (viewEnd - viewStart) / 2);
        }

        @Override
        protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
            return 0.5f; //pass as per your requirement
        }
    }
}
2
SKP
Android:animateLayoutChanges="false"
1