簡體   English   中英

PagerSnapHelper 中的 From-To Page Changed 偵聽器

[英]From-To Page Changed Listener in PagerSnapHelper

我在水平RecyclerView中使用PagerSnapHelper來實現類似視圖尋呼機的行為。

final PagerSnapHelper pagerSnapHelper = new PagerSnapHelper(); pagerSnapHelper.attachToRecyclerView(recyclerView);

它工作得很好,但我希望能夠在用戶向任一方向更改頁面時獲得回調。 所以類似於onSwipeLeft / onSwipeRight回調。

我嘗試在PagerSnapHelper findTargetSnapPosition但這只給我targetIndex而不是當前索引。 我試過這樣的東西,但它並不總是有效。

@Override
public int findTargetSnapPosition(RecyclerView.LayoutManager layoutManager, int velocityX, int velocityY) {
    final int targetPos = super.findTargetSnapPosition(layoutManager, velocityX, velocityY);

    final View currentView = findSnapView(layoutManager);
    final int currentPos = layoutManager.getPosition(currentView);

    if (currentPos < targetPos) {
        callback.onSwipeRight();
    } else if (currentPos > targetPos) {
        callback.onSwipeLeft();
    }

    return targetPos;
}

有沒有更好的方法來實現這個總是有效的? 謝謝!

更新 2
!! 重要的提示 !!
如果您以編程方式調用scrollTo()並將SnapPagerScrollListenerON_SETTLED一起使用,則不會調用onScrollStateChanged 所以舊的捕捉位置不會得到更新。 WIP,我會在修復后立即更新課程。

更新

原始類在第一個布局上通知時存在一些問題。 現在它僅在項目位置第一次從RecyclerView.NO_POSITION更改為其他位置時觸發。

為了進一步擴展到僅在用戶手勢上忽略/觸發,因此對scrollTo()的非編程調用,請注意,在編程調用的情況下, onScrolled()會被dx == 0 and dy == 0觸發。

public class SnapPagerScrollListener extends RecyclerView.OnScrollListener {

    // Constants
    public static final int ON_SCROLL = 0;
    public static final int ON_SETTLED = 1;

    @IntDef({ON_SCROLL, ON_SETTLED})
    public @interface Type {
    }

    public interface OnChangeListener {
        void onSnapped(int position);
    }

    // Properties
    private final PagerSnapHelper snapHelper;
    private final int type;
    private final boolean notifyOnInit;
    private final OnChangeListener listener;
    private int snapPosition;

    // Constructor
    public SnapPagerScrollListener(PagerSnapHelper snapHelper, @Type int type, boolean notifyOnInit, OnChangeListener listener) {
        this.snapHelper = snapHelper;
        this.type = type;
        this.notifyOnInit = notifyOnInit;
        this.listener = listener;
        this.snapPosition = RecyclerView.NO_POSITION;
    }

    // Methods
    @Override
    public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);
        if ((type == ON_SCROLL) || !hasItemPosition()) {
            notifyListenerIfNeeded(getSnapPosition(recyclerView));
        }
    }

    @Override
    public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
        super.onScrollStateChanged(recyclerView, newState);
        if (type == ON_SETTLED && newState == RecyclerView.SCROLL_STATE_IDLE) {
            notifyListenerIfNeeded(getSnapPosition(recyclerView));
        }
    }

    private int getSnapPosition(RecyclerView recyclerView) {
        RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
        if (layoutManager == null) {
            return RecyclerView.NO_POSITION;
        }

        View snapView = snapHelper.findSnapView(layoutManager);
        if (snapView == null) {
            return RecyclerView.NO_POSITION;
        }

        return layoutManager.getPosition(snapView);
    }

    private void notifyListenerIfNeeded(int newSnapPosition) {
        if (snapPosition != newSnapPosition) {
            if (notifyOnInit && !hasItemPosition()) {
                listener.onSnapped(newSnapPosition);
            } else if (hasItemPosition()) {
                listener.onSnapped(newSnapPosition);
            }

            snapPosition = newSnapPosition;
        }
    }

    private boolean hasItemPosition() {
        return snapPosition != RecyclerView.NO_POSITION;
    }
}


用法:
只需將 SnapPagerScrollListener 的實例添加到您的 RecyclerView

your_recycler_view.addOnScrollListener(new SnapPagerScrollListener(your_snap_helper, SnapPagerScrollListener.ON_SCROLL/ON_SETTLED, true/false, your_on_changed_listener));


Type屬性用於定義何時觸發回調。

  1. ON_SCROLL:用於在新視圖/頁面通過中間時立即通知回調
  2. ON_SETTLED:用於通知 RecyclerViews 狀態為SCROLL_STATE_IDLE后的回調。 我使用該模式僅在滾動穩定后觸發 API 調用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM