शीर्ष पर चयनित आइटम दिखाने के लिए RecyclerView स्क्रॉल करें


216

मैं RecyclerViewशीर्ष पर चयनित आइटम दिखाने के लिए स्क्रॉल करने का एक तरीका ढूंढ रहा हूं ।

ListViewमैं एक का उपयोग करके ऐसा करने में सक्षम थाscrollTo(x,y) उस तत्व के शीर्ष का और प्राप्त जिसे केंद्रित करने की आवश्यकता है।

कुछ इस तरह:

@Override
public void onItemClick(View v, int pos){
    mylistView.scrollTo(0, v.getTop());
}

समस्या यह है कि RecyclerViewयह scrollToकह रही विधि का उपयोग करते समय एक त्रुटि देता है

RecyclerView एक पूर्ण स्थिति में स्क्रॉलिंग का समर्थन नहीं करता है

मैं RecyclerViewचयनित आइटम को दृश्य के शीर्ष पर रखने के लिए स्क्रॉल कैसे कर सकता हूं ?

जवाबों:


406

आप उपयोग कर रहे हैं LinearLayoutManagerया कंपित GridLayoutManager, लेकिन उन दोनों है scrollToPositionWithOffset विधि है कि दोनों की स्थिति और भी की शुरुआत से आइटम की शुरुआत की भरपाई लेता RecyclerViewहै, जो यह की तरह लगता है हासिल करेगी आपको क्या चाहिए (स्थापित करने के लिए 0 ऑफसेट शीर्ष के साथ संरेखित करना चाहिए)।

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

//Scroll item 2 to 20 pixels from the top
linearLayoutManager.scrollToPositionWithOffset(2, 20);

34
अगर किसी को RecyclerView की स्क्रॉल स्थिति को पुनर्स्थापित करने के लिए इसकी आवश्यकता है, तो यह है कि स्क्रॉल पदों को कैसे बचाया जाए (विधि स्क्रॉल के लिए दो तर्क स्क्रॉल टाइप करें): int index = linearLayoutManager.findVirstVoiceItemPosition (); देखें v = linearLayoutManager.getChildAt (0); int top = (v == null)? 0: (v.getTop () - linearLayoutManager.getPaddingTop ());
डोमिनिक

के बारे में यह है क्या मैं पाने के लिए नहीं लग रहे जब scrollToPosition कॉल करने के लिए? यदि चयन श्रोता अलग-अलग विचारों पर है, तो RecyclerView ऑब्जेक्ट (जिसके लेआउट प्रबंधक को scrolToPosition कह सकते हैं) तक पहुंच कैसे हो सकती है।
नॉनोस

@ पहले आप पहले उस लेआउट मैन को स्टोर कर सकते हैं जिसे आप RecylerView.setLayoutManager () में उपयोग करते हैं और फिर इसे सीधे एक्सेस करते हैं। इस तरह: LinearLayoutManager llm = new LinearLayoutManager (यह); mRecyclerView.setLayoutManager (एलएलएम); ... (बाद में कोड में) ... llm.scrollToPositionWithOffset (2, 20);
नीरज

19
क्या होगा अगर मैं शीर्ष पर "सुचारू रूप से" स्क्रॉल करना चाहता हूं?
टियागो

@Tiago, मैंने इसके साथ नहीं खेला है, लेकिन लेखों की यह 3-भाग श्रृंखला मदद कर सकती है: blog.stylingandroid.com/scrolling-recyclerview-part-1
Niraj

93

यदि आप लंबवत रैखिक प्रबंधक की तलाश में हैं, तो आप कस्टम का उपयोग करके चिकनी स्क्रॉलिंग प्राप्त कर सकते हैं LinearSmoothScroller:

import android.content.Context;
import android.graphics.PointF;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.LinearSmoothScroller;
import android.support.v7.widget.RecyclerView;

public class SnappingLinearLayoutManager extends LinearLayoutManager {

    public SnappingLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
        super(context, orientation, reverseLayout);
    }

    @Override
    public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state,
                                       int position) {
        RecyclerView.SmoothScroller smoothScroller = new TopSnappedSmoothScroller(recyclerView.getContext());
        smoothScroller.setTargetPosition(position);
        startSmoothScroll(smoothScroller);
    }

    private class TopSnappedSmoothScroller extends LinearSmoothScroller {
        public TopSnappedSmoothScroller(Context context) {
            super(context);

        }

        @Override
        public PointF computeScrollVectorForPosition(int targetPosition) {
            return SnappingLinearLayoutManager.this
                    .computeScrollVectorForPosition(targetPosition);
        }

        @Override
        protected int getVerticalSnapPreference() {
            return SNAP_TO_START;
        }
    }
}

