Spinner 개념
spinner란?
스피너는 값 집합에서 하나의 값을 선택할 수 있는 빠른 방법을 제공한다.
기본적으로 스피너는 현재 선택된 값을 표시할 수 있다.
보통 스피너를 터치하면 기타 모든 사용 가능한 값을 포함하는 "DropDown" 메뉴가 표시된다.
Spinner 생성
Spinner layout 설정
<Spinner
android:id="@+id/spinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@+id/tv_title"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
Spinner의 선택 항목 생성
스피너를 선택 항목으로 채우기 위해서는 Activity 또는 Fragment 에서
Spinner Adapter를 생성하여 Spinner에 설정해야 한다.
Spinner Adapter와 Spinner를 생성하기 위해 스피너의 주요 클래스를 알아보도록 하자.
스피너의 주요 클래스는 다음과 같다.
- Spinner
- Spinner Adapter
- AdapterView.OnItemSelectedListener
스피너에 제공하는 선택 항목은 어떠한 소스에서든 가져올 수 있다. (코드 내 list 또는 array 자료형,context의 Resource 등)
이러한 소스들은 반드시 Spinner Adapter를 통해 Spinner에 전달되어야 한다.
Spinner Adapter의 종류는 다음과 같다.
- 소스가 간단한 배열이라면 사용할 수 있는 "ArrayAdapter"
- 데이터베이스 쿼리를 통해 소스를 얻어와야 한다면 "CursorAdapter"
이번 포스팅에서는 간편한 ArrayAdapter 만을 다룬다.
Spinner의 선택 항목 소스는 코드 내에서 만들어진 collection일 수 있다.
val source = listOf("지구", "태양", "수성", "목성", "토성", "해왕성")
이 때 해당 소스를 ArrayAdapter를 이용해 Spinner에 할당할 수 있다.
//Fragment or Acitivity
val spinner = binding.spinner //or findViewById<Spinner>(R.id.spinner)
ArrayAdapter(
this,
android.R.layout.simple_spinner_item,
source
).also{ adapter ->
adapter.setDropDownViewResourece(android.R.layout.simple_spinner_dropdown_item)
spinner.adapter = adapter
}
1. ArrayAdapter 생성
- 1번째 인자 : Context = this 또는 requireContext()
- 2번째 인자 : int resource = Spinner에 대해 custom layout을 만든 게 아니라면 플랫폼에 정의된 Spinner 기본형인
android.R.layout.simple_spinner_item을 사용한다. - 3번째 인자 : collection = List 또는 Array 모두 사용 가능하다.
2. ArrayAdapter의 dropDown 메뉴 resource을 정해준다
ArrayAdapter.setDropDownViewResource() 메서드를 이용한다.
인자는 android.R.layout.simple_spinner_dropdown_item으로 역시나 플랫폼에 정의된 기본형이다.
3. spinner view에 adapter로 할당
spinner.adapter = adpater
Spinner 선택 항목 동적으로 할당하기
viewModel.list.observe(this) {
list?.let{
ArrayAdapter(
this,
android.R.layout.simple_spinner_item,
source
).also{ adapter ->
adapter.setDropDownViewResourece(android.R.layout.simple_spinner_dropdown_item)
spinner.adapter = adapter
}
}
}
그런데 만약 Spinner의 선택 항목 소스가 다음과 같이 res/value/array의 resources로부터 기반할 수 있다.
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<string_array name="planet_name">
<item>Mercury</item>
<item>Venus</item>
<item>Earth</item>
<item>Uros</item>
<item>Uranus</item>
<item>Cronus</item>
<item>Apollo</item>
</string_array>
</resources>
해당 소스를 ArrayAdapter.createFromResource() 메서드를 이용해 Spinner에 할당할 수 있다.
//Fragment or Acitivity
val spinner = binding.spinner //or findViewById<Spinner>(R.id.spinner)
ArrayAdapter.createFromResource(
this,
R.array.planet_name,
android.R.layout.simple_spinner_item
).also {
... //위와 같음.
}
createFromResource() 메서드를 이용.
두번째 인자로 res/value에 정의한 리소스가 들어간다는 점. (R.array.planet_name)
사용자 선택에 응답
사용자가 dropDown 메뉴에서 항목을 선택하면 Spinner 객체가 이벤트를 수신한다.
스피너가 항목 선택 이벤트 핸들러를 정의 하려면 AdapterView.OnItemSelectedListener 인터페이스 구현해야 한다.
class SpinnerActivity : Activity(), AdapterView.OnItemSelectedListener() {
...
override fun onItemSelected(p0: AdapterView<*>?, p1: View?, p2: Int, p3: Long) {
val item = p0?.getItemAtPosition(p2) ?: return
textView.text = item.toString()
}
override fun onNothingSelected(p0: AdapterView<*>?) {
textView.text = "빅뱅 이전."
}
}
인터페이스를 구현하면 2개의 callback Method를 override할 수 있다.
해당 메서드들을 알맞게 구현해준 뒤
//Fragment or Acitivity
val spinner = binding.spinner //or findViewById<Spinner>(R.id.spinner)
ArrayAdapter(
this,
android.R.layout.simple_spinner_item,
source
).also{ adapter ->
...
spinner.onItemSelectedListener = this
}
이처럼 spinner.onItemSelectedListener 에 this로 할당해준다.