Android Spinner:選択されたアイテム変更イベントを取得します


407

選択したアイテムが変更されたときに、Spinnerのイベントリスナーをどのように設定できますか?

基本的に私がやろうとしていることはこれに似たものです:

spinner1.onSelectionChange = handleSelectionChange;

void handleSelectionChange(Object sender){
    //handle event
}

私はこれらの答えを試しましたが、誰も役に立ちませんでした。Spinnerコンポーネントがアイテムのクリックイベントをサポートしない場合。Spinnerのドキュメント

回答:


812

以前の回答のいくつかは正しくありません。他のウィジェットやビューでも機能しますが、Spinnerウィジェットのドキュメントには次のように明記されています。

スピナーはアイテムのクリックイベントをサポートしていません。このメソッドを呼び出すと、例外が発生します。

代わりにOnItemSelectedListener()を使用することをお勧めします。

spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
    @Override
    public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
        // your code here
    }

    @Override
    public void onNothingSelected(AdapterView<?> parentView) {
        // your code here
    }

});

これでうまくいきます。

onItemSelectedメソッドは、ビューの構築時にも呼び出されるため、onCreate()メソッド呼び出し内に配置することを検討できます。


47
この問題は、ビューの構築時にonItemSelectedメソッドも呼び出されることです。したがって、そこに記述されたコードは、起動時にも実行されます。ユーザーが実際にアイテムを選択した場合にのみ、含まれているコードを実行する方法はありますか?
Kennethvr、2010

39
実際には、onCreateメソッドではなくオーバーライドOnStartメソッドにsetOnItemSelectedListenerを配置することで、この問題を解決できます。愚かな私...
Kennethvr 2010

16
リスナーをonStartメソッドに配置しましたが、onCreateと同様に、ユーザーが何かを見る前に呼び出されます。つまり、私の場合、ユーザーが何かを選択するまで非表示にすることを目的とする「進む」ボタンでは、ボタンは、初期表示時に表示されます。あなたの経験は違うと言っていますか?もしそうなら、私が見逃しているonStartメソッドであなたは何を違うようにしていますか?
Yevgeny Simkin

7
匿名リスナー内の別のフィールドを使用して最初の選択を記録し、選択に遭遇しない限りonItemSelectedに何もしないように指示しますか?ちょっとした考え。
Sam Svenbjorgchristiensensen

4
しかし、ユーザーが一番上にある「デフォルト」アイテムを選択するとどうなるでしょうか。その後onItemSelected(...)、ヒットされません。(私はこれを難しい方法で見つけたので知っています。)
Andrew Wyld

55
Spinner spnLocale = (Spinner)findViewById(R.id.spnLocale);

spnLocale.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
    public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) { 
        // Your code here
    } 

    public void onNothingSelected(AdapterView<?> adapterView) {
        return;
    } 
}); 

注: 1つのことを覚えておいてください。

スピナーOnItemSelectedListenerイベントは2回実行されます。

  1. スピナーの初期化
  2. ユーザーが手動で選択

フラグ変数を使用して、これら2つを区別してみてください。


3
鉱山も2回呼び出されます!2つをどのように区別するかわかりませんか?
MAC

18
Boolean initialDisplay = true;のようなグローバルブールを設定するだけです。次に、onSelectでtrueかどうかを確認し、trueの場合は、selectで他に行うことは何もしないで、フラグがfalseに設定されるようにして、次回呼び出されたとき(ユーザーが実際に選択したとき)に備えます。
Yevgeny Simkin

OnclickListenerの実行に関する最良の説明。
Pankaj Kumar

6
私は個人的に、とても単純なもの(このような基本的なUIウィジェット)を実装するのは非常に難しいです...真剣に-「デフォルトの表示アイテム」プロパティを構築し、ブールフラグプロパティをオブジェクトに構築するのはどれほど難しいでしょうか。クラス自体?? 私はObjective Cのファンではありませんが、iOSウィジェットの実装には、Androidの約10分の1の時間がかかると言います。
ベネットフォンベネット

