일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- Today
- Total
- android argument
- 안드로이드 범블비
- 안드로이드 커스텀 스위치
- android alarm
- 안드로이드 커스텀 스피너
- 코딩
- android alarm manager
- android navigation
- android custom spinner
- CoordinateLayout
- navGraph
- spinner hint
- android custom switch
- 무선페어링
- navArg
- layout behavior
- navigation navigate
- 파이어베이스
- thumb 공간
- navController
- Android Studio
- 안드로이드
- 툴바 고정
- alarm manager
- Android
- custom spinner
- 안드로이드 스튜디오
- track 공간
- 스피너 힌트
- checkedChangeListener
Pa K'ode
[안드로이드] Spinner 기본 사용 방법과 Custom 방법에대해 알아보자 본문
안녕하세요, 안드로이드 개발자 파쿠입니다 :)
오늘은 View의 한 종류인 Spinner에 대해 알아보려고 합니다.
보통 드랍다운 레이아웃이 필요한 경우에 많이 사용하게 되는데요,
여기서 드랍다운 메뉴란 ↓ 이렇게 생긴 레이아웃 종류입니다!
아래 나와있는 분류대로 순차적으로 알아보도록 하겠습니다!
- 스피너 커스텀 하기
- 스피너에 데이터 추가하기
- 스피너에 가이드 문구 추가하기
1) 스피너 커스텀 하기
우선,스피너의 배경이 될 drawable 파일을 하나 생성해줍니다.
bg_spinner.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="true">
<layer-list>
<item>
<shape>
<solid android:color="@color/white"/>
<stroke android:width="1dp" android:color="@color/light_blue_grey" />
<corners android:radius="15dp" />
<padding android:bottom="15dp" android:left="10dp" android:right="10dp" android:top="15dp" />
</shape>
</item>
<item android:right="5dp">
<bitmap android:gravity="center_vertical|right" android:src="@drawable/ic_arrow_down_yellow" />
</item>
</layer-list>
</item>
<item android:state_enabled="false">
<layer-list>
<item>
<shape>
<solid android:color="@color/pale_grey"/>
<stroke android:width="1dp" android:color="@color/light_blue_grey" />
<corners android:radius="15dp" />
<padding android:bottom="15dp" android:left="10dp" android:right="10dp" android:top="15dp" />
</shape>
</item>
<item android:right="5dp">
<bitmap android:gravity="center_vertical|right" android:src="@drawable/ic_arrow_down" />
</item>
</layer-list>
</item>
</selector>
예시로 사용된 코드는 상단에 기제된 gif내 스피너의 배경입니다. 참고하셔서, 상황에 맞게 사용하시면 됩니다.
이렇게 배경이될 drawable 파일을 생성하셨다면, 다음으로 메뉴에 추가될 아이템을 만들어줍니다.
item_spinner.xml
<TextView
id="@+id/tv_title"
style="@style/Pretend_Medium"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:lineSpacingExtra="6sp"
android:paddingHorizontal="20dp"
android:paddingVertical="16dp"
android:textColor="@color/dark_grey"
android:textSize="15sp"
android:textStyle="normal" />
스피너에서 선택된 아이템의 뷰 입니다.
item_spinner_dropdown.xml
<TextView
id="@+id/tv_title"
style="@style/Pretend_Medium"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:lineSpacingExtra="6sp"
android:paddingHorizontal="20dp"
android:paddingVertical="16dp"
android:textColor="@color/dark_grey"
android:textSize="15sp"
android:textStyle="normal" />
스피너에서 펼쳐진 아이템의 뷰 입니다.
스피너 배경과 메뉴 아이템까지 작성하셨다면, 범용으로 사용할수 있게끔 테마를 추가해줍니다.
themes.xml
<style name="Widget.My.Spinner" parent="Widget.AppCompat.Spinner">
<item name="android:overlapAnchor">false</item>
<item name="overlapAnchor"> false</item>
<item name="android:spinnerMode">dropdown</item>
<item name="android:dropDownWidth">match_parent</item>
<item name="android:background">@drawable/bg_spinner</item>
</style>
- overlapAnchor
- true -> 드랍다운 메뉴의 표시위치가 스피너와 겹쳐질수 있습니다.
- false -> 드랍다운 메뉴가 스피너 아래로 고정됩니다.
- spinnerMode
- dropdown -> 메뉴가 드랍다운 형식으로 표시됩니다.
- dialog -> 메뉴가 팝업형태로 표시됩니다.
- dropDownWidth
- 드랍다운 메뉴의 가로길이를 설정합니다.
스타일까지 작성되었다면, 스피너에 적용해줍니다.
fragment.xml
<Spinner
style="@style/Widget.My.Spinner"
list="@{output.categoryList}"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:padding="0dp" />
저는 databinding을 이용해 리스트를 바로 추가해 주었습니다.
주의할점으론, 예시의 bg_spinner 내부에 padding 값이 포함되었기때문에 spinner에 padding="0dp" 값을 추가해줍니다.
2) 스피너에 데이터 추가하기
스피너에 제공하는 선택 항목은 어떠한 소스에서든 가져올 수 있지만, SpinnerAdapter를 통해 제공되어야 합니다. 예를 들어 선택 항목을 배열에서 사용할 수 있는 경우에는 ArrayAdapter, 선택 항목을 데이터베이스 쿼리에서 사용할 수 있는 경우에는 CursorAdapter를 통해 제공합니다.
출처: https://developer.android.com/guide/topics/ui/controls/spinner?hl=ko
보통의 상황에서는 ArrayAdapter를 통해 스피너에 들어갈 데이터를 전달해 줍니다.
ArrayAdapter 앞 <> 태그로 들어갈 데이터의 변수형을 명명해주는것이 좋습니다.
val adapter = ArrayAdapter<*>(requireContext(), R.layout.item_spinner, R.id.tv_title , listOf<*>())
adapter.setDropDownViewResource(R.layout.item_spinner_dropdown)
(Spinner).adapter = adapter
앞에서 만들어준 item_spinner와 item_spinner_dropdown resource를 연동해 줍니다.
주의하실 점으로는 item_spinner의 textview에 지정해준 id값도 옆에 추가해 줘야합니다
결과 값을 받아서 처리해야 한다면 onItemSelectedListener를 사용하여 callback을 받을수 있습니다
(Spinner).onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onNothingSelected(parent: AdapterView<*>?) {}
override fun onItemSelected(
parent: AdapterView<*>?,
view: View?,
position: Int,
id: Long
) {
// 결과 값의 처리
}
}
3) 스피너에 가이드 문구 추가하기
기본적으로 스피너에는 예시에서 본것처럼의 가이드 문구에 대한 처리를 제공하지 않습니다.
그래서 일부 코드를 추가하여 사용해야 하는데, 제가 알고있는 방식으로는 두가지가 있습니다.
- 데이터 바인딩을 사용, 특정 포지션의 콜백을 비활성화 하여 바인딩 연산자를 이용하는 방법
- CustomArrayAdapter에 ArrayAdapter를 상속받아, 해당 포지션의 뷰를 수정하는 방법.
-> 1번 방식보다 간편하고, DropdownView에 View를 제거해 깔끔한 UI를 보여줄수 있습니다.
해당 포스트 에선 2번 방식에 대해 알아보겠습니다.
BaseArrayAdapter.class
class BaseArrayAdapter<T>(
context: Context
) : ArrayAdapter<T>(context, R.layout.item_spinner, R.id.tv_title, arrayListOf()) {
override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View {
val view = super.getDropDownView(position, convertView, parent)
if (position == 0) {
(view.findViewById<TextView>(R.id.tv_title)).apply {
width = 0
height = 0
}
}
return view
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val view = super.getView(position, convertView, parent)
if(position == 0) {
view.findViewById<TextView>(R.id.tv_title).setTextColor(context.getColor(R.color.key_color))
}
return view
}
fun submitList(list: List<T>?) {
this.clear()
this.addAll(list)
this.notifyDataSetChanged()
}
}
DropdownView -> 아이템을 리턴할떄, 특정 뷰의 포지션을 찾아 보이지 않게 처리하였습니다.
View -> 특정 뷰의 포지션을 찾아 글자색을 변경해줌으로써 hint 효과를 주었습니다.
기본적으로 Spinner의 경우 항상 0번쨰 포지션의 View를 보여주기떄문에, position == 0 의 조건을 걸었습니다.
Fragment.class
val adapter = BaseArrayAdapter(requireContext())
adapter.setDropDownViewResource(R.layout.item_spinner_dropdown)
(Spinner).adapter = adapter
adapter.submitList(listOf("가이드 문구가 0번쨰"))
(Spinner).onItemSelectedListener = object: AdapterView.OnItemSelectedListener {
override fun onItemSelected(
parent: AdapterView<*>?,
view: View?,
position: Int,
id: Long
) {
if (position == 0) return
// 선택되었을떄의 처리
}
override fun onNothingSelected(parent: AdapterView<*>?) {}
}
2번에서 연결한 ArrayAdapter 코드처럼 사용해주시면 됩니다.
주의하실 점으로는 가이드가 될 text는 항상 리스트에 첫번쨰에 위치해야 합니다.
'안드로이드' 카테고리의 다른 글
[안드로이드] Alarm Manager 를 활용한 알람기능 구현 (2) | 2023.10.05 |
---|---|
[안드로이드] Navigation Components 들을 알아보자 (2) | 2022.12.05 |
[안드로이드] CoordinateLayout 을 이용한 활용방법들을 알아보자 (feat. AppBarLayout) (2) | 2022.05.31 |
[안드로이드] 스튜디오 BumbleBee 업데이트 적용 및 기능정의 (0) | 2022.02.09 |
[안드로이드] [디자인] Switch 커스텀 해서 사용하기 (0) | 2022.01.20 |