web-dev-qa-db-ja.com

Androidでのスムーズなスクロール

市場にはフローティング画像と呼ばれるアプリがあります。このアプリには、最もスムーズなスクロールロジックの1つがあります。基本的に、アプリには画面全体を覆う空白のキャンバスがあり、空白のキャンバスの上にいくつかの画像が表示されます。ユーザーはスワイプすることができ、アプリはスワイプの方向に画像を移動します。さらに、動的スクロールも行います。さらに、スクロールバーがないため、開発者はすべてのスムーズなスクロールロジックを実装するカスタムビューを作成したようです。

ソースを入手できれば素晴らしいと思います。しかし、この種の機能を実装する方法についての擬似コードやロジックは誰でも持っています。リード、サイトリンクが役立つでしょう。

32
prashant

OpenGLや加速度計の経験はありませんが、スワイプ(AndroidのAPIではflingと呼ばれます)を達成するのは難しくありません。このようなカスタムViewを作成するときに最初に必要なことは、GestureDetectorを実装し、ビューのonTouchEvent()でそのonTouchEvent()を呼び出すことです

_GestureDetector mGD = new GestureDetector(getContext(),
                                        new SimpleOnGestureListener() {

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2,
                                float distanceX, float distanceY) {
        // beware, it can scroll to infinity
        scrollBy((int)distanceX, (int)distanceY);
        return true;
    }

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float vX, float vY) {
        mScroller.fling(getScrollX(), getScrollY(),
                -(int)vX, -(int)vY, 0, (int)mMaxScrollX, 0, (int)mMaxScrollY);
        invalidate(); // don't remember if it's needed
        return true;
    }

    @Override
    public boolean onDown(MotionEvent e) {
        if(!mScroller.isFinished() ) { // is flinging
            mScroller.forceFinished(true); // to stop flinging on touch
        }
        return true; // else won't work
    }
});

@Override
public boolean onTouchEvent(MotionEvent event) {
    return mGD.onTouchEvent(event);
}
_

OnGestureListener.onScroll()View.scrollBy()を直接呼び出しますが、onFling()メソッドにはScrollerが必要です。

Scrollerは、参照が示すように、スクロールをカプセル化する単純なオブジェクトです。連続的なスクロールや、フリングに反応するために使用できます。 Scroller.fling()はそれ自体の内部でフリングスクロールの「シミュレーション」を開始し、それを見ることで、連続した再描画アニメーションでその滑らかさをコピーできます。

_@Override
protected void onDraw(Canvas canvas) {
    // ....your drawings....

    // scrollTo invalidates, so until animation won't finish it will be called
    // (used after a Scroller.fling() )
    if(mScroller.computeScrollOffset()) {
        scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
    }
}
_

つまり、アニメーションが実行されるまで、到達したポイントを計算し、そこでスクロールします。

最後の注意として:ダウン状態で何もしたくない場合でも、OnGestureListener.onDown()trueを返すことを忘れないでください。そうしないと機能しません。

Scroller in Android 2.2にはバグがあります。これは、引数として渡した制限に達しても、投げ飛ばしアニメーションが実際に終了しないバグです(まだ計算されたオフセットに関してそれらなので、実際には動きません)。

64
bigstones

フローティング画像アプリはオープンソースプロジェクトです。 http://code.google.com/p/floatingimage/

8
rallat