안드로이드 스피너(Android Spinner)는 드롭다운 메뉴입니다. 스피너를 클릭하면 선택가능한 메뉴가 보이고, 이 메뉴 중 하나를 눌렀을 때 출력 값을 다르게 할 수 있습니다.
AndroidX RecyclerView 구현(kotlin) 글에서 구현한 것은 Android Dev Submmit
의 Youtube 정보를 RecyclerView로 보여주는 앱이었습니다.
이 프로젝트에 스피너를 추가하여, Android Dev Submmit
와 Google I/O
두개의 정보를 선택적으로 보여주도록 앱을 구현해보겠습니다.
프로젝트 생성
AndroidX RecyclerView 구현(kotlin)에서 만든 프로젝트에서 Spinner를 추가해보겠습니다.
이 프로젝트는 GitHub에서 다운받을 수 있습니다.
리소스 추가
새로운 이미지 3개를 다운받아야하는데요.
완성된 프로젝트의 /res/drawable/
에 보면 googleio
로 시작하는 JPG 파일 3개가 있습니다.
이 이미지를 다운로드하여 자신의 프로젝트, 동일 위치에 파일들을 추가해주세요.
그리고 프로젝트의 리소스 strings.xml
에 아래 3개의 문자열 추가해주세요.
<resources>
...
<string name="io_title01">Keynote</string>
<string name="io_title02">Android: Open to the future</string>
<string name="io_title03">Wear OS by Google</string>
...
</resources>
마지막으로 arrays.xml
을 만들고 아래 문자열 배열을 추가해주세요
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="spinner_entries">
<item >Android Dev Summit</item>
<item >Android I/O</item>
</string-array>
</resources>
스피너 정의
스피너는 XML 레이아웃에 다음과 같이 정의할 수 있습니다.
<Spinner
android:id="@+id/planets_spinner"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
저희는 entries
속성을 추가하여 activity_main.xml
에 스피너를 정의하겠습니다.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<Spinner
android:id="@+id/spinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:entries="@array/spinner_entries"
android:paddingTop="10dp"
android:paddingBottom="10dp"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/list_item"/>
</LinearLayout>
여기서 스피너의 entries
는 @array/spinner_entries
를 참조하는데요. 스피너의 리스트 목록을 가져옵니다.
이렇게 리소스로 리스트를 관리할 수 있습니다.
앱을 빌드하고 실행해보면 UI에 스피너가 생성되었고 터치해보면 리소스에서 추가한 리스트가 나오는 것을 볼 수 있습니다.
리스너 등록
하지만 리스트를 선택해봐도 화면은 달라지지 않습니다. 리스너를 등록하여 특정 목록을 선택했을 때 화면 구성을 다르게 할 수 있습니다.
Spinner에 리스너는 아래 코드처럼 등록할 수 있습니다. 그럼 onNothingSelected
와 onItemSelected
에 대한 콜백을 받을 수 있습니다.
spinner.onItemSelectedListener = object: AdapterView.OnItemSelectedListener {
override fun onNothingSelected(parent: AdapterView<*>?) {
}
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
}
}
코드를 조금 수정해서, "Android Dev Summit"
를 선택하면 Android Dev Summit에 대한 내용을 보여주고
Android I/O
을 선택하면 Android I/O에 대한 내용을 보여주도록 수정해보겠습니다.
class MainActivity : AppCompatActivity() {
private lateinit var adapter: RecyclerAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val list = ArrayList<YoutubeItem>()
adapter = RecyclerAdapter(list)
recyclerView.adapter = adapter
recyclerView.addItemDecoration(
DividerItemDecoration(this, DividerItemDecoration.VERTICAL))
spinner.onItemSelectedListener = object: AdapterView.OnItemSelectedListener {
override fun onNothingSelected(parent: AdapterView<*>?) {
}
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
Log.d("MainActivity",
"onItemSelected : $position, ${spinner.getItemAtPosition(position)}")
when (spinner.getItemAtPosition(position)) {
"Android Dev Summit" -> {
updateAndroidSubmit()
}
"Android I/O" -> {
updateGoogleIO()
}
else -> {
updateAndroidSubmit()
}
}
}
}
}
fun updateAndroidSubmit() {
val list = ArrayList<YoutubeItem>()
list.add(YoutubeItem(getDrawable(R.drawable.image01)!!, getString(R.string.title01)))
list.add(YoutubeItem(getDrawable(R.drawable.image02)!!, getString(R.string.title02)))
list.add(YoutubeItem(getDrawable(R.drawable.image03)!!, getString(R.string.title03)))
list.add(YoutubeItem(getDrawable(R.drawable.image04)!!, getString(R.string.title04)))
list.add(YoutubeItem(getDrawable(R.drawable.image05)!!, getString(R.string.title05)))
list.add(YoutubeItem(getDrawable(R.drawable.image06)!!, getString(R.string.title06)))
list.add(YoutubeItem(getDrawable(R.drawable.image07)!!, getString(R.string.title07)))
list.add(YoutubeItem(getDrawable(R.drawable.image08)!!, getString(R.string.title08)))
list.add(YoutubeItem(getDrawable(R.drawable.image09)!!, getString(R.string.title09)))
list.add(YoutubeItem(getDrawable(R.drawable.image10)!!, getString(R.string.title10)))
adapter.items = list
adapter.notifyDataSetChanged()
}
fun updateGoogleIO() {
val list = ArrayList<YoutubeItem>()
list.add(YoutubeItem(getDrawable(R.drawable.googleio01)!!, getString(R.string.io_title01)))
list.add(YoutubeItem(getDrawable(R.drawable.googleio02)!!, getString(R.string.io_title02)))
list.add(YoutubeItem(getDrawable(R.drawable.googleio03)!!, getString(R.string.io_title03)))
adapter.items = list
adapter.notifyDataSetChanged()
}
}
빌드해보면 컴파일 에러가 발생하는데요. RecyclerView의 item을 private val
에서 var
로 변경하면 에러가 해결됩니다.
class RecyclerAdapter(var items: ArrayList<YoutubeItem>) :
....
빌드 후 실행해보세요. 스피너의 목록을 선택하면 UI가 변경되는 것을 확인할 수 있습니다.
스피너 어댑터
XML에서 스피너의 엔트리를 설정하지 않고 코틀린 코드에서 설정할 수 있습니다. 이런 경우 직접 스피너의 어댑터를 생성해야 합니다.
val adapter = ArrayAdapter.createFromResource(
this,
R.array.spinner_entries, android.R.layout.simple_spinner_item
)
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
spinner.adapter = adapter
정리
간단히 XML로 스피너(Spinner)를 생성하는 방법과 리스너를 등록하여 목록에 따라 다르게 동작하도록 구현하였습니다. 또한 어댑터를 생성하여 스피너를 구현하는 방법을 알아보았습니다.
참고
- 샘플 코드는 GitHub에 있습니다
- Spinner - Android developer
Related Posts
- Android 14 - 사진/동영상 파일, 일부 접근 권한 소개
- Android - adb push, pull로 파일 복사, 다운로드
- Android 14 - 암시적 인텐트 변경사항 및 문제 해결
- Jetpack Compose - Row와 Column
- Android 13, AOSP 오픈소스 다운로드 및 빌드
- Android 13 - 세분화된 미디어 파일 권한
- Android 13에서 Notification 권한 요청, 알림 띄우기
- Android 13에서 'Access blocked: ComponentInfo' 에러 해결
- 에러 해결: android gradle plugin requires java 11 to run. you are currently using java 1.8.
- 안드로이드 - 코루틴과 Retrofit으로 비동기 통신 예제
- 안드로이드 - 코루틴으로 URL 이미지 불러오기
- Android - 진동, Vibrator, VibrationEffect 예제
- Some problems were found with the configuration of task 에러 수정
- Query method parameters should either be a type that can be converted into a database column or a List
- 우분투에서 Android 12 오픈소스 다운로드 및 빌드
- Android - ViewModel을 생성하는 방법
- Android - Transformations.map(), switchMap() 차이점
- Android - Transformations.distinctUntilChanged() 소개
- Android - TabLayout 구현 방법 (+ ViewPager2)
- Android - 휴대폰 전화번호 가져오는 방법
- Android 12 - Splash Screens 알아보기
- Android 12 - Incremental Install (Play as you Download) 소개
- Android - adb 명령어로 bugreport 로그 파일 추출
- Android - adb 명령어로 App 데이터 삭제
- Android - adb 명령어로 앱 비활성화, 활성화
- Android - adb 명령어로 특정 패키지의 PID 찾기
- Android - adb 명령어로 퍼미션 Grant 또는 Revoke
- Android - adb 명령어로 apk 설치, 삭제
- Android - adb 명령어로 특정 패키지의 프로세스 종료
- Android - adb 명령어로 screen capture 저장
- Android - adb 명령어로 System 앱 삭제, 설치
- Android - adb 명령어로 settings value 확인, 변경
- Android 12 - IntentFilter의 exported 명시적 선언
- Android - adb 명령어로 공장초기화(Factory reset)
- Android - adb logcat 명령어로 로그 출력