रीसायकल दृश्य में लेआउटमैन के एक उदाहरण का उपयोग करें और फिर कॉल करने recyclerView.smoothScrollToPosition(pos);से रीसायकल दृश्य के शीर्ष पर चयनित स्थिति तक स्क्रॉल होगा


1
वास्तव में उपयोगी जवाब! मैं getHorizontalSnapPreference()क्षैतिज सूचियों के लिए TopSnappedSmoothScroller में भी ओवरराइड करता हूं।
जुआन सराविया

6
क्या मैं यह देखने में सही हूं कि यह केवल उन वस्तुओं के लिए काम करता है जो अभी भी शेष को भरने के लिए उनके नीचे / नीचे पर्याप्त हैं RecyclerView? - की परवाह किए बिना यह पिछले आइटम के लिए काम करने के लिए प्रतीत नहीं होता: जो कहने के लिए है केवल स्क्रॉल जब तक आइटम तल पर दिखाई देने लगता है, लेकिन यह सभी तरह से ले जाने के ऊपर नहीं है। कैसे प्राप्त करने के लिए कोई विचार? (मैंने इसके चारों ओर कस्टम पैडिंग सेट करके काम किया है, लेकिन यह वास्तव में सही नहीं लगता ...)SNAP_TO_STARTRecyclerViewRecyclerView
david.mihola


कुछ समय बाद आइटम को केंद्रित किया जाता है, मैं आइटम दृश्य के लिए ध्यान आकर्षित करने योग्य हूं।
YLS

1
@ david.mihola क्या आपने 'सही' तरीका खोजा है? मैं अपने recyclerview के लिए कस्टम पैडिंग सेट कर रहा हूँ, लेकिन मुझे कुछ अजीब समस्याएं हो रही हैं ...
bernardo.g

52

// स्क्रॉल आइटम स्थिति

linearLayoutManager.scrollToPositionWithOffset(pos, 0);

7
क्या इसे सुचारू रूप से करने का कोई तरीका है?
अश्कां


1
@MarkBuikema मैंने इसे पहले पाया। आपके ध्यान के लिए
धन्यवाद

28

आपको बस कॉल करने की आवश्यकता है recyclerview.scrollToPosition(position) । कोई बात नहीं!

यदि आप इसे एडॉप्टर में कॉल करना चाहते हैं, तो बस अपने एडेप्टर में रिसाइक्लेव्यू का उदाहरण है या एक्टिविटी या फ्रैगमेंट जिसमें रिसाइक्लेव्यू शामिल है, विधि की तुलना में getRecyclerview() उनमें है।

उम्मीद है यह आपकी मदद कर सकता है।


2
यह मेरे लिए काम किया - recyclerView.scrollToPosition (0); मुझे सबसे ऊपर रखो।
रे हंटर

2
काम नहीं करने के लिए आपको linearLayoutManager.scrollToPositionWithOffset (स्थिति, 0) का उपयोग करना होगा;
अनिल उगले

@ अनिल उगले यह बकवास है। बेशक यह काम करता है। आप किसी RecyclerView के लिए किसी भी LayoutManager का उपयोग कर सकते हैं। जब आप स्क्रॉल करना चाहते हैं तो आपको बाद में इसकी परवाह क्यों करनी चाहिए? मुझे लगता है कि आप कुछ गलत कर रहे थे। Recyclerview.scrollToPosition (स्थिति) एक सुविधा विधि है जो LayoutManager.scrollToPosition (स्थिति) को कॉल करती है।
अविश्वसनीय जन

1
@ TheincredibleJan यह सभी मामलों में काम नहीं करता है, लेआउट मैनजर आमतौर पर आपकी जानकारी के लिए किसी भी तरह स्क्रॉल करने के लिए जिम्मेदार है।
मोहम्मद

11

गति नियामक के साथ भी ऐसा ही है

public class SmoothScrollLinearLayoutManager extends LinearLayoutManager {
private static final float MILLISECONDS_PER_INCH = 110f;
private Context mContext;

public SmoothScrollLinearLayoutManager(Context context,int orientation, boolean reverseLayout) {
    super(context,orientation,reverseLayout);
    mContext = context;
}

@Override
public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state,
                                   int position) {
    RecyclerView.SmoothScroller smoothScroller = new TopSnappedSmoothScroller(recyclerView.getContext()){
        //This controls the direction in which smoothScroll looks for your view
        @Override
        public PointF computeScrollVectorForPosition(int targetPosition) {
            return new PointF(0, 1);
        }

        //This returns the milliseconds it takes to scroll one pixel.
        @Override
        protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
            return MILLISECONDS_PER_INCH / displayMetrics.densityDpi;
        }
    };
    smoothScroller.setTargetPosition(position);
    startSmoothScroll(smoothScroller);
}


