[Android/Kotlin] 안드로이드 Spinner 커스텀 해보기(3) feat. Drop Down Menu
2021/01/30 - [Android/Material Design] - [Android/Kotlin] 안드로이드 Spinner 커스텀 해보기 (1)
2021/01/30 - [Android/Material Design] - [Android/Kotlin] 안드로이드 Spinner 커스텀 해보기(2) feat. Hint 만들기
안녕하세요.
이번시간에는 Spinner 위젯 사용시 Drop Down Menu도 커스텀 하는 방법에 대해서 알아보겠습니다.
커스텀 하기 이전에는 보통 텍스값을 많이 사용합니다.
이번에는 이미지와 텍스트값이 같이 나타나도록 해보겠습니다.
완성된 모습은 아래와 같습니다.
이전 Spinner 구현 코드에서 이어서 해보겠습니다.
필요하신 분들은 이전 블로그 글을 참고부탁드립니다.
STEP01. Item Layout 만들기
아래와 같이 왼쪽에 이미지 오른쪽에 텍스트를 나타내는 레이아웃을 하나 만들어 줍니다.
[item_spinner.xml]
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:tools="http://schemas.android.com/tools"
android:padding="8dp"
xmlns:app="http://schemas.android.com/apk/res-auto">
<ImageView
android:id="@+id/img_spinner"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginStart="8dp"
android:src="@drawable/ic_calendar"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:contentDescription="@string/app_name" />
<TextView
android:id="@+id/txt_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintStart_toEndOf="@+id/img_spinner"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
tools:text="2021"/>
</androidx.constraintlayout.widget.ConstraintLayout>
STEP02. Model 클래스 만들기
이미지와 텍스트를 저장할 데이터 클래스를 만들어줍니다.
[SpinnerModel.kt]
data class SpinnerModel(
val image: Int,
val name: String,
)
STEP03. 커스텀을 위한 Adapter 클래스 만들기
Spinner item을 커스텀하기 위해서 ArrayAdapter를 상속받는 Adapter 클래스를 하나 만들어 줍니다.
클래스 생성시 리스트를 넘겨받고 사용합니다. getView() 메소드에서는 눈에 보여지는 Spinner 모습을, 그리고 getDropDownView() 메소드에서는 메뉴가 나타났을 때 모습을 수정해 줍니다.
[SpinnerAdapter.kt]
class SpinnerAdapter(
context: Context,
@LayoutRes private val resId: Int,
private val values: MutableList<SpinnerModel>
) : ArrayAdapter<SpinnerModel>(context, resId, values) {
override fun getCount() = values.size
override fun getItem(position: Int) = values[position]
@SuppressLint("ViewHolder")
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val binding = ItemSpinnerBinding.inflate(LayoutInflater.from(parent.context), parent, false)
val model = values[position]
try {
binding.imgSpinner.setImageResource(model.image)
binding.imgSpinner.setColorFilter(ContextCompat.getColor(context, R.color.white))
binding.txtName.text = model.name
binding.txtName.setTextColor(ContextCompat.getColor(context, R.color.white))
} catch (e: Exception) {
e.printStackTrace()
}
return binding.root
}
override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View {
val binding = ItemSpinnerBinding.inflate(LayoutInflater.from(parent.context), parent, false)
val model = values[position]
try {
binding.imgSpinner.setImageResource(model.image)
binding.txtName.text = model.name
} catch (e: Exception) {
e.printStackTrace()
}
return binding.root
}
}
STEP03. MainActivity에서 적용하기
listOfYear와 listOfMonth를 만들어 넘겨줄 SpinnerModel 리스트를 만들어 줍니다.
기존 어댑터를 삭제해 주시고, 새롭게 정의한 SpinnerAdapter를 생성하여 setAdapter()에 넣어주시면 됩니다.
[MainActivity.kt]
class MainActivity : AppCompatActivity() {
private var _binding: ActivityMainBinding? = null
private val binding get() = _binding!!
private lateinit var spinnerAdapterYear: SpinnerAdapter
private lateinit var spinnerAdapterMonth: SpinnerAdapter
private val listOfYear = ArrayList<SpinnerModel>()
private val listOfMonth = ArrayList<SpinnerModel>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
_binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
setupSpinnerYear()
setupSpinnerMonth()
setupSpinnerHandler()
}
private fun setupSpinnerYear() {
val years = resources.getStringArray(R.array.spinner_year)
for (i in years.indices) {
val year = SpinnerModel(R.drawable.ic_calendar, years[i])
listOfYear.add(year)
}
spinnerAdapterYear = SpinnerAdapter(this, R.layout.item_spinner, listOfYear)
binding.spinnerYear.adapter = spinnerAdapterYear
}
private fun setupSpinnerMonth() {
val monthsContainHint = mutableListOf("월")
val months = DateFormatSymbols().months
monthsContainHint.addAll(months)
for (i in monthsContainHint.indices) {
val month = SpinnerModel(R.drawable.ic_bedtime, monthsContainHint[i])
listOfMonth.add(month)
}
spinnerAdapterMonth = SpinnerAdapter(this, R.layout.item_spinner, listOfMonth)
binding.spinnerMonth.adapter = spinnerAdapterMonth
}
private fun setupSpinnerHandler() {
binding.spinnerYear.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
val year = binding.spinnerYear.getItemAtPosition(position) as SpinnerModel
if (!year.name.equals("연도")) {
binding.txtYear.text = "Selected: ${year.name}"
}
}
override fun onNothingSelected(p0: AdapterView<*>?) {
}
}
binding.spinnerMonth.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
val month = binding.spinnerMonth.getItemAtPosition(position) as SpinnerModel
if (!month.name.equals("월")) {
binding.txtMonth.text = "Selected: ${month.name}"
}
}
override fun onNothingSelected(p0: AdapterView<*>?) {
}
}
}
override fun onDestroy() {
super.onDestroy()
_binding = null
}
}
'기리's Android 이야기' 카테고리의 다른 글
[Android/Kotlin] 안드로이드 Section(Group) RecyclerView 만들기 (1) | 2021.01.31 |
---|---|
[Android/Kotlin] 안드로이드 Room Database 사용하기(1) (1) | 2021.01.30 |
[Android/Kotlin] 안드로이드 Spinner 커스텀 해보기(2) feat. Hint 만들기 (0) | 2021.01.30 |
[Android/Kotlin] 안드로이드 Spinner 커스텀 해보기(1) (3) | 2021.01.30 |
[Android Studio/Kotlin] 안드로이드 Live Template 사용하기 (2) | 2021.01.26 |
댓글