RecyclerView에서 보이는 항목 가져 오기


답변:


579

첫 번째 / 마지막으로 보이는 아이는에 따라 다릅니다 LayoutManager. 당신이 사용하는 경우 LinearLayoutManager또는 GridLayoutManager, 당신은 사용할 수 있습니다

int findFirstVisibleItemPosition();
int findFirstCompletelyVisibleItemPosition();
int findLastVisibleItemPosition();
int findLastCompletelyVisibleItemPosition();

예를 들면 다음과 같습니다.

GridLayoutManager layoutManager = ((GridLayoutManager)mRecyclerView.getLayoutManager());
int firstVisiblePosition = layoutManager.findFirstVisibleItemPosition();

의 경우 LinearLayoutManager첫 번째 / 마지막은 어댑터 순서에 따라 다릅니다. 에서 어린이를 쿼리하지 마십시오 RecyclerView. LayoutManager캐싱에 보이는 것보다 많은 항목을 레이아웃하는 것을 선호 할 수 있습니다.


10
LayoutManager에 대한 참조를 전달하지 않고 RecyclerView.Adapter에서이 메소드에 액세스 할 가능성이 있습니까?
Yorgi 2018

3
@ Yogi와 마찬가지로 어댑터 내부가 유용합니다. onBindViewHolder를 사용하여 사용자가 스크롤하는 동안 실제로 화면에 나타나는 패턴을 추적 할 수있는 패턴이 있는지 궁금합니다.
RoundSparrow hilltx

7
getItemCountfindFirstVisibleItemPosition동일한 호출에서 1과 -1을 반환 할 수 있습니다 .
mbmc

4
StaggeredLayoutManager에 대해 무엇을 제안 할 수 있습니까?
hornet2319

37
이 방법은 신뢰할 수 없으므로 완전히 쓸모가 없습니다. 특히 notifyDataSetChanged / itemRemoved / RangeChanged 이후
JK

12

마지막으로 어댑터의 onBindViewHolder 이벤트에서 현재 항목이 표시되는지 확인하는 솔루션을 찾았습니다.

핵심은 LayoutManager에서 isViewPartiallyVisible 메소드 입니다.

어댑터에서 RecyclerView에서 LayoutManager를 가져올 수 있으며 onAttachedToRecyclerView 이벤트 에서 매개 변수로 가져옵니다 .


그러나 레이아웃 관리자가 null이 아닌이 메소드를 어디에서 호출합니까?
6rchid

어댑터의 onAttachedToRecyclerView 이벤트를 기다려야합니다. 이 경우 RecyclerView를 매개 변수로받습니다. 그런 다음 RecyclerVie에서 LayoutManager를 가져 와서 전역 var에 저장할 수 있습니다. LayoutManager가 null 인 경우 Activity / Fragment / Layout에서 RecyclerView에 할당되지 않았기 때문일 수 있습니다. 할당 후 어댑터를 빌드하십시오.
Ernesto Vega

소스 코드에 따르면 isViewPartiallyVisible이 심하게 손상되었습니다. fullyVisible이 true 인 경우보기가 완전히 표시되면 true를 리턴합니다. 그러나 false이면 뷰가 부분적으로 표시되거나 표시되지 않으면 true를 반환하는 결과를 무시합니다. 문서조차도 이해가되지 않습니다.
Molanda


9

RecyclerView 어댑터 내에서 구현할 로직이있는 사용자는 @ernesto 접근 방식을 on scrollListener와 함께 사용 what you want하여 RecyclerView를 참조 할 수 있습니다. 어댑터 내부에는 다음과 같은 것이 있습니다.

@Override
    public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);
        RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
        if(manager instanceof LinearLayoutManager && getItemCount() > 0) {
            LinearLayoutManager llm = (LinearLayoutManager) manager;
            recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
                @Override
                public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
                    super.onScrollStateChanged(recyclerView, newState);
                }

                @Override
                public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
                    super.onScrolled(recyclerView, dx, dy);
                        int visiblePosition = llm.findFirstCompletelyVisibleItemPosition();
                        if(visiblePosition > -1) {
                            View v = llm.findViewByPosition(visiblePosition);
                            //do something
                            v.setBackgroundColor(Color.parseColor("#777777"));
                        }
                }
            });
        }
    }

