RecyclerView smoothScroll zur Position in der Mitte. Android
Lesezeit: 4 Minuten
Stan Malcom
Ich verwende einen horizontalen Layout-Manager für meine RecyclerView. Ich muss machen RecyclerView auf die nächste Weise: Wenn Sie auf ein Element klicken, machen Sie smoothScroll zu dieser Position und platzieren Sie dieses Element in der Mitte RecyclerView (möglichst z. B. 10 Stück von 20).
Also ich habe kein Problem damit smoothScrollToPosition()aber wie man Artikel als in der Mitte von setzt RecyclerView???
Vielen Dank!
Benutzer3680200
Ja es ist möglich.
Durch die Umsetzung RecyclerView.SmoothScroller‘s Methode onTargetFound(View, State, Action).
/**
* Called when the target position is laid out. This is the last callback SmoothScroller
* will receive and it should update the provided {@link Action} to define the scroll
* details towards the target view.
* @param targetView The view element which render the target position.
* @param state Transient state of RecyclerView
* @param action Action instance that you should update to define final scroll action
* towards the targetView
*/
abstract protected void onTargetFound(View targetView, State state, Action action);
Konkret im LinearLayoutManager mit LinearSmoothScroller:
public class CenterLayoutManager extends LinearLayoutManager {
public CenterLayoutManager(Context context) {
super(context);
}
public CenterLayoutManager(Context context, int orientation, boolean reverseLayout) {
super(context, orientation, reverseLayout);
}
public CenterLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {
RecyclerView.SmoothScroller smoothScroller = new CenterSmoothScroller(recyclerView.getContext());
smoothScroller.setTargetPosition(position);
startSmoothScroll(smoothScroller);
}
private static class CenterSmoothScroller extends LinearSmoothScroller {
CenterSmoothScroller(Context context) {
super(context);
}
@Override
public int calculateDtToFit(int viewStart, int viewEnd, int boxStart, int boxEnd, int snapPreference) {
return (boxStart + (boxEnd - boxStart) / 2) - (viewStart + (viewEnd - viewStart) / 2);
}
}
}
extends LinearSmoothScroller überschreiben muss computeScrollVectorForPosition()
– Ninja
27. Dezember 2016 um 7:02 Uhr
Hat einwandfrei funktioniert
– Eliseo Ocampos
21. April 2017 um 17:11 Uhr
Perfekt, für andere rufen Sie einfach an recyclerView.smoothScrollToPosition(position); und vergessen Sie nicht, den Layout-Manager einzustellen recyclerView.setLayoutManager(layoutManager);
– Peter
9. Juni 2017 um 15:58 Uhr
Wo ist das onTargetFound() Funktion implementiert?
– Fehler passieren
24. August 2018 um 11:05 Uhr
Aber ich habe nicht genau verstanden, warum Sie diese Methode erwähnt haben onTargetFound() ?
– Sirop4ik
31. Oktober 2018 um 8:55 Uhr
王能
Verbesserungen an der Antwort – Es besteht keine Notwendigkeit, die zu überschreiben LinearLayoutManager
Aus der vorherigen Antwort:
public class CenterSmoothScroller extends LinearSmoothScroller {
public CenterSmoothScroller(Context context) {
super(context);
}
@Override
public int calculateDtToFit(int viewStart, int viewEnd, int boxStart, int boxEnd, int snapPreference) {
return (boxStart + (boxEnd - boxStart) / 2) - (viewStart + (viewEnd - viewStart) / 2);
}
}
Hier, wie man es benutzt:
RecyclerView.LayoutManager lm = new GridLayoutManager(...): // or whatever layout manager you need
...
RecyclerView.SmoothScroller smoothScroller = new CenterSmoothScroller(recyclerView.getContext());
smoothScroller.setTargetPosition(position);
lm.startSmoothScroll(smoothScroller);
Für andere, die so verwirrt sind wie ich, CenterSmoothScroller ist eine Klasse, die in der akzeptierten Antwort gefunden wird.
– RJR-Apps
14. Februar 2019 um 23:20 Uhr
Halleluja! Sie haben einen halben Tag damit verbracht, eine Reihe komplizierter Methoden auszuprobieren, und Ihre Lösung funktioniert perfekt. Vielen Dank!
– mjp66
18. März 2020 um 23:25 Uhr
Wie bekomme ich die Position, während ich die Recycleransicht deklariere? Ich muss das Element in die Mitte bringen, während der Benutzer das Element mit dem D-Pad scrollt. @ user8944115
– Aravind
28. April 2020 um 7:31 Uhr
das funktionierte wie ein Zauber!! Danke, wenn Sie die Klasse nicht finden, müssen Sie vielleicht Ihre Abhängigkeiten aktualisieren, ist unter androidx.recyclerview.widget.LinearSmoothScroller
– Javier
2. Juli 2021 um 9:46 Uhr
Es ist die richtige und einfache Lösung. Vielen Dank
– Trung Đoan
25. Oktober 2021 um 5:30 Uhr
Nur für den Fall, dass jemand die braucht Kotlin-Äquivalent der Klasse in der akzeptierten Antwort.
Basierend auf der Antwort von @Boda können Sie Folgendes verwenden, wenn Sie die reibungslose Bildlaufgeschwindigkeit (für eine bessere Animation) steuern möchten:
class CenterLayoutManager : LinearLayoutManager {
constructor(context: Context) : super(context)
constructor(context: Context, orientation: Int, reverseLayout: Boolean) : super(
context,
orientation,
reverseLayout
)
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(
context,
attrs,
defStyleAttr,
defStyleRes
)
override fun smoothScrollToPosition(
recyclerView: RecyclerView,
state: RecyclerView.State,
position: Int
) {
val centerSmoothScroller = CenterSmoothScroller(recyclerView.context)
centerSmoothScroller.targetPosition = position
startSmoothScroll(centerSmoothScroller)
}
private class CenterSmoothScroller(context: Context) : LinearSmoothScroller(context) {
override fun calculateDtToFit(
viewStart: Int,
viewEnd: Int,
boxStart: Int,
boxEnd: Int,
snapPreference: Int
): Int = (boxStart + (boxEnd - boxStart) / 2) - (viewStart + (viewEnd - viewStart) / 2)
override fun calculateSpeedPerPixel(displayMetrics: DisplayMetrics): Float {
return MILLISECONDS_PER_INCH / displayMetrics.densityDpi
}
}
companion object {
// This number controls the speed of smooth scroll
private const val MILLISECONDS_PER_INCH = 150f
}
}