web-dev-qa-db-ja.com

スピナーのonItemSelectedが誤って呼び出されました(ユーザーアクションなし)

ダイアログビューに表示しているスピナーがあり、ダイアログが開始した瞬間にonItemSelectedが呼び出されます。私はこれを実際に処理したくありませんが、ユーザーが選択を行ったときにのみ処理します。だから私はこれを防ぐ必要がある(おそらくデフォルト値が設定されていないためでしょうか?)、またはこの選択をしているのがユーザーではないことを知る必要がありますか?

26
Androider

Androider、私はこの問題の解決策を見つけて、ここに(コードサンプルと共に)投稿しました:

Spinner onItemSelected()は想定されていないときに実行されます

6

Bill Moteのソリューションの精神におけるもう1つのオプションは、OnItemSelectedListenerOnTouchListenerにすることです。次に、ユーザー操作フラグをonTouchメソッドでtrueに設定し、選択の変更が処理されたらonItemSelected()でリセットできます。ユーザーインタラクションフラグはスピナー専用に処理され、目的の動作に影響を与える可能性のあるアクティビティの他のビューでは処理されないため、この解決策をお勧めします。

コードで:

スピナーのリスナーを作成します。

public class SpinnerInteractionListener implements AdapterView.OnItemSelectedListener, View.OnTouchListener {

    boolean userSelect = false;

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        userSelect = true;
        return false;
    }

    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
        if (userSelect) { 
            // Your selection handling code here
            userSelect = false;
        }
    }

}

リスナーをOnItemSelectedListenerOnTouchListenerの両方としてスピナーに追加します。

SpinnerInteractionListener listener = new SpinnerInteractionListener();
mSpinnerView.setOnTouchListener(listener);
mSpinnerView.setOnItemSelectedListener(listener);
41
Andres Q.

あなたはそれを解決するために単にintカウントを追加することができます:)

 sp.setOnItemSelectedListener(new OnItemSelectedListener() {
    int count=0;
    @Override
    public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
        if(count >= 1){
            int item = sp.getSelectedItemPosition();
            Toast.makeText(getBaseContext(),
                 "You have selected the book: " + androidBooks[item],
                  Toast.LENGTH_SHORT).show();
        }
        count++;
    }


    @Override
    public void onNothingSelected(AdapterView<?> arg0) {
    }
});
21

APIレベル3から、ブール値を持つアクティビティでonUserInteraction()を使用して、ユーザーがデバイスと対話しているかどうかを確認できます。

http://developer.Android.com/reference/Android/app/Activity.html#onUserInteraction()

@Override
public void onUserInteraction() {
    super.onUserInteraction();
    userIsInteracting = true;
}

私が持っている活動のフィールドとして:

private boolean userIsInteracting;

最後に、私のスピナー:

    mSpinnerView.setOnItemSelectedListener(new OnItemSelectedListener() {

        @Override
        public void onItemSelected(AdapterView<?> arg0, View view, int position, long arg3) {
            spinnerAdapter.setmPreviousSelectedIndex(position);
            if (userIsInteracting) {
                updateGUI();
            }
        }

        @Override
        public void onNothingSelected(AdapterView<?> arg0) {

        }
    });

アクティビティを行ったり来たりすると、ブール値はfalseにリセットされます。魅力のように機能します。

8
Bill Mote

この問題は別の方法で解決しました。方向の変更時にonItemSelectedメソッドが2回呼び出される場合と、1回呼び出される場合があることに気づいたためです。

現在のスピナーの選択に依存しているようです。そのため、フラグやカウンターは機能しませんでした。代わりに、widgetsRestartTime = System.currentTimeMillis()を使用してシステム時刻をonResume()とonCreateの両方に記録します

widgetsRestartTimeは、doubleおよびintance変数として宣言されています。

