5

Instagram のフィルター レイアウトの仕組みに似たレイアウトを作成しようとしています。基本的に、フィルターを選択すると、選択した項目までスクロールして + 1 表示され、さらにフィルターがあることが示されます。

私は現在、ここでLinearLayoutManager水平方向のカスタムを構築しようとしてRecyclerViewいます:

public class LinearLayoutSnapManager extends LinearLayoutManager {
    private int mCurrentPos = 0;

    public LinearLayoutSnapManager(Context context) {
        super(context);
    }

    public LinearLayoutSnapManager(Context context, int orientation, boolean reverseLayout) {
        super(context, orientation, reverseLayout);
    }

    public LinearLayoutSnapManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);

    }


    public void snap(RecyclerView rv, int position) {
        if (mCurrentPos == position) {
            // No move
            return;
        }

        boolean goingRight = true;
        if (position < mCurrentPos) {
            goingRight = false;
        }
        mCurrentPos = position;
        smoothScrollToPosition(rv, new RecyclerView.State(), goingRight ? getScrollRightPos(): getScrollLeftPos());
    }

    private int getScrollLeftPos() {
        int newPos = mCurrentPos - 1;
        return (newPos > 0) ? newPos : 0;
    }

    private int getScrollRightPos() {
        return mCurrentPos + 1;
    }
}

左にスクロールすると意図したとおりに機能しますが、右にスクロールすると、newItem + 1 に対してリストの最後にジャンプするように見え、なぜそれが起こるのかわかりません。

ここに画像の説明を入力

4

4 に答える 4

1

別の解決策をお勧めします。LinearLayoutManager便利な機能が付属しています:

int findFirstCompletelyVisibleItemPosition()

完全に表示されている最初のビューのアダプター位置を返します。


int findLastCompletelyVisibleItemPosition()

完全に表示されている最後のビューのアダプター位置を返します。


int findFirstVisibleItemPosition()

最初に表示されるビューのアダプター位置を返します。


int findFirstVisibleItemPosition()

最後に表示されたビューのアダプター位置を返します。

最初の 2 つの関数は完全に表示されているビューの位置を返しますが、最後の 2 つの関数は部分的に表示されているビューも返します。選択は、あなたが達成したい行動次第です。

それらを使用する場合、関数getScrollLeftPosgetScrollRightPosは次のようになります。

private int getScrollLeftPos() {
    int newPos = findFirstCompletelyVisibleItemPosition() - 1;
    return (newPos > 0) ? newPos : 0;
}

private int getScrollRightPos() {
    return findLastCompletelyVisibleItemPosition()+ 1;
}

メソッドを呼び出さないでください:

smoothScrollToPosition(rv, new RecyclerView.State(), goingRight ? getScrollRightPos(): getScrollLeftPos());

からLayoutManager。への参照がある場合は、次をRecyclerView呼び出します。

rv.smoothScrollToPosition(newPosition);

ソースコードをRecyclerView調べると、そのような実装が見つかります:

public void smoothScrollToPosition(int position) {
    if (mLayoutFrozen) {
        return;
    }
    if (mLayout == null) {
        Log.e(TAG, "Cannot smooth scroll without a LayoutManager set. " +
                "Call setLayoutManager with a non-null argument.");
        return;
    }
    mLayout.smoothScrollToPosition(this, mState, position);
}

これは基本的には同じですが、 の関数がLayoutManager適切な で呼び出されることに注意してくださいRecyclerView.State。それはちょうど一致していますRecyclerView

于 2016-11-03T15:34:55.447 に答える