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 RecyclerViewBreite 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!