2016-07-22 16 views
1

今日は非常に奇妙な問題があります。私はRecyclerViewに水平にいくつかのサムネイルを表示していますが、私は必要な項目にナビゲートするのにsmoothScrollToPositionを使用します。最後の項目にスクロールしないでください。さらにデバッグすると、私のリサイクルビューに表示されるものよりも子供が少なくなっています。私は一度に3つずつ、5つの項目を見る。 (recyclerView.getChildCountを取得した)子供の数は5の代わりに4を返します。最後の子はgetChildAt(4)で取得できません。さらにより奇妙、adapter.getItemCount()戻り5、及びrecyclerView.getAdapter().getItemCount()戻る5 ...RecyclerView子どもの数が子どもの数よりも少ない

recyclerView.getLayoutManager().getItemCount()戻る5を検査すると、と `recyclerView..getLayoutManager()のgetChildCount()は4を返し...

私は2つのものが必要です:まず、その最後のアイテムにスクロールするために私のrecyclerViewが必要です。そして、2番目:ユーザーがアイテムとやりとりするときに私はいくつかの変更を行うので、すべての子供を取得する必要があります。

いくつかのコード:

// Scrolling and editing the item inside the recyclerView 
// It doesn't scroll to position 4, even having a item there... 
mLayoutManager.smoothScrollToPosition(recyclerView, null, position); 

// the code bellow returns null if position = 4, even if the recyclerView adapter has a item at index 4, and it is visible... 
ImageView iv = (ImageView) recyclerView.getChildAt(position); 
if (iv != null) { 
    iv.setPadding(10, 10, 10, 10); 
    iv.setBackgroundColor(getResources().getColor(R.color.colorPrimaryDark)); 
    ImageView ivo = (ImageView) recyclerView.getChildAt(position - 1); 
    if (position - 1 == 0) { 
     ivo.setPadding(10, 10, 10, 10); 
    } else { 
     ivo.setPadding(0, 10, 10, 10); 
    } 
    ivo.setBackgroundColor(getResources().getColor(R.color.transparent)); 
} 

smoothScrollToPosition実装:

public class SnappingLinearLayoutManager extends LinearLayoutManager { 

    private static final float MILLISECONDS_PER_INCH = 150f; 

    public SnappingLinearLayoutManager(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 TopSnappedSmoothScroller(recyclerView.getContext()){ 
      @Override 
      public PointF computeScrollVectorForPosition(int targetPosition) { 
       return new PointF(0, 1); 
      } 

      //This returns the milliseconds it takes to scroll one pixel. 
      @Override 
      protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) { 
       return MILLISECONDS_PER_INCH/displayMetrics.densityDpi; 
      } 
     }; 
     smoothScroller.setTargetPosition(position); 
     startSmoothScroll(smoothScroller); 
    } 

    private class TopSnappedSmoothScroller extends LinearSmoothScroller { 
     public TopSnappedSmoothScroller(Context context) { 
      super(context); 

     } 

     @Override 
     public PointF computeScrollVectorForPosition(int targetPosition) { 
      return SnappingLinearLayoutManager.this 
        .computeScrollVectorForPosition(targetPosition); 
     } 

     @Override 
     protected int getVerticalSnapPreference() { 
      return SNAP_TO_ANY; 
     } 
    } 
} 
+2

RecycleViewは、アダプタのすべてのアイテムを保持していません。リサイクラビューリストの最初と最後には、表示されたビューのビュー+余分なものしかないため、より速くレンダリングすることができます。たぶんこれが問題です。 – Rafal

答えて

1

1)あなたはscrollToPosition(position)を使用することができ、リスト内の位置にスクロールします。あなたが渡す位置は、このような最後の項目のインデックスを次のようになります。

recyclerView.smoothScrollToPosition(adapter.getItemCount()) 

私はV7のRecyclerViewとアンドロイドのLinearLayoutManagerでの作業このアプローチを得ることができました。

build.gradle

... 
dependencies { 
    ... 
    compile 'com.android.support:appcompat-v7:23.4.0' 
    compile 'com.android.support:recyclerview-v7:23.4.0' 
    ... 
} 

RecyclerViewのレイアウトコード:

private void scrollToBottom() { 
    recyclerView.smoothScrollToPosition(recyclerView.getAdapter().getItemCount()); 
} 
:私は、リストの一番上までスクロールしたいとき

<android.support.v7.widget.RecyclerView android:id="@+id/item_list" 
    android:name="fbalashov.spikeapp.ItemListFragment" 
    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" 
    app:layoutManager="LinearLayoutManager" /> 

その後、私はちょうど私のscrollToBottomメソッドを呼び出します

これにより、RecyclerViewはスムーズにリストの最後の項目にスクロールします。

2)Rafalが述べているように、RecyclerView(とListView)は、画面上に表示されるアイテムと上部または下部にあるアイテムまたは2つのバッファのみを描画し、スクロールをきれいにします。スクロールすると、ビューがリサイクルされ、アダプタのデータが表示されます。したがって、上からスクロールされたビューは、リストの一番下に再利用され、次のアイテムからデータが再作成されます。

このように、アダプター内の項目のすべてのビューを同時に取得することはできません。ただし、アダプター内のすべての項目を取得して変更し、アダプターをトリガーしてadapter.notifyDataSetChanged()を使用してrecyclerViewのビューを再描画することができます。例:

// getItems() is a method you will have to add to you adapter to get the items from your 
// adapter. Otherwise you can add a method in your adapter to update the items. 
List<DataType> items = adapter.getItems(); 
for (DataType item : items) { 
    // make some change to each item 
} 
// this will force the recycler view to redraw its views 
adapter.notifyDataSetChanged(); 

また、単にアダプタでそれらの項目を更新し、notifyItemChanged(position)を使用して、アダプタ内の項目へのよりターゲットを絞った変更を加えることができます。

+0

Dr. Nitpickに感謝します!私はアニメーション化されていないので 'scrollToPosition'を使用しませんでした。アニメーションスクロールのために' smoothScrollToPosition'を使うべきであることを他の投稿が示唆しました...あなたがポイントを更新したり、 'scrollToPosition'を使ったアニメーションスクロール?カウントについては、アドバイスのおかげで、何らかの方法でビューにタグを付けるようにします。 –

+0

[RecyclerView from support v7](https://developer.android.com/)を使用していますか? topic/libraries/support-library/features.html#v7-recyclerview)?私はアンドロイドのLinearLayoutManagerでそれを使用して、 'smoothScrollToPosition'をオーバーライドしなくてもスムーズにスクロールしてリストの一番下までスクロールすることができました。私の答えにサンプルコードを追加する。 –

関連する問題