private class TopSnappedSmoothScroller extends LinearSmoothScroller {
    public TopSnappedSmoothScroller(Context context) {
        super(context);

    }

    @Override
    public PointF computeScrollVectorForPosition(int targetPosition) {
        return SmoothScrollLinearLayoutManager.this
                .computeScrollVectorForPosition(targetPosition);
    }

    @Override
    protected int getVerticalSnapPreference() {
        return SNAP_TO_START;
    }
}
}

8

कोशिश करो कि मेरे लिए क्या अच्छा काम किया!

एक चर बनाएं private static int displayedposition = 0;

अब अपनी गतिविधि में अपने RecyclerView की स्थिति के लिए।

myRecyclerView.setOnScrollListener(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);

                LinearLayoutManager llm = (LinearLayoutManager) myRecyclerView.getLayoutManager();


                displayedposition = llm.findFirstVisibleItemPosition();


            }
        });

इस कथन को उस स्थान पर रखें जहाँ आप चाहते हैं कि यह आपके दृश्य में प्रदर्शित पूर्व साइट को जगह दे।

LinearLayoutManager llm = (LinearLayoutManager) mRecyclerView.getLayoutManager();
        llm.scrollToPositionWithOffset(displayedposition , youList.size());

खैर यह बात है, यह मेरे लिए ठीक है / ओ /


7

बस इस विधि को बस कॉल करें:

((LinearLayoutManager)recyclerView.getLayoutManager()).scrollToPositionWithOffset(yourItemPosition,0);

के बजाय:

recyclerView.scrollToPosition(yourItemPosition);

"के बजाय"? डिस्टवो ने "स्क्रोलटपोजिशन" का उल्लेख नहीं किया। अगर उसने इसका इस्तेमाल किया होता तो कोई समस्या नहीं होती। स्क्रॉलटाप्पोज () जैसा कि इरादा है।
अविश्वसनीय जन

1
मेरे लिए और recyclerview.scrollToPosition didn के लिए स्क्रॉलटॉपपोजिटथऑफसेट काम करता है, काफी अजीब। हालाँकि, मैं अमीर से अनुरोध करूँगा कि वे RecyclerView को रिसाइक्लेरव्यू में बदल दें, क्योंकि इससे यह समझ में आता है कि तरीके स्थिर हैं, और वे नहीं हैं।
मोहित

6

बटन पर RecyclerView को ताज़ा करने के बाद मैंने स्क्रॉल स्थिति को पुनर्स्थापित करने के लिए क्या किया:

if (linearLayoutManager != null) {

    index = linearLayoutManager.findFirstVisibleItemPosition();
    View v = linearLayoutManager.getChildAt(0);
    top = (v == null) ? 0 : (v.getTop() - linearLayoutManager.getPaddingTop());
    Log.d("TAG", "visible position " + " " + index);
}

else{
    index = 0;
}

linearLayoutManager = new LinearLayoutManager(getApplicationContext());
linearLayoutManager.scrollToPositionWithOffset(index, top);

लीनियर लाईटमैनेजर ऑब्जेक्ट बनाने से पहले ऊपर से पहली दिखाई देने वाली वस्तु की भरपाई करना और उसके तुरंत बाद इसे स्क्रॉल करना।


6

मुझे नहीं पता कि मुझे सबसे अच्छा जवाब क्यों नहीं मिला लेकिन यह वास्तव में सरल है।

recyclerView.smoothScrollToPosition(position);

त्रुटियाँ नहीं

एनिमेशन बनाता है


आप इसे गतिविधि या एडॉप्टर में कहां लगाएंगे?
अर्नोल्ड ब्राउन

3

विशेष स्थिति में स्क्रॉल करें
और इससे मुझे बहुत मदद मिली। क्लिक श्रोता द्वारा आप अपने एडॉप्टर में स्थिति प्राप्त कर सकते हैं

layoutmanager.scrollToPosition(int position);

3
If you want to scroll automatic without show scroll motion then you need to write following code:

**=> mRecyclerView.getLayoutManager().scrollToPosition(position);**

If you want to display scroll motion then you need to add following code.
=>Step 1: You need to declare SmoothScroller.

RecyclerView.SmoothScroller smoothScroller = new
                LinearSmoothScroller(this.getApplicationContext()) {
                    @Override
                    protected int getVerticalSnapPreference() {
                        return LinearSmoothScroller.SNAP_TO_START;
                    }
                };

