Android Spinner : 선택한 항목 변경 이벤트 가져 오기


407

선택한 항목이 변경 될 때 Spinner의 이벤트 리스너를 어떻게 설정할 수 있습니까?

기본적으로 내가하려는 것은 이와 비슷한 것입니다.

spinner1.onSelectionChange = handleSelectionChange;

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

이 답변을 시도했지만 아무도 도움이되지 않았습니다. 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

39
실제로 해당 문제는 onOn 메소드가 아닌 대체 OnStart 메소드에 setOnItemSelectedListener를 넣어서 해결할 수 있습니다. 바보 같은 ...
Kennethvr

16
리스너를 onStart 메소드에 넣었지만, onCreate와 같이 사용자가 아무것도 볼 수 있기 전에 호출됩니다. 버튼은 초기 표시시 표시됩니다. 당신의 경험이 다르다고 말하는가? 그렇다면 누락 된 onStart 메소드에서 다르게 무엇을하고 있습니까?
예브게니 심킨

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;
    } 
}); 

참고 : 한 가지만 기억하십시오.

스피너 OnItemSelectedListener이벤트는 두 번 실행됩니다.

  1. 스피너 초기화
  2. 사용자가 수동으로 선택

플래그 변수를 사용하여이 두 가지를 구별하십시오.


3
광산도 두 번 불려옵니다! 두 가지를 어떻게 구분하는지 알 수 없습니까?
MAC

18
Boolean initialDisplay = true와 같은 전역 부울을 설정하기 만하면됩니다. 그런 다음 onSelect에서 true인지 확인하고 그렇지 않은 경우 select에서 수행하려는 다른 작업을 수행하지 말고 다음에 호출 할 때 (사용자가 실제로 선택할 때) 플래그를 false로 설정하십시오.
예브게니 Simkin

OnclickListener 실행에 대한 최상의 설명.
Pankaj Kumar

6
개인적으로 너무나 단순한 것 (기본 UI 위젯)은 구현하기가 너무 어려워서 ... 진지하게- '기본 표시 항목'속성을 작성하고 객체에 부울 플래그 속성을 작성하는 것이 얼마나 어려울까 수업 자체 ?? 나는 Objective C의 팬이 아니지만 iOS 위젯 구현은 Android에서보다 약 1/10 시간이 걸린다고 말할 것입니다.
베넷 본 베넷

4
동의합니다. 스피너는 하나의 고정 위젯입니다. 팝업 또는 드롭이 언제 열리거나 닫히는 지 알기가 매우 어렵습니다. 이에 대한 이벤트를 추가하기가 어려웠습니까? 위의 솔루션은 목록이 열려 있거나 닫혀 있지만 세 가지 문제가있는 경우 ALMOST가 알려줄 수 있습니다. (1) 이미 선택된 항목을 선택하는 이벤트가없고 (목록이 닫힙니다.) (2) 중단 할 이벤트가 없습니다 (터치) (3) onNothingSelected는 결코 나를 위해 발사하지 않는 것 같습니다.
Batdude

19

AdapterView.OnItemSelectedListener활동에서 클래스를 구현할 수 있습니다 .

그런 다음 아래 줄을 사용하십시오. onCreate()

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

그런 다음이 두 가지 방법을 재정의하십시오.

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
익명의 내부 클래스 내에서 최종 변수가 아닌 변수를 사용할 수 없습니다. iCurrentSelection이 익명 클래스 내 에서 변수가 선언 되면 정상적으로 작동합니다. 첫 번째 호출에서 코드가 실행되도록 -1로 초기화 할 수 있습니다.
dahvyd

2
이것을 사용하면 @ intvyd가 정확합니다 .int는 final이어야합니다. 어쨌든 그것은 정말 잘 작동합니다. 위치 0을 선택하지 않고 변경 한 경우 다시 활성화하면 EditText 필드를 비활성화했습니다. 고마워
natur3

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

onCreate 또는 onStart에서 OnItemSelectedListener를 설정하는 것은 중요하지 않습니다. Activity 생성 또는 시작 중 (각각) 여전히 호출됩니다.
따라서 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
이것은 스피너가 처음 시작될 때 호출되는이 콜백 문제를 다루지 않습니다 (따라서 실제로 선택된 항목과 관련이없는 응답을 유발합니다).
예브게니 심킨

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;in 을 갖는 것 입니다 onCreate(). 그리고 아이템 선택 이벤트에서 그 플래그 즉 flagitemselected++,; 그런 다음 확인

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

이것은 내가 추측하는 데 도움이 될 것입니다.


0

내가 찾은 한 가지 트릭은 setOnItemSelectedListeners를 onCreate 대신 onWindowFocusChanged에 넣는 것입니다. 나는이 방법으로 나쁜 부작용을 발견하지 못했습니다. 기본적으로 윈도우가 그려진 후 리스너를 설정하십시오. onWindowFocusChanged가 얼마나 자주 실행되는지 잘 모르겠지만 너무 자주 실행되는 경우 잠금 변수를 쉽게 만들 수 있습니다.

안드로이드가 메시지 기반 처리 시스템을 사용하고 있다고 생각하고 onCreate에 모두 넣으면 스피너가 그려진 후 스피너가 채워지는 상황이 발생할 수 있습니다. 따라서 항목 위치를 설정하면 청취자가 시작됩니다. 이것은 물론 교육받은 추측이지만이 문제를 자유롭게 고칠 수 있습니다.


0

기본적으로 스피너 배열의 첫 번째 항목은

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

스피너에서 값을 선택할 때마다 선택한 값이 제공됩니다.

선택한 항목의 위치를 ​​원하면 그렇게하십시오.

pos = spinner.getSelectedItemPosition();

위의 두 답변은 리스너를 적용하지 않은 것입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.