1

私は標準のAndroidギャラリーコントロールを持っています:

<Gallery
    android:id="@+id/galArt"
    android:spacing="10dp"
    android:fadingEdgeLength="0dp"
    android:unselectedAlpha="1"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" />

このコードでイベントをリッスンします。

galArt.setOnItemSelectedListener(new OnItemSelectedListener() {
        public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
            showMessageToast("Selected: " + pos);           
        }
        public void onNothingSelected(AdapterView<?> arg0) {}
    });

これは、意図したとおりに機能します。画像をスワイプすると、どの画像が選択されているかを示すトーストが表示されます。

ただし、このトーストは、アニメーションの実行中に画像のスライドが停止する前に表示されます。アニメーションの中断を避けるために、スライドが停止した後にアクションを実行したいと思います。

アニメーションが終了した後に通知を受け取るために何を聞くことができますか?

4

1 に答える 1

0

了解しました。解決策を見つけました。これは単なる解決策であり、必ずしも最良の解決策ではないことに注意してください。

私の解決策は、すべての論理イベント(onScrollやonAnimationEndなど、いずれも機能させることができなかったため)を無視し、子ビューの場所の変更をリッスンすることです。子ビューが静止しているとき、アニメーションは終了しています。

このようにすることの実際の利点は、これがドラッグとフリングの両方で機能することです。

問題は、onItemSelected関数がUIスレッド以外のスレッドから呼び出されることです。例に示すように、アクティビティのrunOnUIThread関数を使用してこれを解決します。

変更をリッスンする方法(これは通常のonItemSelected関数ではなく、私自身のonItemReallySelectedであることに注意してください):

galArt.setOnItemReallySelectedListener(new OnItemSelectedListener() {
    public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
            _activity.runOnUiThread(new Runnable() {
                public void run() {
                    //Do your stuff here ...
                }
            });
    }
    public void onNothingSelected(AdapterView<?> arg0) {
        //... or here.
    }
});

Androidギャラリーの私の実装:

import java.util.Timer;
import java.util.TimerTask;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.Gallery;

public class ArtGallery extends Gallery {

    OnItemSelectedListener _listener;
    Timer _timer = new Timer();

    public ArtGallery(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public ArtGallery(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

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

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if(event.getAction()==MotionEvent.ACTION_UP){
            setTimer();
        }
        return super.onTouchEvent(event);
    }

    private int _lastScrollX = Integer.MIN_VALUE;
    private void setTimer() {
        //Cancel existing tasks (if any), and create a new timer.
        _timer.cancel();
        _timer = new Timer();

        //Schedule our animation check.
        _timer.schedule(new TimerTask() {
            @Override
            public void run() {
                //Just some value that will change while the animation is running.
                int x = getSelectedView().getLeft(); 
                if(_lastScrollX != x){
                    //Value has changed; save current value, and reset the timer.
                    _lastScrollX = x;
                    setTimer();
                }else{
                    //The value hasn't changed during the last 50ms. That probably means that the animation has stopped.
                    fireOnSelected();
                }
            }
        }, 50); 
    }

    public void setOnItemReallySelectedListener(OnItemSelectedListener listener){
        _listener = listener;
    }

    //This function is copied from the Android Gallery source code, and works exactly like the original one.
    private void fireOnSelected() {
        if (_listener == null)
            return;

        int selection = this.getSelectedItemPosition();
        if (selection >= 0) {
            _listener.onItemSelected(this, getSelectedView(), selection, getAdapter().getItemId(selection));
        } else {
            _listener.onNothingSelected(this);
        }

    }
}
于 2012-08-16T20:54:55.697 に答える