कैसे पता करें कि एक RecyclerView / LinearLayoutManager को ऊपर या नीचे स्क्रॉल किया जाता है?


81

वर्तमान में मैं यह जांचने के लिए अनुसरण कोड का उपयोग कर रहा हूं कि क्या SwipeRefreshLayout सक्षम होना चाहिए।

private void laySwipeToggle() {
    if (mRecyclerView.getChildCount() == 0 || mRecyclerView.getChildAt(0).getTop() == 0) {
        mLaySwipe.setEnabled(true);
    } else {
        mLaySwipe.setEnabled(false);
    }
}

लेकिन यहाँ समस्या है। जब इसे किसी दूसरे आइटम के दृश्य की सीमा तक स्क्रॉल किया जाता है, तो वह mRecyclerView.getChildAt(0).getTop()0 भी देता है।

समस्या

कुछ ऐसा है RecyclerView.isScrolledToBottom()या RecyclerView.isScrolledToTop()?

संपादित करें: (mRecyclerView.getChildAt(0).getTop() == 0 && linearLayoutManager.findFirstVisibleItemPosition() == 0)किस तरह का है RecyclerView.isScrolledToTop(), लेकिन इसके बारे में क्या RecyclerView.isScrolledToBottom()?


मुझे लगता है कि उत्तरार्द्ध को पिछले बच्चे यानी mRecyclerView.getBottom () == linearLayoutmanager.findViewbyPosition (adapter.getItemCount () - 1) .getBottom ()
humblerookie

@ सरेन आर्टेरियस आप इस
शेराज़ अहमद खिलजी

जवाबों:


109

इसका समाधान लेआउट मैनेजर में है।

LinearLayoutManager layoutManager = new LinearLayoutManager(this);

// Add this to your Recycler view
recyclerView.setLayoutManager(layoutManager);

// To check if at the top of recycler view
if(layoutManager.firstCompletelyVisibleItemPosition()==0){
    // Its at top
}

// To check if at the bottom of recycler view
if(layoutManager.lastCompletelyVisibleItemPosition()==data.size()-1){
    // Its at bottom
}

संपादित करें

यदि आपके आइटम का आकार स्क्रीन से बड़ा है तो शीर्ष घटना का पता लगाने के लिए निम्नलिखित का उपयोग करें।

RecyclerView recyclerView = (RecyclerView) view;
LinearLayoutManager linearLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();

int pos = linearLayoutManager.findFirstVisibleItemPosition();

if(linearLayoutManager.findViewByPosition(pos).getTop()==0 && pos==0){
    return true;
}

पुनश्च: वास्तव में, यदि आप RecyclerViewसीधे अंदर रखते हैं तो SwipeRefreshviewआपको ऐसा करने की आवश्यकता नहीं होगी


नहीं, यह तब भी होता है जब RecyclerView SwipeRefreshLayout का प्रत्यक्ष बच्चा है। लेकिन FirstCompletelyVoubleItemPosition की जाँच करने से समस्या ठीक हो जाती है। मुझे यहां कुछ बताने की जरूरत है। यदि कोई भी आइटम पूरी तरह से पहले दिखाई नहीं दे रहा है तो पहले से ही अदृश्य ItemPosition () रिटर्न -1। तो यह समाधान तब काम नहीं करेगा जब पहला आइटम RecyclerView में फिट नहीं होगा जब इसे ऊपर स्क्रॉल किया जाएगा। लेकिन यह बहुत दुर्लभ स्थिति है।
eluleci

