(Smooth)ScrollToPosition werkt niet goed met RecyclerView

Ik gebruik standaard RecyclerView met GridLayoutManager. Ik merkte op dat noch smoothScrollToPosition noch scrollToPosition correct werkt.

a) bij gebruik van smoothScrollToPositionkrijg ik vaak een foutmelding van RecyclerView

“RecyclerView﹕ Gepasseerd over doelpositie tijdens soepel scrollen.”

en RecyclerViewwordt niet goed gescrolld (vaak mist het de beoogde rij). Dit wordt meestal waargenomen wanneer ik naar het eerste item van een rij probeer te scrollen

b) bij gebruik van scrollToPositionlijkt het redelijk goed te werken, maar meestal kan ik alleen het eerste item van de rij zien en de rest wordt niet weergegeven.

Kun je me wat hints geven hoe ik tenminste één van de methoden goed kan laten werken?

Hartelijk dank!


Antwoord 1, autoriteit 100%

Eindelijk lukte het me om het te laten werken! LinearLayoutManager.scrollToPositionWithOffset(int, int)deed het.


Antwoord 2, autoriteit 23%

Ik heb hetzelfde probleem, maar heb het probleem kunnen oplossen door SmoothScroller aan te passen

laat Custom LayoutManager zoals hieronder

public class CustomLayoutManager extends LinearLayoutManager {
    private static final float MILLISECONDS_PER_INCH = 50f;
    private Context mContext;
    public CustomLayoutManager(Context context) {
        super(context);
        mContext = context;
    }
    @Override
    public void smoothScrollToPosition(RecyclerView recyclerView,
        RecyclerView.State state, final int position) {
        LinearSmoothScroller smoothScroller = 
            new LinearSmoothScroller(mContext) {
            //This controls the direction in which smoothScroll looks
            //for your view
            @Override
            public PointF computeScrollVectorForPosition
            (int targetPosition) {
                return CustomLayoutManager.this
                    .computeScrollVectorForPosition(targetPosition);
            }
            //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);
    }
}

(documentatie becommentarieerd in de bovenstaande code)Stel de bovenstaande LayoutManager in
naar de recyerview

CustomLayoutManagerlayoutManager = new CustomLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
recyclerView.smoothScrollToPosition(position);

met behulp van de aangepaste lay-outmanager

scrollToPosition
werkt ook goed in mijn geval die je kunt gebruiken

recyclerView.scrollToPosition(position)

ook als je de snelheid van smoothScrollToPosition wilt aanpassen, overschrijf dan de

private static final float MILLISECONDS_PER_INCH = 50f;

in CustomLayoutManager.
Dus als we de waarde als 1fplaatsen, zal smoothScrollToPosition sneller zijn, zoals scrollToPosition. toenemende waarde maakt vertraging en afnemende maakt de snelheid van scrollen.
Ik hoop dat dit nuttig zal zijn.


Antwoord 3, autoriteit 17%

In mijn geval,

mRecyclerView.scrollToPosition(10);

werkte ook niet.
Maar

mRecyclerView.smoothScrollToPosition(10);

werkt prima voor mij…


Antwoord 4, autoriteit 10%

Om soepel naar beneden te scrollen vanuit elke positie in de RecyclerView door op EditText te klikken.

edittext.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                rv_commentList.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                      rv_commentList.scrollToPosition(rv_commentList.getAdapter().getItemCount() - 1);
                    }
                }, 1000);
            }
        });

Antwoord 5, autoriteit 9%

Een andere reden waarom een ​​van de bovengenoemde oplossingen mogelijk niet werkt, is als uw RecyclerView is ingesloten in een NestedScrollView. In dit geval moet je de scroll-actie op de NestedScrollView aanroepen.

bijvoorbeeld:

nestedScrollview.smoothScrollTo(0,0)

Antwoord 6, autoriteit 4%

recyclerView.getLayoutManager().smoothScrollToPosition(recyclerView,new RecyclerView.State(),currentPosition);

Antwoord 7

Probeer de breedte of hoogte van het item te meten en roep smoothScrollBy(int dx, int dy) aan.


Antwoord 8

Vloeiend scrollen uitvoeren en de verticale positie van RecyclerViewopslaan nadat het apparaat is gedraaid:
Dit is de methode die voor mijn geval werkt,

public class MainFragment extends Fragment { //OR activity it's //fragment in my case
    ....
 @Override
    public void onLoadFinished(@NonNull Loader<List<Report>> loader, List<Report> objects) { // or other method of your choice, in my case it's a Loader 
    RecyclerView recyclerViewRv = findViewById(........;
         .....
    recyclerViewRv.setAdapter(.....Your adapter);
            recyclerViewRv.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);
                    recyclerScrollY = recyclerViewRv. computeVerticalScrollOffset();
                }
            });
    //Apply smooth vertical scroll
    recyclerViewRv.smoothScrollBy(0,recyclerScrollY);
}
    //Save vertical scroll position before rotating devices
    @Override
        public void onSaveInstanceState(@NonNull Bundle outState) {
            super.onSaveInstanceState(outState);
            outState.putInt("recyclerScrollY",recyclerScrollY);
        }
    //BackUp vertical scroll position after rotating devices 
    @Override
        public void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            if(savedInstanceState != null) {
                recyclerScrollY = savedInstanceState.getInt("recyclerScrollY");
            }
        }
