Google I / O 2019 Update
ViewPager2 ist da!
Google hat gerade beim Vortrag "Was ist neu in Android" (auch bekannt als "The Android Keynote") angekündigt , dass sie an einem neuen ViewPager arbeiten, der auf RecyclerView basiert!
Von den Folien:
Wie ViewPager, aber besser
- Einfache Migration von ViewPager
- Basierend auf RecyclerView
- Unterstützung des Rechts-Links-Modus
- Ermöglicht vertikales Paging
- Verbesserte Benachrichtigungen über Datensatzänderungen
Sie können die neueste Version überprüfen hier und die Release Notes hier . Es gibt auch eine offizielle Probe .
Persönliche Meinung: Ich denke, dies ist eine wirklich notwendige Ergänzung. Ich hatte in letzter Zeit große Probleme mit dem PagerSnapHelper
oszillierenden Links-Rechts auf unbestimmte Zeit - siehe das Ticket, das ich geöffnet habe.
Neue Antwort (2016)
Sie können jetzt einfach einen SnapHelper verwenden .
Wenn Sie ein zentriertes Ausrichtungsverhalten ähnlich ViewPager wünschen, verwenden Sie PagerSnapHelper :
SnapHelper snapHelper = new PagerSnapHelper();
snapHelper.attachToRecyclerView(recyclerView);
Es gibt auch einen LinearSnapHelper . Ich habe es versucht und wenn du mit Energie fliegst, rollt es 2 Gegenstände mit 1 Schleuder. Persönlich hat es mir nicht gefallen, aber ich entscheide einfach selbst - es dauert nur Sekunden.
Ursprüngliche Antwort (2016)
Nachdem ich viele Stunden lang 3 verschiedene Lösungen ausprobiert habe, die hier in SO gefunden wurden, habe ich endlich eine Lösung entwickelt, die das Verhalten in a sehr genau nachahmt ViewPager
.
Die Lösung basiert auf der @ eDizzle- Lösung , die ich meiner Meinung nach so weit verbessert habe, dass sie fast wie eine funktioniert ViewPager
.
Wichtig: Die RecyclerView
Breite meiner Artikel entspricht genau der des Bildschirms. Ich habe es nicht mit anderen Größen versucht. Auch ich benutze es mit einer Horizontalen LinearLayoutManager
. Ich denke, dass Sie den Code anpassen müssen, wenn Sie einen vertikalen Bildlauf wünschen.
Hier haben Sie den Code:
public class SnappyRecyclerView extends RecyclerView {
// Use it with a horizontal LinearLayoutManager
// Based on https://stackoverflow.com/a/29171652/4034572
public SnappyRecyclerView(Context context) {
super(context);
}
public SnappyRecyclerView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public SnappyRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public boolean fling(int velocityX, int velocityY) {
LinearLayoutManager linearLayoutManager = (LinearLayoutManager) getLayoutManager();
int screenWidth = Resources.getSystem().getDisplayMetrics().widthPixels;
// views on the screen
int lastVisibleItemPosition = linearLayoutManager.findLastVisibleItemPosition();
View lastView = linearLayoutManager.findViewByPosition(lastVisibleItemPosition);
int firstVisibleItemPosition = linearLayoutManager.findFirstVisibleItemPosition();
View firstView = linearLayoutManager.findViewByPosition(firstVisibleItemPosition);
// distance we need to scroll
int leftMargin = (screenWidth - lastView.getWidth()) / 2;
int rightMargin = (screenWidth - firstView.getWidth()) / 2 + firstView.getWidth();
int leftEdge = lastView.getLeft();
int rightEdge = firstView.getRight();
int scrollDistanceLeft = leftEdge - leftMargin;
int scrollDistanceRight = rightMargin - rightEdge;
if (Math.abs(velocityX) < 1000) {
// The fling is slow -> stay at the current page if we are less than half through,
// or go to the next page if more than half through
if (leftEdge > screenWidth / 2) {
// go to next page
smoothScrollBy(-scrollDistanceRight, 0);
} else if (rightEdge < screenWidth / 2) {
// go to next page
smoothScrollBy(scrollDistanceLeft, 0);
} else {
// stay at current page
if (velocityX > 0) {
smoothScrollBy(-scrollDistanceRight, 0);
} else {
smoothScrollBy(scrollDistanceLeft, 0);
}
}
return true;
} else {
// The fling is fast -> go to next page
if (velocityX > 0) {
smoothScrollBy(scrollDistanceLeft, 0);
} else {
smoothScrollBy(-scrollDistanceRight, 0);
}
return true;
}
}
@Override
public void onScrollStateChanged(int state) {
super.onScrollStateChanged(state);
// If you tap on the phone while the RecyclerView is scrolling it will stop in the middle.
// This code fixes this. This code is not strictly necessary but it improves the behaviour.
if (state == SCROLL_STATE_IDLE) {
LinearLayoutManager linearLayoutManager = (LinearLayoutManager) getLayoutManager();
int screenWidth = Resources.getSystem().getDisplayMetrics().widthPixels;
// views on the screen
int lastVisibleItemPosition = linearLayoutManager.findLastVisibleItemPosition();
View lastView = linearLayoutManager.findViewByPosition(lastVisibleItemPosition);
int firstVisibleItemPosition = linearLayoutManager.findFirstVisibleItemPosition();
View firstView = linearLayoutManager.findViewByPosition(firstVisibleItemPosition);
// distance we need to scroll
int leftMargin = (screenWidth - lastView.getWidth()) / 2;
int rightMargin = (screenWidth - firstView.getWidth()) / 2 + firstView.getWidth();
int leftEdge = lastView.getLeft();
int rightEdge = firstView.getRight();
int scrollDistanceLeft = leftEdge - leftMargin;
int scrollDistanceRight = rightMargin - rightEdge;
if (leftEdge > screenWidth / 2) {
smoothScrollBy(-scrollDistanceRight, 0);
} else if (rightEdge < screenWidth / 2) {
smoothScrollBy(scrollDistanceLeft, 0);
}
}
}
}
Genießen!