OnItemSelected()メソッドで現在の時刻を再度確認し、widgetsRestartTimeを次のように減算します。 } else {//システムが生成したイベントeg向きの変更、アクティビティの起動。無視してください}

4
karl

私も同じ問題を抱えていました。しかし、フォームに複数のスピナーがあり、それらのいくつかが非表示になっているため、受け入れられたソリューションは機能しませんでした。スピナーが非表示の場合、リスナーは起動しません。したがって、カウントは私にとってのソリューションではありません。

別の解決策が見つかりました:

  1. スピナーの初期化中に、アクティビティのonCreate()またはフラグメントのonCreateViewで、リスナーを設定する前に、デフォルトのタグを設定します
  2. リスナーでタグが存在する場合は、タグを確認してから削除し、コードを実行しないでください。

それだけです、それは魅力のように機能します!

リスナーの例:

        if(((String)parent.getTag()).equalsIgnoreCase(TAG_SPINNERVALUE))
        {
            parent.setTag("");
            return;
        }

追伸そして、これは複数のスピナーに設定された同じリスナーに対して機能します!

3
XMight

同じ問題があり、以前に選択したスピナーの値を覚えておくことで解決しました。各onItemSelected呼び出しで、新しい値を前の値と比較し、同じ場合はコードをさらに処理しません。

3
Shumoapp

最初は選択されていないSpinner も購入している場合は、

@Override
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
    if(pos != 0) {
        pos--;

        // your code here
    }
}

アイテム0は選択できないため。乾杯:-)

2
ThomasRS

はい、あなたが見ているものは正しく、デフォルトの振る舞いです、あなたはこれを防ぐことはできません。 OnItemSelectedコールバックは、初期ロード時に呼び出されます。最初の読み込み後は、ユーザーが選択を変更した場合、またはコード内から選択を変更した場合にのみトリガーされます。イベントが初期ロードの結果であったかどうかを通知できるインジケーターを使用でき、処理したくない場合は最初のイベントを無視できます。

2
Veeresh

それは私のために働いた、

private boolean isSpinnerInitial = true;

@Override
public void onItemSelected(AdapterView<?> parent, View view,
        int position, long id) {

    if(isSpinnerInitial)
    {
        isSpinnerInitial = false;
    }
    else  {
        // do your work...
    }

}
2
karan

シーケンスが重要です。

spinner.setAdapter(adapter);
spinner.setSelection(position);
spinner.setOnItemSelectedListener(listener);
1
Treesouth

次のように、2つの引数を使用してスピナーを設定することができます。

spinner.setSelection(count, false);

したがって、これをセットOnItemSelectedListenerの前に置きます。

spinner.setSelection(0,false);

詳細は開発者ページから確認できます。

https://developer.Android.com/reference/Android/widget/Spinner.html

1
Carlos Ughini

私もインターネットで良い解決策を探しましたが、自分のニーズを満たすものが見つかりませんでした。したがって、この拡張機能をSpinnerクラスに記述して、ListViewと同じ動作を持つ単純なOnItemClickListenerを設定できるようにしました。

アイテムが「選択」された場合のみ、onItemClickListenerが呼び出されます。

楽しんでください!

public class MySpinner extends Spinner
{
    private OnItemClickListener onItemClickListener;


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

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

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

    @Override
    public void setOnItemClickListener(Android.widget.AdapterView.OnItemClickListener inOnItemClickListener)
    {
        this.onItemClickListener = inOnItemClickListener;
    }

    @Override
    public void onClick(DialogInterface dialog, int which)
    {
        super.onClick(dialog, which);

        if (this.onItemClickListener != null)
        {
            this.onItemClickListener.onItemClick(this, this.getSelectedView(), which, this.getSelectedItemId());
        }
    }
}
1
Cliffus

Promtの位置を使用してもかまわない場合は、スピナーでスタッフを配置するたびに、このようなことを行うことができます。最初に選択をpromtに設定します。

spinner.setselected(0);
spinner.add("something");
...

そして、選択が行われたときにそのようなことを行います:

spinner.ItemSelected += (object sender, AdapterView.ItemSelectedEventArgs e) => 
            {
                if (spinner.SelectedItemPosition != 0)
                {
                   //do staff
                } 
            }
0
CDrosos