//If you want to perform the same operation for horizontal scrolling just add a variable called recyclerScrollX = recyclerScrollY = recyclerViewRv. computeHorizontalScrollOffset(); then save in bundle

Antwoord 9

Ik had een raar probleem waarbij smoothScrollToPositionslechts af en toe werkte.

Na het plaatsen van de smoothScrollToPositionin de Handler Post
Vertraagd
met 1 seconde vertraging, het werkte prima.

Raadpleeg het volgende Kotlin-voorbeeld:

Handler().postDelayed({
   recyclerViewObject.smoothScrollToPosition(0) // mention the position in place of 0
}, 1000) // 1000 indicates the 1 second delay.

Antwoord 10

Deze extensie is zo handig, probeer het alstublieft.

fun RecyclerView.smoothSnapToPosition(position: Int, snapMode: Int = LinearSmoothScroller.SNAP_TO_START) {
        val smoothScroller = object : LinearSmoothScroller(this.context) {
            override fun getVerticalSnapPreference(): Int = snapMode
            override fun getHorizontalSnapPreference(): Int = snapMode
        }
        smoothScroller.targetPosition = position
        layoutManager?.startSmoothScroll(smoothScroller)
    }

Antwoord 11

Het aanroepen van de recyclerView smoothScroll is niet effectief, omdat de recyclerView zelf de lay-out niet aankan.

Wat u moet doen, is in plaats daarvan de scroll-methode van de lay-outmanager aanroepen.

Dit zou er ongeveer zo uit moeten zien

mRecyclerView.getLayoutManager().scrollToPosition(desiredPosition);

Antwoord 12

Als je snel naar een positie bovenaan de RecyclerView wilt scrollen, gebruik dan gewoon LinearLayoutManager.scrollToPositionWithOffset met 0 als offset.

Voorbeeld:

mLinearLayoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(mLinearLayoutManager);
mLinearLayoutManager.scrollToPositionWithOffset(myPosition, 0);

smoothScrollToPosition is erg traag. Als je iets snel wilt, ga dan met scrollToPositionWithOffset.


Antwoord 13

wanneer u scrollToPositiongebruikt, wordt dit bovenaan de weergave van de recycler weergegeven.

Maar als je smoothScrollToPositiongebruikt, zal het scrollen totdat het in Window Visible komt. dat is de reden waarom, terwijl smoothScrool naar het item hieronder, het onderaan wordt weergegeven


Antwoord 14

Als je een RecyclerView in een NestedScrollView hebt, moet je beide regels gebruiken elke keer dat je naar het begin van de RecyclerView wilt gaan:

nestedScrollView.smoothScrollTo(0, 0);
layoutManager.scrollToPositionWithOffset(0, 0);

Dit werkt helemaal voor mij.


Antwoord 15

dit werkte voor mij

   Handler().postDelayed({
                    (recyclerView.getLayoutManager() as LinearLayoutManager).scrollToPositionWithOffset( 0, 0)
}, 100)

Antwoord 16

Dus ik was op zoek naar een oplossing om terug te keren naar de top met een recyclerview in een andere lay-out die er bovenop heeft (in mijn geval had ik een LinearLayout met een TextView en mijn recyclerview erin). Hierdoor zou de smoothscroll maar tot halverwege het eerste item gaan.

Dit is wat ik deed wat heel goed werkt (Kotlin-oplossing):

back_to_top.setOnClickListener {
        GlobalScope.launch(Dispatchers.Main) {
            GlobalScope.launch(Dispatchers.Main) {
                recyclerview.layoutManager?.smoothScrollToPosition(recyclerview, RecyclerView.State(), 0)
                delay((recyclerview.layoutManager as LinearLayoutManager).findLastVisibleItemPosition() * 100L)
            }.join()
            recyclerview.scrollToPosition(0)
        }
        back_to_top.visibility = View.GONE
    }
}

Wat ik doe, is dat ik vloeiend naar het eerste element scrol en het scrollen met 100 ms keer het laatste zichtbare item uitstel en vervolgens de scrollToPosition(0) aanroep (die naar de top.correctly gaat)


Antwoord 17

Geen van deze antwoorden werkte voor mij. Ik moest smoothScrollToPositionmaar @Ramz antwoord werkte niet. Ik merkte dat het constant zou overscrollen, maar slechts in één richting. Ik ontdekte dat het leek alsof de item-decorateurs het eraf gooiden. Ik had een horizontale lay-out en ik wilde na elk item een ​​spatie toevoegen, behalve het laatste en die asymmetrie hield niet van. Zodra ik achter elk item een ​​spatie plaatste, werkte het!

Other episodes