1
@eluleci: यह जांचने के लिए कि क्या सूची शीर्ष RecyclerView rc = (RecyclerView) दृश्य पर है; LinearLayoutManager lm = (LinearLayoutManager) rc.getLayoutManager (); if (lm.findViewByPosition (lm.findFirstVanishVemPosition ())। getTop () == 0 && lm.findFirstVanishItemPosition () == 0 0 सही है; // यदि आइटम स्क्रीन से बड़े आकार का है तो यह काम करेगा
humblerookie

2
यह विफल होगा यदि आइटम (पहली या अंतिम) पूरी स्क्रीन से बड़ी है। क्योंकि, first/lastCompletelyVisibleItemPosition()-1 वापस आ जाएगा, इसका मतलब है, कोई भी पूरी तरह से दिखाई देने वाली वस्तु नहीं है।
सुबीन सेबेस्टियन

4
दोनों lastVisibleItemPositionऔर lastCompletelyVisibleItemPositionकाम नहीं करते। (विधि हल नहीं कर सकते)। मदद?
स्टारडस्ट

4
findLastCompletelyVisibleItemPositionयदि अंतिम आइटम की ऊंचाई स्क्रीन की ऊंचाई से अधिक है, तो विफल हो जाएगा। इसका मतलब है कि अंतिम आइटम दिखाई दे रहा है, लेकिन पूरी तरह से दिखाई नहीं दे रहा है, इसलिए layout.findLastCompletelyVisibleItemPosition()=-1(RecyclerView.NO_POSITION)lastVisibleItemPositionलेआउट में अंतिम दृश्य के निचले भाग के लिए उपयोग और जांच अधिक सुरक्षित होगी।
चला गया

78

आप कोशिश कर सकते हैं recyclerView.canScrollVertically(int direction), अगर आपको सिर्फ यह जानना है कि स्क्रॉल करना संभव है या नहीं।

दिशा पूर्णांक:

  • -1 के लिए
  • 1 नीचे के लिए
  • 0 हमेशा झूठे लौटेगा।

यह एक अंतराल पर दोहराया जाना होगा, हालांकि, है ना?
स्टारडस्ट

1
आप इसे recyclerView.addOnScrollListener..it में एक आकर्षण की तरह काम कर सकते हैं ... धन्यवाद
therealprashant

2
महान! जब हम स्क्रॉलिंग के अंत तक पहुँचते हैं तो यह गलत होता है, मुझे इस घटना की आवश्यकता थी।
बॉक्स

1
अति उत्कृष्ट। onScrollStateChangedमेरे लिए काम में यह प्रयोग करें ।
लाईम ज़ॉय

5
दिशा पूर्णांक: -1 अप के लिए, नीचे के लिए 1, 0 हमेशा गलत होगा।
ग्रुक

33

यह जांचने के लिए कि RecyclerViewनीचे स्क्रॉल किया गया है या नहीं । निम्नलिखित कोड का उपयोग करें।

/**
     * Check whether the last item in RecyclerView is being displayed or not
     *
     * @param recyclerView which you would like to check
     * @return true if last position was Visible and false Otherwise
     */
    private boolean isLastItemDisplaying(RecyclerView recyclerView) {
        if (recyclerView.getAdapter().getItemCount() != 0) {
            int lastVisibleItemPosition = ((LinearLayoutManager) recyclerView.getLayoutManager()).findLastCompletelyVisibleItemPosition();
            if (lastVisibleItemPosition != RecyclerView.NO_POSITION && lastVisibleItemPosition == recyclerView.getAdapter().getItemCount() - 1)
                return true;
        }
        return false;
    }

कुछ अतिरिक्त जानकारी

आप लागू करना चाहते हैं ScrollToBottomमें RecyclerViewजब Edittextहै tappedतो मैं आप जोड़ने की सलाह देते 1 सेकंड की देरी इस तरह:

 edittext.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if (event.getAction() == MotionEvent.ACTION_UP)
                    if (isLastItemDisplaying(recyclerView)) {
// The scrolling can happen instantly before keyboard even opens up so to handle that we add 1 second delay to scrolling
                        recyclerView.postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                recyclerView.smoothScrollToPosition(recyclerView.getAdapter().getItemCount() - 1);

                            }
                        }, 1000);
                    }
                return false;
            }
        });

मेरे लिए काम किया। मैं RecyclerView के लिए इसे जोड़ने के लिए था addOnScrollListener () , हालांकि
aphoe

1
यह नॉट टूविल केस के लिए काम करता है, जहां रिसाइकलव्यू में एक आइटम है और यह पूरी तरह से दिखाई देता है।
techtinkerer

आपने एक दिन बचाया
रीना

22

@Saren Arterius, का उपयोग करते हुए addOnScrollListener की RecycleView , आप स्क्रॉल ऊपर या कार्यक्षेत्र RecycleView के नीचे नीचे की तरह, पा सकते हैं

