Оновлення 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);
}
}
}
}
Насолоджуйтесь!