=>step 2: You need to add this code any event you want to perform scroll to specific position.
=>First you need to set target position to SmoothScroller.

**smoothScroller.setTargetPosition(position);**

=>Then you need to set SmoothScroller to LayoutManager.
                        **mRecyclerView.getLayoutManager().startSmoothScroll(smoothScroller);**

3

कोई भी उत्तर स्पष्ट नहीं करता है कि अंतिम आइटम को शीर्ष पर कैसे दिखाया जाए। तो, उत्तर केवल उन वस्तुओं के लिए काम करते हैं जिनमें अभी भी शेष से भरने के लिए उनके ऊपर या नीचे पर्याप्त आइटम हैं RecyclerView। उदाहरण के लिए, यदि 59 तत्व हैं और 56-वें तत्व का चयन किया गया है, तो यह शीर्ष पर होना चाहिए जैसा कि नीचे दी गई तस्वीर में है:

RecyclerView - तत्व 56 चुना गया है हम का उपयोग करके उन मामलों को संभाल सकता linearLayoutManager.scrollToPositionWithOffset(pos, 0)में और एक अतिरिक्त तर्क Adapterकी RecyclerView(यदि अंतिम आइटम नहीं है दिखाई तो इसका मतलब है वहाँ पर्याप्त जगह को भरने अंतिम आइटम नीचे एक कस्टम मार्जिन जोड़कर - RecyclerView)। कस्टम मार्जिन रूट दृश्य ऊंचाई और आइटम ऊंचाई के बीच अंतर हो सकता है। तो, आपके Adapterलिए RecyclerViewनिम्नानुसार दिखेगा:

...
@Override
public void onBindViewHolder(ViewHolder holder, final int position) {
    ...

    int bottomHeight = 0;
    int itemHeight = holder.itemView.getMeasuredHeight();
    // if it's the last item then add a bottom margin that is enough to bring it to the top
    if (position == mDataSet.length - 1) {
        bottomHeight = Math.max(0, mRootView.getMeasuredHeight() - itemHeight);
    }
    RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)holder.itemView.getLayoutParams();
    params.setMargins(0, 0, params.rightMargin, bottomHeight);
    holder.itemView.setLayoutParams(params);

    ...
} 
...

2

मेरे मामले में मेरे RecyclerViewपास एक पैडिंग टॉप है

<android.support.v7.widget.RecyclerView
     ...
     android:paddingTop="100dp"
     android:clipToPadding="false"
/>

फिर किसी आइटम को शीर्ष पर स्क्रॉल करने के लिए, मुझे करने की आवश्यकता है

recyclerViewLinearLayoutManager.scrollToPositionWithOffset(position, -yourRecyclerView.getPaddingTop());

1

यदि आपका LayoutManagerहै LinearLayoutManagerआप का उपयोग scrollToPositionWithOffset(position,0);इस पर और यह सूची में अपने आइटम पहला दृश्य आइटम कर देगा। अन्यथा, आप उपयोग कर सकते हैं smoothScrollToPositionपर RecyclerViewसीधे।

मैंने नीचे दिए गए कोड का उपयोग करके समाप्त किया।

 RecyclerView.LayoutManager layoutManager = mainList.getLayoutManager();
        if (layoutManager instanceof LinearLayoutManager) {
            // Scroll to item and make it the first visible item of the list.
            ((LinearLayoutManager) layoutManager).scrollToPositionWithOffset(position, 0);
        } else {
            mainList.smoothScrollToPosition(position);
        }

-2

मैं नीचे दिए गए कोड का उपयोग करके किसी आइटम (यह दृश्य) को ऊपर-नीचे कर सकता हूं।
यह अलग-अलग ऊंचाइयों के विचारों के साथ GridLayoutManager के लिए भी काम करता है:

View firstView = mRecyclerView.getChildAt(0);
int toY = firstView.getTop();
int firstPosition = mRecyclerView.getChildAdapterPosition(firstView);
View thisView = mRecyclerView.getChildAt(thisPosition - firstPosition);
int fromY = thisView.getTop();

mRecyclerView.smoothScrollBy(0, fromY - toY);

एक त्वरित समाधान के लिए काफी अच्छा काम करता है।


1
का मूल्य क्या है thisPosition?
pRaNaY

यह वह स्थिति है जिसे आप स्क्रॉल करना चाहते हैं
Jan Rabe

बस किसी भी गणना के बिना smoothScrollToPosition (int स्थिति) का उपयोग क्यों नहीं करें? इससे कोई फर्क नहीं पड़ता कि आप कहाँ से शुरू करते हैं?
अविश्वसनीय जन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.