RecyclerView rv = (RecyclerView)findViewById(R.id.rv);

rv.addOnScrollListener(new RecyclerView.OnScrollListener() {

            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
            }

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {

                if (dy < 0) {
                    // Recycle view scrolling up...

                } else if (dy > 0) {
                    // Recycle view scrolling down...
                }
            }
        });

6

स्क्रॉल के ऊपर या नीचे तक पहुँचने के लिए जाँच करने के लिए recyclerView.canScrollVertically (int दिशा) का उपयोग करें ।

नीचे स्क्रॉल करने के लिए दिशा = 1 (नीचे)

दिशा = -1 ऊपर स्क्रॉल करने के लिए (शीर्ष)

यदि विधि गलत है जिसका अर्थ है कि आप ऊपर या नीचे पहुँच गए हैं तो दिशा पर निर्भर करता है।


बहुत धन्यवाद यह काम किया!
फेर अतुल

5

बस अपने लेआउट मैनेजर का संदर्भ रखें और इस तरह से अपने रिसाइकलर दृश्य पर onScrollListener सेट करें

mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {

    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);

        visibleItemCount = mRecyclerView.getChildCount();
        totalItemCount = mLayoutManager.getItemCount();
        firstVisibleItemIndex = mLayoutManager.findFirstVisibleItemPosition();

        //synchronizew loading state when item count changes
        if (loading) {
            if (totalItemCount > previousTotal) {
                loading = false;
                previousTotal = totalItemCount;
            }
        }
        if (!loading)
            if ((totalItemCount - visibleItemCount) <= firstVisibleItemIndex) {
                // Loading NOT in progress and end of list has been reached
                // also triggered if not enough items to fill the screen
                // if you start loading
                loading = true;
            } else if (firstVisibleItemIndex == 0){
                // top of list reached
                // if you start loading
                loading = true;
            }
        }
    }
});

1
setOnScrollListnerअब पदावनत कर दिया गया है।
शजील अफजल

2
आपको उपयोग करना चाहिए addOnScrollListenerक्योंकि @shajeelAfzal ने कहा कि setOnScrollListenerअब पदावनत कर दिया गया है, addOnScrollListenerइसलिए आपको उपयोग करना चाहिए क्योंकि @shajeelAfzal ने कहा कि setOnScrollListenerअब पदावनत कर दिया गया है, यहाँ देखें
Vasilisfoo

क्या है previousTotal?
कूलमाइंड

3

आप निम्न का उपयोग करके शीर्ष का पता लगा सकते हैं

 recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {

        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
          }

        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);
            if(IsRecyclerViewAtTop())
            {
                //your recycler view reached Top do some thing
             }
        }
    });

  private boolean IsRecyclerViewAtTop()   {
        if(recyclerView.getChildCount() == 0)
            return true;
        return recyclerView.getChildAt(0).getTop() == 0;
    }

जब आप उंगली को एक बार ऊपर पहुंचाते हैं तो यह शीर्ष का पता लगाएगा, यदि आप जल्द से जल्द पता लगाना चाहते हैं कि रीसायकलर्विस शीर्ष जांच विधि के if(IsRecyclerViewAtTop())अंदर कैसे पहुंचता हैonScrolled


3
यह गलत लगता है। getChildAt()के पहले बच्चे को लौटाता है ViewGroup, जो सूची के पहले तत्व से अलग हो सकता है (और होगा)। यदि वह बच्चा पुनरावर्ती के शीर्ष के साथ पूरी तरह से गठबंधन करने के लिए होता है, तो आपका IsRecyclerViewAtTop()तरीका सही वापस आ जाएगा, भले ही यह शीर्ष पर न हो।
aspyct

2

मैंने यह जानने के लिए एक RecyclerViewHelper लिखा है कि recyclerview शीर्ष पर या नीचे है।

public class RecyclerViewHelper {
public static boolean isAtTop(RecyclerView recyclerView) {
    if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
        return isAtTopBeforeIceCream(recyclerView);
    } else {
        return !ViewCompat.canScrollVertically(recyclerView, -1);
    }
}

