Dapatkan item yang terlihat di RecyclerView


Jawaban:


579

Anak terlihat pertama / terakhir tergantung pada LayoutManager. Jika Anda menggunakan LinearLayoutManageratau GridLayoutManager, Anda dapat menggunakan

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

Sebagai contoh:

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

Sebab LinearLayoutManager, pertama / terakhir tergantung pada pemesanan adaptor. Jangan meminta anak-anak dari RecyclerView; LayoutManagermungkin lebih suka mengatur lebih banyak item daripada yang terlihat untuk caching.


10
Apakah ada kemungkinan untuk mengakses metode ini dari RecyclerView.Adapter tanpa melewati referensi ke LayoutManager?
Yorgi

3
Seperti @Yorgi - di dalam adaptor sepertinya berguna. Saya ingin tahu apakah ada beberapa pola yang dapat Anda kembangkan dalam menggunakan onBindViewHolder untuk melacak mana yang sebenarnya ada di layar saat pengguna menggulir.
RoundSparrow hilltx

7
getItemCountdapat mengembalikan 1 dan findFirstVisibleItemPosition-1 pada panggilan yang sama.
mbmc

4
apa yang bisa Anda sarankan tentang StaggeredLayoutManager?
hornet2319

37
Metode-metode ini sangat tidak dapat diandalkan sehingga sama sekali tidak berguna. Terutama setelah notifyDataSetChanged / itemRemoved / RangeChanged
JK

12

Akhirnya, saya menemukan solusi untuk mengetahui apakah item saat ini terlihat, dari peristiwa onBindViewHolder di adaptor.

Kuncinya adalah metode isViewPartiallyVisible dari LayoutManager.

Di adaptor Anda, Anda bisa mendapatkan LayoutManager dari RecyclerView, yang Anda dapatkan sebagai parameter dari acara onAttachedToRecyclerView .


Tetapi di mana Anda akan memanggil metode ini di mana manajer tata letak tidak nol?
6rchid

Anda harus menunggu acara onAttachedToRecyclerView dari adaptor. Dalam peristiwa itu Anda menerima RecyclerView sebagai parameter; dan kemudian Anda bisa mendapatkan LayoutManager dari RecyclerVie, dan menyimpannya dalam global var. Jika LayoutManager adalah nol, mungkin bisa karena itu tidak ditugaskan ke RecyclerView di Activity / Fragment / Layout; dan mencoba membangun adaptor setelah penugasan itu.
Ernesto Vega

Menurut kode sumber, isViewPartiallyVisible rusak parah. Jika sepenuhnyaVisible benar, itu akan mengembalikan benar jika tampilan sepenuhnya terlihat. Namun, jika salah, itu hanya meniadakan hasil yang mengembalikan true jika tampilan sebagian terlihat atau tidak terlihat. Bahkan dokumentasinya tidak masuk akal.
Molanda


9

bagi mereka yang memiliki logika untuk diimplementasikan di dalam adaptor RecyclerView Anda masih dapat menggunakan pendekatan @ernesto dikombinasikan dengan pada scrollListener untuk mendapatkan what you wantsebagai berkonsultasi dengan RecyclerView. Di dalam adaptor Anda akan memiliki sesuatu seperti ini:

@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

Anda dapat menggunakan recyclerView.getChildAt()untuk mendapatkan setiap anak yang terlihat, dan menetapkan beberapa tag convertview.setTag(index)pada tampilan ini dalam kode adaptor akan membantu Anda untuk menghubungkannya dengan data adaptor.


Masalah dengan getChildAt () adalah bahwa urutan elemen dapat dari 5 elemen: 0, 5, 4, 3, 2, 1 (jumlah anak sebagian besar> = jumlah item yang terlihat). Jadi saya mencoba untuk mendapatkan urutan elemen melalui getGlobalVisibleRect.
bangkit

Apa kebutuhan Anda yang sebenarnya, dapatkan anak yang terlihat (anak di dalam layar terikat) dalam urutan yang sebenarnya?
Sreejith B Naick

Sekarang saya ingin tahu elemen mana yang ada di tengah, nanti saya mungkin juga tertarik dengan batasannya.
bangkit

1
Anda hanya akan mendapatkan item yang terlihat dari recyclerView.getChildAt(), itulah cara umumnya RecyclerViewbekerja. RecyclerViewakan mencoba untuk menahan hanya beberapa tampilan anak yang saat ini terlihat (yaitu; dalam batas layar, bukan Visibilitas sebagai GONE, TIDAK TERLIHAT) dan mencoba untuk mendaur ulang tampilan ini ketika pengguna menggulir.
Sreejith B Naick

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

5

Addendum :

fungsi yang diusulkan findLast ... Posisi () tidak tidak bekerja dengan benar dalam skenario dengan toolbar runtuh sementara toolbar diperluas.

Tampaknya tampilan pendaur ulang memiliki ketinggian tetap, dan sementara bilah alat diperluas, pendaur ulang dipindahkan ke bawah, sebagian keluar dari layar. Akibatnya, hasil fungsi yang diusulkan terlalu tinggi. Contoh: Item yang terlihat terakhir dikatakan sebagai # 9, tetapi sebenarnya item # 7 adalah yang terakhir yang ada di layar.

Perilaku ini juga merupakan alasan mengapa tampilan saya sering gagal untuk menggulir ke posisi yang benar, yaitu scrollToPosition () tidak berfungsi dengan benar (saya akhirnya menciutkan bilah alat pemrograman).


Itu benar, tetapi ini adalah cara kerja bilah alat runtuh. Saya berhenti mengembangkan Aplikasi Android setahun yang lalu, tetapi saya dapat mengingat fakta itu.
hidup kembali


3

Untuk StaggeredGridLayoutManagermelakukan ini:

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

Dan untuk mendapatkan tampilan item yang terlihat:

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

Ingatlah untuk memeriksa apakah itu kosong.


Apa maksudmu "periksa apakah kosong"? Bagaimana cara mengeceknya?
tmm1

viewsIdsadalah array, dan mungkin kosong.
Douglas Nassif Roma Junior
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.