버튼 수집상

[안드로이드] Spinner 아이템 선택 안 하고도 onItemSelectedListener 를 타는 문제 본문

TIL - 안드로이드

[안드로이드] Spinner 아이템 선택 안 하고도 onItemSelectedListener 를 타는 문제

cocokaribou 2022. 12. 8. 12:59

스피너 Spinner 를 열지도 않았는데

뷰를 초기화하자마자 디폴트값으로 onItemSelectedListener를 탔다.

 

검색해보니,

아이템을 선택한 건지 아닌지 판별하기 위해서는

터치리스너를 빼서 플래그를 켜야하는 것 같았다.

 

Android Spinner OnItemSelected ONLY on User Interaction

I know that this question has been answered multiple times, but I have not found any of them satisfactory and certainly not elegant. The issue is that OnItemSelected gets fired not only when the u...

stackoverflow.com

 

위의 코드를 정리하자면 이렇다.

spinner.apply {
    adapter = ArrayAdapter(binding.root.context, R.layout.view_common_sort_item, list)
    
    setOnTouchListener { _, _ ->
        isSpinnerTouched = true
        false
    }
    onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
        override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
            if (!isSpinnerTouched) return

            if (data.selected != parent?.selectedItem) {
                // select event
            }
            isSpinnerTouched = false
        }

        override fun onNothingSelected(p0: AdapterView<*>?) {
            isSpinnerTouched = false
        }
    }
}

 

결론:

- 웬만하면 스피너를 쓰지 말자.

- 리사이클러뷰로 뷰를 직접 만들던가 하자.

 

 

덧붙이는 말:

스피너는 리사이클러뷰 리스트와 다르게 최상단 UI에 그려진다.

 

 

덧붙이는 말 (2023.11):

디폴트로 선택된 아이템이 있다면, 굳이 위처럼 세팅하지 않아도 된다.

itemSelectedListener 를 세팅한 후, setSelection을 호출하면 최초의 선택지를 제어할 수 있다.

// 앱 언어변경 스피너
binding.languageSpinner.apply {
    adapter = ArrayAdapter(context, R.layout.view_language_item, languageList)
    onItemSelectedListener = itemSelectedListener // 리스너 설정

    // 현재 세팅된 언어로 디폴트 선택
    setSelection(
        when (currentLanguage) {
            LOCALE_KOREA -> 0
            LOCALE_CHINESE -> 1
            else -> 2
        }
    )
}

이러면 디폴트값으로 onItemSelectedListener을 최초 한 번만 잘 탄다.

728x90