4

smoothScrollToPosition()の方法はGridView正しく機能しますか?未解決のバグレポートを見つけましたが、私のものも正しく機能していません。

setSelection()正常に動作していますが、スムーズなスクロール効果が必要です。

この問題について何か考えがありますか?

これが永続的な問題である場合、どこから適切なスクロール効果を実装し始める必要がありますか?

4

2 に答える 2

3

投稿したサンプルコードの実行で問題は発生していませんが、アプリケーションで一貫した結果が表示されない場合は、独自のスクロールコントローラーを作成するのはそれほど難しいことではありません。使用できる実装例は次のとおりです。

private class ScrollPositioner {
    private static final int SCROLL_DURATION = 20;
    private static final int DIR_UP = 1;
    private static final int DIR_DOWN = 2;

    int mTargetPosition = AdapterView.INVALID_POSITION;
    int mDirection = AdapterView.INVALID_POSITION;
    int mLastSeenPosition = AdapterView.INVALID_POSITION;
    int mExtraScroll;
    GridView mGrid;

    public ScrollPositioner(GridView grid) {
        mGrid = grid;
        mExtraScroll = ViewConfiguration.get(mGrid.getContext()).getScaledFadingEdgeLength();
    }

    Handler mHandler = new Handler();
    Runnable mScroller = new Runnable() {
        public void run() {
            int firstPos = mGrid.getFirstVisiblePosition();
            switch(mDirection) {
            case DIR_UP: {
                if (firstPos == mLastSeenPosition) {
                    // No new views, let things keep going.
                    mHandler.postDelayed(mScroller, SCROLL_DURATION);
                    return;
                }

                final View firstView = mGrid.getChildAt(0);
                if (firstView == null) {
                    return;
                }
                final int firstViewTop = firstView.getTop();
                final int extraScroll = firstPos > 0 ? mExtraScroll : mGrid.getPaddingTop();

                mGrid.smoothScrollBy(firstViewTop - extraScroll, SCROLL_DURATION);

                mLastSeenPosition = firstPos;

                if (firstPos > mTargetPosition) {
                    mHandler.postDelayed(mScroller, SCROLL_DURATION);
                }
                break;
            }

            case DIR_DOWN: {
                final int lastViewIndex = mGrid.getChildCount() - 1;
                final int lastPos = firstPos + lastViewIndex;

                if (lastViewIndex < 0) {
                    return;
                }

                if (lastPos == mLastSeenPosition) {
                    // No new views, let things keep going.
                    mHandler.postDelayed(mScroller, SCROLL_DURATION);
                    return;
                }

                final View lastView = mGrid.getChildAt(lastViewIndex);
                final int lastViewHeight = lastView.getHeight();
                final int lastViewTop = lastView.getTop();
                final int lastViewPixelsShowing = mGrid.getHeight() - lastViewTop;
                final int extraScroll = lastPos < mGrid.getAdapter().getCount() - 1 ? mExtraScroll : mGrid.getPaddingBottom();

                mGrid.smoothScrollBy(lastViewHeight - lastViewPixelsShowing + extraScroll, SCROLL_DURATION);

                mLastSeenPosition = lastPos;
                if (lastPos < mTargetPosition) {
                    mHandler.postDelayed(mScroller, SCROLL_DURATION);
                }
                break;
            }

            default:
                break;
            }
        }
    };

    public void scrollToPosition(int position) {
        mTargetPosition = position;
        mLastSeenPosition = AdapterView.INVALID_POSITION;

        if(position < mGrid.getFirstVisiblePosition()) {
            mDirection = DIR_UP;
        } else if (position > mGrid.getLastVisiblePosition()) {
            mDirection = DIR_DOWN;
        } else {
            return;
        }
        mHandler.post(mScroller);
    }
}

これは、フレームワーク実装の代わりにスクロールを実行するこの新しいクラスを含む、リンクした例のスニペットです。

GridView g;
boolean t= false;
@Override
public void onBackPressed() {
    //Instantiate and attach the custom positioner
    if(mPositioner == null) {
        mPositioner = new ScrollPositioner(g);
    }
    //Use the custom object to scroll the view
    mPositioner.scrollToPosition(0);
    if(t) {
        super.onBackPressed();
    }
    else {
        t = true;
    }
}

スクロール方向が下向きでも、選択した位置が常に上にスクロールする機能を追加したい場合は、それを行うことができます。 これは、フレームワークの実装が行うように設計されたものではありませんがDIR_DOWN、最初の表示位置がターゲットと一致するまでスクロールを継続するコードを追加することで実現できます(DIR_UPそうするように)。また、位置が一番上に到達する前にスクロールが終了する場合にも注意する必要があります。そのため、異なる結果が得られない場合にハンドラーを常に投稿しているわけではありません。

HTH

于 2012-01-19T08:09:09.037 に答える
1

Had the same issue- I built a simple GridView and for some reason the smoothScrollToPosition() didn't work at all (just bounce from time to time).

after lot of debugging it turn out to be that I need to remove the android:padding parameter from the GridView.

very strange, I really don't know why it is like this, but at least now it works.

于 2013-03-14T09:13:15.987 に答える