private static boolean isAtTopBeforeIceCream(RecyclerView recyclerView) {
    RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
    if (layoutManager instanceof LinearLayoutManager) {
        LinearLayoutManager linearLayoutManager = (LinearLayoutManager) layoutManager;
        int pos = linearLayoutManager.findFirstVisibleItemPosition();
        if (linearLayoutManager.findViewByPosition(pos).getTop() == recyclerView.getPaddingTop() && pos == 0)
            return true;
    }
    return false;
}


public static boolean isAtBottom(RecyclerView recyclerView) {
    if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
        return isAtBottomBeforeIceCream(recyclerView);
    } else {
        return !ViewCompat.canScrollVertically(recyclerView, 1);
    }
}

private static boolean isAtBottomBeforeIceCream(RecyclerView recyclerView) {
    RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
    int count = recyclerView.getAdapter().getItemCount();
    if (layoutManager instanceof LinearLayoutManager) {
        LinearLayoutManager linearLayoutManager = (LinearLayoutManager) layoutManager;
        int pos = linearLayoutManager.findLastVisibleItemPosition();
        int lastChildBottom = linearLayoutManager.findViewByPosition(pos).getBottom();
        if (lastChildBottom == recyclerView.getHeight() - recyclerView.getPaddingBottom() && pos == count - 1)
            return true;
    }
    return false;
}

}


2

आप यह कर सकते हैं यह मेरे लिए काम कर रहा है

      mRecycleView.addOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);
            }
        }

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                int topRowVerticalPosition = (recyclerView == null || recyclerView.getChildCount() == 0) ?
                        0 : recyclerView.getChildAt(0).getTop();
                LinearLayoutManager linearLayoutManager1 = (LinearLayoutManager) recyclerView.getLayoutManager();
                int firstVisibleItem = linearLayoutManager1.findFirstVisibleItemPosition();
                swipeRefreshLayout.setEnabled(firstVisibleItem == 0 && topRowVerticalPosition >= 0);
            }
        });

2

यह जानने के लिए कि क्या RecyclerView को नीचे तक स्क्रॉल किया गया है, आप स्क्रॉलबार के लिए उपयोग किए गए तरीकों का पुन: उपयोग कर सकते हैं।

यह एक कोटलिन एक्सटेंशन फ़ंक्शन के रूप में लिखी गई सुविधा के लिए गणना है:

fun RecyclerView.isScrolledToBottom(): Boolean {
    val contentHeight = height - (paddingTop + paddingBottom)
    return computeVerticalScrollRange() == computeVerticalScrollOffset() + contentHeight
}

अच्छा समाधान! मैंने कुछ मुद्दों को देखा जहां स्क्रॉल का आकार केवल 1 था, भले ही मुझे नीचे स्क्रॉल किया गया था (शायद कुछ गोल मुद्दे) इसलिए मैंने एक मार्जिन का उपयोग करने के लिए कोड बदल दिया:fun RecyclerView.isScrolledToBottom(margin: Int = 1): Boolean { val contentHeight = height - (paddingTop + paddingBottom) return computeVerticalScrollRange() - computeVerticalScrollOffset() - contentHeight >= margin }
रेंसो लोहूइस

मेरा मतलब है, मार्जिन के बराबर या छोटा। जैसे:fun RecyclerView.isScrolledToBottom(margin: Int = 1): Boolean { val contentHeight = height - (paddingTop + paddingBottom) return computeVerticalScrollRange() - computeVerticalScrollOffset() - contentHeight <= margin }
रेंसो लोहुइस

1

आप OnTouchListener के साथ कोशिश कर सकते हैं:

recyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
    @Override
    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
        if (e.getAction() == MotionEvent.ACTION_UP
            || e.getAction() == MotionEvent.ACTION_MOVE){
        if (mLinearLayoutManager.findFirstCompletelyVisibleItemPosition() > 0)
        {
        // beginning of the recycler 
        }

        if (mLinearLayoutManager.findLastCompletelyVisibleItemPosition()+1 < recyclerView.getAdapter().getItemCount())
        {
        // end of the recycler 
        }         
     }             
return false;
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.