Хорошо, после некоторого исследования я пришел к выводу о замене моего ViewPager2
на recyclerView
, который будет «вести себя как» viewPager: /.
Сначала я заменил свой viewPager2
с горизонтальным recyclerView
. Чтобы заставить его вести себя как видовой пейджер, используйте SnapHelper
.
RecyclerView childRecyclerView2 = findVIewById(R.id.previously_viewPager);
// other init like setup layout manager, adapter etc
SnapHelper snapHelper = new PagerSnapHelper();
snapHelper.attachToRecyclerView(replacedRecyclerView); // <-- this makes out rv behave like a viewPager
. После этого вам нужно добавить OnItemTouchListener
и переопределить onInterceptTouchEvent
так же, как сегмент кода в моем вопросе:
childRecyclerView2.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
@Override
public boolean onInterceptTouchEvent(@NonNull RecyclerView rv, @NonNull MotionEvent e) {
// same as the code segment in the question,
//so skipping this part.
//just copy it from my question
}
// ...
}
Необязательно:
В viewPager2 вы можете получить текущий фокус с помощью getCurrentItem()
, но так как мы заменили viewpager2 на recyclerview, у нас нет этого метода. Итак, нам нужно реализовать собственную эквивалентную версию. Если вы парень Kotlin, вы можете сразу перейти к ссылке 2 и пропустить эту часть. Вот версия java, если вам нужно, но я пропущу объяснение. Создайте SnapHelperExt.java
public class SnapHelperExt {
public SnapHelperExt(){}
public int getSnapPosition(RecyclerView recyclerView, SnapHelper snapHelper){
RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
View snapView = snapHelper.findSnapView(layoutManager);
if (snapView != null) {
return layoutManager.getPosition(snapView);
}else{
return -1;
}
}
}
Далее создайте интерфейс OnSnapPositionChangeListener
как наш слушатель:
public interface OnSnapPositionChangeListener {
void onSnapPositionChange(int position);
}
После этого создайте SnapOnScrollListener.java
:
public class SnapOnScrollListener extends RecyclerView.OnScrollListener {
public enum Behavior {
NOTIFY_ON_SCROLL,
NOTIFY_ON_SCROLL_STATE_IDLE
}
private SnapHelperExt snapHelperExt;
private SnapHelper snapHelper;
private Behavior behavior;
private OnSnapPositionChangeListener onSnapPositionChangeListener;
private int snapPosition = RecyclerView.NO_POSITION;
public SnapOnScrollListener(SnapHelper snapHelper, Behavior behavior, OnSnapPositionChangeListener onSnapPositionChangeListener){
this.snapHelper = snapHelper;
this.behavior = behavior;
this.onSnapPositionChangeListener = onSnapPositionChangeListener;
this.snapHelperExt = new SnapHelperExt();
}
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (behavior == Behavior.NOTIFY_ON_SCROLL) {
maybeNotifySnapPositionChange(recyclerView);
}
}
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (behavior == Behavior.NOTIFY_ON_SCROLL_STATE_IDLE
&& newState == RecyclerView.SCROLL_STATE_IDLE) {
maybeNotifySnapPositionChange(recyclerView);
}
}
private void maybeNotifySnapPositionChange(RecyclerView recyclerView){
int prevPosition = this.snapHelperExt.getSnapPosition(recyclerView, snapHelper);
boolean snapPositionIsChanged = (this.snapPosition!=prevPosition);
if(snapPositionIsChanged){
onSnapPositionChangeListener.onSnapPositionChange(prevPosition);
this.snapPosition = prevPosition;
}
}
}
Наконец, используйте его следующим образом:
SnapOnScrollListener snapOnScrollListener = new SnapOnScrollListener(
snapHelper,
SnapOnScrollListener.Behavior.NOTIFY_ON_SCROLL,
position -> {
Log.e(TAG, "currently focused page no = "+position);
// your code here, do whatever you want
}
);
childRecyclerView2.addOnScrollListener(snapOnScrollListener);
Ссылки:
- create-viewpager-using-recyclerview
- Обнаружение мгновенных изменений с помощью андроидов-переработчиков