7

recyclerView.getChildAt()각각의 보이는 자식을 가져 오는 데 사용할 수 있으며 convertview.setTag(index)어댑터 코드에서 이러한보기에 일부 태그 를 설정 하면 어댑터 데이터와 연관시키는 데 도움이됩니다.


getChildAt ()의 문제점은 요소의 순서가 0, 5, 4, 3, 2, 1의 5 개 요소 중 하나 일 수 있다는 것입니다 (자식 수는 대부분> = 표시 항목 수). 그래서 getGlobalVisibleRect를 통해 요소의 순서를 얻으려고했습니다.
rekire

실제 요구 사항은 무엇입니까? 실제 순서로 보이는 자식 (스크린 내부의 자식)을 얻으십시오.
Sreejith B Naick

이제 중심에 어떤 요소가 있는지 알고 싶습니다. 나중에 경계에 관심이있을 수도 있습니다.
rekire

1
에서 recyclerView.getChildAt()일반적인 항목 만 표시되는 항목 만 표시됩니다 RecyclerView. RecyclerView는 현재 표시되는 하위 뷰를 몇 개만 유지하려고합니다 (예 : 화면 경계 내에서 가시성으로 보이지 않음). 사용자 스크롤시 이러한 뷰를 재활용하려고합니다.
Sreejith B Naick

6
표시 visibleChild = recyclerView.getChildAt (0); int positionOfChild = recyclerView.getChildAdapterPosition (visibleChild);
Kevin Lee

4

다음 Linear / Grid LayoutManager방법을 사용하여 어떤 품목이 있는지 확인할 수 있습니다visible

int findFirstVisibleItemPosition();
int findLastVisibleItemPosition();
int findFirstCompletelyVisibleItemPosition();
int findLastCompletelyVisibleItemPosition();

is item visible on screen일부 임계 값 을 추적 하려면 다음 블로그를 참조하십시오.

https://proandroiddev.com/detecting-list-items-perceived-by-user-8f164dfb1d05


4

부록 : 도구 모음이 확장되어있는 동안 축소 도구 모음이있는 시나리오에서

제안 된 함수 findLast ... Position ()제대로 작동 하지 않습니다 .

리사이클 러보기의 높이는 고정되어 있으며 도구 모음이 확장 된 상태에서 리사이클 러는 화면 밖으로 부분적으로 이동합니다. 결과적으로 제안 된 기능의 결과가 너무 높습니다. 예 : 마지막으로 보이는 항목은 # 9라고하지만 실제로 항목 # 7은 화면에있는 마지막 항목입니다.

이 동작은 또한 내보기가 종종 올바른 위치로 스크롤하는 데 실패한 이유입니다.


사실이지만 이것이 축소 도구 모음의 작동 방식입니다. 1 년 전에 Android 앱 개발을 중단했지만 그 사실을 기억할 수 있습니다.
rekire

3

이를 StaggeredGridLayoutManager위해 :

RecyclerView rv = findViewById(...);
StaggeredGridLayoutManager lm = new StaggeredGridLayoutManager(...);
rv.setLayoutManager(lm);

그리고 보이는 항목보기를 얻으려면 :

int[] viewsIds = lm.findFirstCompletelyVisibleItemPositions(null);
ViewHolder firstViewHolder = rvPlantios.findViewHolderForLayoutPosition(viewsIds[0]);
View itemView = viewHolder.itemView;

비어 있는지 확인하십시오.


"비어 있는지 확인"이란 무엇입니까? 어떻게 확인합니까?
tmm1

viewsIds배열이며 비어있을 수 있습니다.
Douglas Nassif Roma Junior
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.