1

오늘은 아주 이상한 문제가 있습니다. 나는 리모컨 일부를 가로로 표시하는 RecyclerView가 있는데, 나는 필요한 항목으로 이동하기 위해 smoothScrollToPosition을 사용하지만 문제가 있음을 알게되었습니다. 마지막 항목으로 스크롤하지 않습니다. 추가 디버깅을 할 때, 나는 나의 recyclerview가 그것보다 더 적은 아이들을 가지고있는 것을 발견했다! 한 번에 3 개씩 5 개의 항목이 표시됩니다. 그러나 아이들 카운트 (recyclerView.getChildCount)는 5 대신 4를 반환하고, 마지막 아이를 getChildAt(4)으로 가져올 수 없습니다. 더욱 이상한의 adapter.getItemCount() 수익률 5 및 recyclerView.getAdapter().getItemCount() 돌아 오 ...RecyclerView 어린이 수가 어린이 수보다 작습니다.

layoutAdapter, recyclerView.getLayoutManager().getItemCount() 반환 (5) 검사에, 그리고`recyclerView..getLayoutManager(). getChildCount()는 4를 반환 ...

두 가지가 필요합니다. : 먼저 마지막 항목으로 스크롤하려면 recyclerView가 필요합니다. 둘째 : 사용자가 항목과 상호 작용할 때 일부 수정을 수행하므로 모든 하위 항목을 가져올 수 있어야합니다.

일부 코드 :

// 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 레이아웃 코드 : 그런 다음

<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 메소드를 호출 목록의 맨 위로 이동하려면 :

private void scrollToBottom() { 
    recyclerView.smoothScrollToPosition(recyclerView.getAdapter().getItemCount()); 
} 

이렇게하면 RecyclerView가 목록의 마지막 항목으로 부드럽게 스크롤됩니다.

2) Rafal이 말한 것처럼 RecyclerView (및 ListView)는 화면에 표시되는 항목과 위쪽 또는 아래쪽에있는 항목 또는 두 개의 버퍼 만 그리면 스크롤 모양이 멋지게 보입니다. 스크롤하면보기를 "재활용"하여 어댑터의 데이터로 채 웁니다. 따라서 상단에서 스크롤되는보기는 목록의 맨 아래에서 다음 항목의 데이터 형식으로 다시 사용됩니다.

따라서 어댑터의 항목에 대한 모든보기를 동시에 가져올 수 없습니다. 그러나 어댑터의 모든 항목을 가져 와서 수정 한 다음 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'을 오버라이드 할 필요없이 목록 맨 아래로 부드러운 스크롤을 구현할 수있었습니다. 아쉽게도 답안에 예제 코드를 추가하십시오. –