4
私も同意します。スピナーは、ねじ込まれたウィジェットの1つです。ポップアップまたはドロップが開いているか閉じているかを知るのは非常に困難です。このためのイベントを追加するのはそれほど大変だったでしょうか?上記のソリューションは、リストが開いているか閉じているかをALMOSTに通知しますが、3つの問題があります:(1)すでに選択されているアイテムを選択するイベントがない(そしてリストが閉じる)、および(2)中止するイベントがない(タッチ)それを閉じるためのオフリスト)と(3)onNothingSelectedが起動しないようです。
Batdude 2013年

19

AdapterView.OnItemSelectedListenerアクティビティにクラスを実装できます。

そして、以下の行を使用します onCreate()

Spinner spin = (Spinner) findViewById(R.id.spinner);
spin.setOnItemSelectedListener(this);

次に、これらの2つのメソッドをオーバーライドします。

public void onItemSelected(AdapterView<?> parent, View v, int position, long id) {
    selection.setText(items[position]);
}

public void onNothingSelected(AdapterView<?> parent) {
    selection.setText("");
}

16

https://stackoverflow.com/q/1714426/811625

単純なチェックでOnItemSelectedListener()が呼び出されるのを回避できます。現在の選択インデックスを整数変数に格納し、何かを行う前にonItemSelected(..)内でチェックします。

例えば:

Spinner spnLocale;

spnLocale = (Spinner)findViewById(R.id.spnLocale);

int iCurrentSelection = spnLocale.getSelectedItemPosition();

spnLocale.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
    public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) { 
    if (iCurrentSelection != i){
            // Your code here
    }
    iCurrentSelection = i;
    } 

    public void onNothingSelected(AdapterView<?> adapterView) {
        return;
    } 
}); 

iCurrentSelectionこれが機能するためには、オブジェクトスコープにある必要があります。


1
匿名の内部クラス内で非final変数を使用することはできません。iCurrentSelection変数がこの匿名クラス内で宣言されている場合、正常に動作します。最初の呼び出しでコードが実行されるように、これを-1に初期化できます。
12

2
これを使用する場合、@ dahvydは正しかった。intはfinalでなければならない。いずれにせよ、それは本当にうまくいきます。位置0が選択されておらず、変更された場合、EditTextフィールドを無効にしていました。これをありがとう。
natur3 2015年

8

スピナー名とIDを見つけて、このメソッドを実装します。

spinnername.setOnItemSelectedListener(new OnItemSelectedListener() {

    @Override
    public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
        // your code here
    }

    @Override
    public void onNothingSelected(AdapterView<?> parentView) {
        // your code here
    }
});

8

OnItemSelectedListenerをonCreateまたはonStartに設定するかどうかは関係ありません。アクティビティの作成時または開始時に(それぞれ)呼び出されます。
したがって、onCreateで設定できます(onStartではできません!)。
フラグを追加して、最初の初期化を把握します。

private Spinner mSpinner;
private boolean mSpinnerInitialized;

それからonCreate(またはonCreateView)で:

mSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
                if (!mSpinnerInitialized) {
                    mSpinnerInitialized = true;
                    return;
                }

                // do stuff
            }

            public void onNothingSelected(AdapterView<?> adapterView) {
                return;
            }
        });

1
このフラグをご利用いただきありがとうございます。
Javan R.

7

スピナーウィジェットのドキュメントは言う

スピナーはアイテムのクリックイベントをサポートしていません。

あなたのsetOnItemSelectedListener問題を処理するために使用する必要があります。


6
spinner1.setOnItemSelectedListener(
    new AdapterView.OnItemSelectedListener() {
        //add some code here
    }
);

1
これは、スピナーが最初に開始されるときに呼び出されるこのコールバックの問題には対処していません(したがって、実際に選択されている項目とは何の関係もない応答を引き起こします)。
Yevgeny Simkin、2011

4

スピナーの現在の選択のグローバル変数を取得します。

int currentItem = 0;

spinner_counter = (Spinner)findViewById(R.id.spinner_counter);
String[] value={"20","40","60","80","100","All"};
aa=new ArrayAdapter<String>(this,R.layout.spinner_item_profile,value);
aa.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner_counter.setAdapter(aa);

spinner_counter.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            if(currentItem == position){
                return; //do nothing
            }
            else
            {
                 TextView spinner_item_text = (TextView) view;
                 //write your code here
            }
            currentItem = position;
        }

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

        }
    });

//R.layout.spinner_item_profile
<?xml version="1.0" encoding="utf-8"?>

