Обновление Google I / O 2019
ViewPager2 уже здесь!
Google только что объявил на своем выступлении «Что нового в Android» (также известное как «Тема Android»), что они работают над новым ViewPager на основе RecyclerView!
Со слайдов:
Как ViewPager, но лучше
- Легкая миграция из ViewPager
- На основе RecyclerView
- Поддержка режима справа налево
- Разрешает вертикальное перелистывание
- Улучшенные уведомления об изменении набора данных
Вы можете проверить последнюю версию здесь и примечания к выпуску здесь . Также есть официальный образец .
Личное мнение: думаю, это действительно нужное дополнение. У меня недавно было много проблем с PagerSnapHelper
бесконечно колеблющимся левым и правым движением - посмотрите билет, который я открыл.
Новый ответ (2016)
Теперь вы можете просто использовать SnapHelper .
Если вы хотите, чтобы поведение привязки по центру было похоже на ViewPager, используйте PagerSnapHelper :
SnapHelper snapHelper = new PagerSnapHelper();
snapHelper.attachToRecyclerView(recyclerView);
Также существует LinearSnapHelper . Я пробовал, и если вы бросаете с энергией, то он прокручивает 2 элемента за 1 бросок. Лично мне это не понравилось, но решайте сами - проба занимает секунды.
Оригинальный ответ (2016)
После многих часов пробных 3 различных решений, найденных здесь, в SO, я наконец создал решение, которое очень точно имитирует поведение, обнаруженное в файле ViewPager
.
Решение основано на решении @eDizzle , которое, как мне кажется, я улучшил достаточно, чтобы сказать, что оно работает почти как ViewPager
.
Важно: RecyclerView
ширина моих предметов точно такая же, как у экрана. С другими размерами не пробовал. Также использую с горизонталью LinearLayoutManager
. Я думаю, что вам нужно будет адаптировать код, если вы хотите вертикальную прокрутку.
Вот код:
public class SnappyRecyclerView extends RecyclerView {
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;
int lastVisibleItemPosition = linearLayoutManager.findLastVisibleItemPosition();
View lastView = linearLayoutManager.findViewByPosition(lastVisibleItemPosition);
int firstVisibleItemPosition = linearLayoutManager.findFirstVisibleItemPosition();
View firstView = linearLayoutManager.findViewByPosition(firstVisibleItemPosition);
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) {
if (leftEdge > screenWidth / 2) {
smoothScrollBy(-scrollDistanceRight, 0);
} else if (rightEdge < screenWidth / 2) {
smoothScrollBy(scrollDistanceLeft, 0);
} else {
if (velocityX > 0) {
smoothScrollBy(-scrollDistanceRight, 0);
} else {
smoothScrollBy(scrollDistanceLeft, 0);
}
}
return true;
} else {
if (velocityX > 0) {
smoothScrollBy(scrollDistanceLeft, 0);
} else {
smoothScrollBy(-scrollDistanceRight, 0);
}
return true;
}
}
@Override
public void onScrollStateChanged(int state) {
super.onScrollStateChanged(state);
if (state == SCROLL_STATE_IDLE) {
LinearLayoutManager linearLayoutManager = (LinearLayoutManager) getLayoutManager();
int screenWidth = Resources.getSystem().getDisplayMetrics().widthPixels;
int lastVisibleItemPosition = linearLayoutManager.findLastVisibleItemPosition();
View lastView = linearLayoutManager.findViewByPosition(lastVisibleItemPosition);
int firstVisibleItemPosition = linearLayoutManager.findFirstVisibleItemPosition();
View firstView = linearLayoutManager.findViewByPosition(firstVisibleItemPosition);
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);
}
}
}
}
Наслаждайтесь!