RecyclerView में दृश्यमान वस्तुएं प्राप्त करें


268

मुझे यह जानने की जरूरत है कि वर्तमान में मेरे RecyclerView में कौन से तत्व प्रदर्शित हैं। OnScrollListener.onScroll(...)ListViews पर विधि के बराबर कोई नहीं है । मैंने साथ काम करने की कोशिश की View.getGlobalVisibleRect(...), लेकिन वह हैक बहुत बदसूरत है और हमेशा काम भी नहीं करता है।

किसी को कोई विचार?

जवाबों:


578

पहले / अंतिम दृश्यमान बच्चे पर निर्भर करता है LayoutManager। यदि आप उपयोग कर रहे हैं LinearLayoutManagerया GridLayoutManager, आप उपयोग कर सकते हैं

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

उदाहरण के लिए:

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

के लिए LinearLayoutManager, पहले / अंतिम एडेप्टर ऑर्डर करने पर निर्भर करता है। बच्चों से क्वेरी न करें RecyclerView; LayoutManagerकैशिंग के लिए दृश्यमान से अधिक आइटम लेआउट करना पसंद कर सकते हैं।


10
क्या लेआउटमैनेजर के सन्दर्भ के बिना RecyclerView.Adapter से इस तरीके तक पहुँचने की कोई संभावना है?
योर्गी

3
@Yorgi की तरह - एडाप्टर के अंदर उपयोगी लगता है। मुझे आश्चर्य है कि अगर कोई पैटर्न है जिसे आप onBindViewHolder का उपयोग करके ट्रैक कर सकते हैं कि कौन-से लोग वास्तव में ऑन-स्क्रीन हैं जबकि उपयोगकर्ता स्क्रॉल करता है।
राउंडस्पारो हिल्टैक्स

7
getItemCountfindFirstVisibleItemPositionएक ही कॉल पर 1 और -1 वापस कर सकते हैं ।
mbmc

4
क्या आप के बारे में सुझाव दे सकते हैं StaggeredLayoutManager?
Hornet2319

37
ये विधियाँ इतनी अविश्वसनीय हैं कि वे पूरी तरह से बेकार हैं। विशेष रूप से सूचना के बादडेटासेटेट किया गया / आइटम किया गया / रेंज किया गया
जेके

12

अंत में, मुझे यह जानने के लिए एक समाधान मिला कि क्या चालू वस्तु दिखाई दे रही है, एडॉप्टर में onBindViewHolder इवेंट से।

कुंजी लेआउटमैनेजर से .ViewPartiallyV अदृश्य है।

अपने एडेप्टर में, आप RecyclerView से LayoutManager प्राप्त कर सकते हैं, जो आपको onAttachedToRecyclerView इवेंट से पैरामीटर के रूप में मिलता है ।


लेकिन आप इस पद्धति को कहां से कहेंगे जिसमें लेआउट प्रबंधक शून्य नहीं है?
6rchid

आपको एडाप्टर के onAttachedToRecyclerView इवेंट की प्रतीक्षा करनी होगी। उस घटना में आपको पैरामीटर के रूप में RecyclerView प्राप्त होता है; और फिर आप RecyclerVie से LayoutManager प्राप्त कर सकते हैं, और इसे एक वैश्विक संस्करण में सहेज सकते हैं। यदि LayoutManager अशक्त है, तो शायद इसलिए कि यह गतिविधि / खंड / लेआउट में RecyclerView को नहीं सौंपा गया था; और उस असाइनमेंट के बाद एडेप्टर बनाने की कोशिश करें।
अर्नेस्टो वेगा

स्रोत कोड के अनुसार, isViewPartiallyV अदृश्य बुरी तरह से टूट गया है। यदि दृश्य पूरी तरह से अदृश्य है, तो दृश्य पूर्ण रूप से दिखाई देने पर वापस आ जाएगा। हालाँकि, यदि गलत है, तो यह केवल उस परिणाम की उपेक्षा करता है जो दृश्य में आंशिक रूप से दिखाई नहीं देता है या दिखाई नहीं देता है। यहां तक ​​कि प्रलेखन का कोई मतलब नहीं है।
मोलंडा


9

उन लोगों के लिए जिनके पास RecyclerView एडेप्टर के अंदर कार्यान्वित होने का तर्क है, आप अभी भी @ernesto दृष्टिकोण का उपयोग कर सकते हैं, जो कि स्क्रॉललेस्टनर के साथ संयुक्त हो सकता है 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 () के साथ समस्या यह है कि तत्वों का क्रम 5 तत्वों से बाहर हो सकता है: 0, 5, 4, 3, 2, 1 (बच्चे की गिनती ज्यादातर> = दृश्यमान वस्तुओं की गिनती है)। इसलिए मैंने getGlobalVanishRect के माध्यम से तत्व का क्रम प्राप्त करने की कोशिश की।
बजे

आपकी वास्तविक आवश्यकता क्या है, वास्तविक क्रम में दृश्यमान बच्चा (स्क्रीन बाउंड के अंदर का बच्चा) प्राप्त करें?
श्रीजिथ बी नाइक

अब मैं जानना चाहता हूं कि कौन सा तत्व केंद्र में है, बाद में मैं शायद सीमा में भी दिलचस्पी लेता हूं।
खोलें

1
आपको केवल दृश्यमान आइटम ही मिलेंगे recyclerView.getChildAt(), यानी आम तौर पर कैसे RecyclerViewकाम करता है। RecyclerViewकेवल कुछ ही बच्चे के विचारों को रखने की कोशिश करेंगे जो वर्तमान में दिखाई दे रहे हैं (यानी, स्क्रीन सीमा के भीतर, दृश्यता के रूप में दृश्यता नहीं, अदृश्य) और उपयोगकर्ता स्क्रॉल करते समय इन विचारों को पुन: चक्रित करने का प्रयास करें।
श्रीजिथ बी नाइक

6
दृश्यमान दृश्य देखें = recyclerView.getChildAt (0); int positionOfChild = recyclerView.getChildAdapterPosition (दृश्यमान);
केविन ली

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 ... स्थिति () है नहीं एक गिर उपकरण पट्टी के साथ एक परिदृश्य में सही ढंग से काम करते हुए उपकरण पट्टी का विस्तार किया गया है।

ऐसा लगता है कि पुनर्नवीनीकरण दृश्य की एक निश्चित ऊंचाई है, और जब उपकरण पट्टी का विस्तार किया जाता है, तो पुनर्नवीनीकरण को नीचे ले जाया जाता है, आंशिक रूप से स्क्रीन से बाहर। परिणामस्वरूप प्रस्तावित कार्यों के परिणाम बहुत अधिक हैं। उदाहरण: अंतिम दिखाई देने वाली वस्तु # 9 बताई गई है, लेकिन वास्तव में आइटम # 7 अंतिम ऐसा है जो स्क्रीन पर है।

यह व्यवहार भी यही कारण है कि मेरा दृष्टिकोण अक्सर सही स्थिति तक स्क्रॉल करने में विफल रहा, यानी स्क्रॉलटूपन () सही तरीके से काम नहीं करता था (मैंने आखिरकार टूलबार को प्रोग्रामिक रूप से ढहा दिया)।


यह सच है, लेकिन यह कैसे ढहने वाला टूलबार काम करता है। मैंने एक साल पहले एंड्रॉइड ऐप विकसित करना बंद कर दिया था, लेकिन मैं इस तथ्य को याद रख सकता हूं।
21:06

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एक सरणी है, और यह खाली हो सकता है।
डगलस नासिफ रोमा जूनियर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.