RecyclerView'da görünür öğeler edinin


Yanıtlar:


579

İlk / son görünür çocuk LayoutManager. Eğer kullanıyorsanız LinearLayoutManagerveya GridLayoutManagerkullanabileceğiniz

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

Örneğin:

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

Çünkü LinearLayoutManager, ilk / son adaptör sırasına bağlıdır. Çocukları sorgulamayın RecyclerView; LayoutManagerönbellek için görünenden daha fazla öğe düzenlemeyi tercih edebilir.


10
Bu yöntemlere LayoutManager'a başvurmadan RecyclerView.Adapter üzerinden erişme imkanı var mı?
Yorgi

3
@Yorgi gibi - adaptörün içinde faydalı görünüyor. Bir kullanıcı kaydırırken hangilerinin aslında ekranda olduğunu izlemek için onBindViewHolder kullanarak geliştirebileceğiniz bazı model olup olmadığını merak ediyorum.
RoundSparrow hilltx

7
getItemCountfindFirstVisibleItemPositionaynı çağrıda 1 ve -1 döndürebilir .
mbmc

4
StaggeredLayoutManager hakkında ne önerebilirsiniz?
hornet2319

37
Bu yöntemler o kadar güvenilmez ki tamamen işe yaramazlar. Özellikle bildirildikten sonraVeriSetChanged / itemRemoved / RangeChanged
JK

12

Son olarak, bağdaştırıcıdaki onBindViewHolder olayından geçerli öğenin görünür olup olmadığını bilmek için bir çözüm buldum.

Anahtar LayoutManager gelen isPlayPartiallyVisible yöntemidir .

Bağdaştırıcınızda, LayoutManager'ı onAttachedToRecyclerView olayından parametre olarak aldığınız RecyclerView'den alabilirsiniz .


Ancak mizanpaj yöneticisinin boş olmadığı bu yöntemi nereden çağırabilirsiniz?
6rchid

Bağdaştırıcının onAttachedToRecyclerView olayını beklemeniz gerekir. Bu durumda RecyclerView olarak parametre alırsınız; ve sonra LayoutManager'ı RecyclerVie'den alabilir ve global bir var. LayoutManager boşsa, büyük olasılıkla Activity / Fragment / Layout içindeki RecyclerView öğesine atanmamış olabilir; ve bu atamadan sonra bağdaştırıcıyı oluşturmaya çalışın.
Ernesto Vega

Kaynak koduna göre, isViewPartiallyVisible kötü bir şekilde bozuldu. TotallyVisible doğruysa, görünüm tamamen görünürse true değerini döndürür. Ancak, false olursa, görünüm kısmen görünürse veya görünmüyorsa true değerini döndüren sonucu reddeder. Belgeler bile mantıklı değil.
Molanda


9

RecyclerView bağdaştırıcısının içine uygulanacak bir mantığı olanlar için RecernlerView'a what you wantbaşvuruldukça almak üzere bir scrollListener ile birlikte @ ernesto yaklaşımını kullanabilirsiniz . Adaptörün içinde böyle bir şey olacak:

@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()Her görünür alt öğeyi almak için kullanabilirsiniz ve convertview.setTag(index)bağdaştırıcı kodunda bu görünümde bir etiket ayarlamak , bağdaştırıcı verileriyle ilişkilendirmenize yardımcı olacaktır.


GetChildAt () ile ilgili sorun, öğelerin sırasının 5 öğeden olabilmesidir: 0, 5, 4, 3, 2, 1 (alt öğe sayısı çoğunlukla = = görünür öğelerin sayısıdır). Bu yüzden elemanın sırasını getGlobalVisibleRect aracılığıyla almaya çalıştım.
rekire

Gerçek gereksiniminiz nedir, gerçek sırayla görünür çocuk (ekran içi çocuk bağlı) olsun?
Sreejith B Naick

Şimdi hangi elementin ortada olduğunu bilmek istiyorum, daha sonra belki de sınırlarla ilgileniyorum.
rekire

1
Sadece görünür öğeler alırsınız recyclerView.getChildAt(), bu genellikle böyle RecyclerViewçalışır. RecyclerViewşu anda görünür olan yalnızca birkaç alt görünümü tutmaya çalışacaktır (ör. ekran sınırları dahilinde Görünürlüğü GONE, INVISIBLE olarak değil) ve kullanıcı kaydırdığında bu görünümleri geri dönüştürmeye çalışacaktır.
Sreejith B Naick

6
Görünüm visibleChild = recyclerView.getChildAt (0); int positionOfChild = recyclerView.getChildAdapterPosition (visibleChild);
Kevin Lee

5

Zeyilname :

Önerilen fonksiyonlar FindLast ... Konumu () do not araç çubuğu genişletilmiş durumdayken bir çöken araç çubuğu ile bir senaryoda düzgün çalışabilmesi.

Geri dönüşümcü görünümünün sabit bir yüksekliği vardır ve araç çubuğu genişletilirken geri dönüşüm cihazı kısmen ekranın dışına taşınır. Sonuç olarak, önerilen işlevlerin sonuçları çok yüksektir. Örnek: Son görünür öğenin # 9 olduğu söylenir, ancak aslında # 7 öğesi ekranda görüntülenen son öğedir.

Bu davranış aynı zamanda görünümümün genellikle doğru konuma kaydırılamamasının nedenidir, yani scrollToPosition () düzgün çalışmadı (sonunda araç çubuğunu programlı olarak daralttım).


Bu doğrudur, ancak daraltma araç çubuğu bu şekilde çalışır. Bir yıl önce Android Uygulamaları geliştirmeyi bıraktım, ancak bu gerçeği hatırlıyorum.
1919'da

4

Linear / Grid LayoutManagerHangi öğelerin olduğunu kontrol etmek için aşağıdaki yöntemler kullanılabilirvisible

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

ve eğer bir is item visible on screeneşik değeri izlemek istiyorsanız , aşağıdaki bloga başvurabilirsiniz.

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


3

Bunun için StaggeredGridLayoutManager:

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

Görünür öğe görünümleri elde etmek için:

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

Boş olup olmadığını kontrol etmeyi unutmayın.


Ne demek "boş olup olmadığını kontrol et"? Kişi nasıl kontrol eder?
tmm1

viewsIdsbir dizidir ve boş olabilir.
Douglas Nassif Roma Junior
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.