<TextView  android:id="@+id/spinner_item_text"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" 
android:layout_height="wrap_content"
android:background="@drawable/border_close_profile"
android:gravity="start"  
android:textColor="@color/black"         
android:paddingLeft="5dip"
android:paddingStart="5dip"
android:paddingTop="12dip"
android:paddingBottom="12dip"
/>

//drawable/border_close_profile
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
  <item>
   <shape android:shape="rectangle">
    <solid android:color="#e2e3d7" />
   </shape>
 </item>
<item android:left="1dp"
android:right="1dp"
android:top="1dp"
android:bottom="1dp">
<shape android:shape="rectangle">
    <solid android:color="@color/white_text" />
</shape>
</item>
</layer-list>

4

真のonChangedListener()が必要な場合。ハンドラーに初期値を格納し、変更されたかどうかを確認します。これはシンプルで、グローバル変数を必要としませ。ページに複数のスピナーがある場合に機能します。

String initialValue = // get from Database or your object
mySpinner.setOnItemSelectedListener(new SpinnerSelectedListener(initialValue));

...

protected class SpinnerSelectedListener implements AdapterView.OnItemSelectedListener {

        private SpinnerSelectedListener() {
            super();
        }

        public SpinnerSelectedListener(String initialValue) {
            this();
            this.initialValue = initialValue;
        }

        private String initialValue;

        // getter and setter removed.  

        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            final String newValue = (String) spinHeight.getItemAtPosition(position);
            if (newValue.equals(initialValue) == false) {
               // Add your code here.  The spinner has changed value. 

               // Maybe useful.   
               // initialValue = newValue;
            }

        }

        @Override
        public void onNothingSelected(AdapterView<?> parent) {
               // Maybe useful.   
               // initialValue = null; 
        }
    }

オブジェクトはあなたの友達です、それらを使用してください。


3
spinner.setOnItemSelectedListener(
            new AdapterView.OnItemSelectedListener() {

                @Override
                public void onItemSelected(AdapterView<?> arg0, View arg1,
                        int arg2, long arg3) {

                    // TODO Auto-generated method stub
                }

                @Override
                public void onNothingSelected(AdapterView<?> arg0) {
                    // TODO Auto-generated method stub

                }
                //add some code here
            }
        );

1

これは、スピナーとfindviewbyidを初期化し、これを使用して動作します

    Spinner schemeStatusSpinner;

  schemeStatusSpinner = (Spinner) dialog.findViewById(R.id.spinner);

schemeStatusSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
            // your code here
            if(schemeStatusSpinner.getSelectedItemId()==4){
                reasonll.setVisibility(View.VISIBLE);
            }
            else {
                reasonll.setVisibility(View.GONE);
            }
        }

        @Override
        public void onNothingSelected(AdapterView<?> parentView) {
            // your code here
        }

    });

1

私が思うことの最良の方法は、を持っていることflagitemselected = 0;ですonCreate()。そして、アイテム選択イベントでは、そのフラグをインクリメントしflagitemselected++ます。そしてチェック

if(flagitemselected!=1)
{
// do your work here
}

これは私が推測するのに役立ちます。


0

私が見つけた1つのトリックは、onCreateではなくonWindowFocusChangedにsetOnItemSelectedListenersを置くことでした。この方法で行うことによる悪影響はまだ見つかっていません。基本的に、ウィンドウが描画された後にリスナーを設定します。onWindowFocusChangedがどのくらいの頻度で実行されるかはわかりませんが、あまりにも頻繁に実行されている場合は、ロック変数を作成するのは簡単です。

Androidはメッセージベースの処理システムを使用していると思います。すべてをonCreateに入れると、スピナーが描画された後にスピナーが実装される状況に遭遇する可能性があります。そのため、アイテムの場所を設定すると、リスナーが起動します。もちろん、これは知識に基づいた推測ですが、これについては自由に修正してください。


0

デフォルトでは、スピナー配列の最初のアイテムを取得します

value = spinner.getSelectedItem().toString();

スピナーで値を選択すると、選択した値が表示されます

選択したアイテムの位置が必要な場合は、そのようにします

pos = spinner.getSelectedItemPosition();

上記の2つの答えは、リスナーを適用しない場合の答えです

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.