ホーム
2022.9.26

kotlin スピナーをIDでコントロールする

スピナー選択時に、選択されたアイテムのテキストだけでなくIDも取り扱いたい。
また、IDからスピナーポジションを判断して任意のスピナーアイテムを選択したい。
今回の方法はBaseAdapterを継承したMySpinnerAdapterを作成し、
spinnerのadapterとしました。
IdとNameを属性としたdata class MySpinnerDataも作成しています。
スピナーで選択したアイテムはMySpinnerDataの形で返ってくるため
選択されたアイテムを様々な様式で取得するとこができます。

MySpinnerData.kt

package com.example.samplespinner

data class MySpinnerData(
val id: Int,
var name: String
)

MySpinnerAdapter.kt

package com.example.samplespinner

import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import com.example.samplespinner.databinding.ItemMySpinnerBinding

class MySpinnerAdapter(
private val context: Context,
private val spinnerItems: MutableList<MySpinnerData>
) : BaseAdapter() // *1
{
class ViewHolder(view: View) {
private val binding = ItemMySpinnerBinding.bind(view)
private val txvItem = binding.txvItem

fun bindItem(mySpinnerData: MySpinnerData) {
txvItem.text = mySpinnerData.name
}
}

private val positionById = mutableMapOf<Int, Int>() // *2
init {
var i = 0
for (elm in spinnerItems) {
positionById[elm.id] = i++
}
}

override fun getCount(): Int {
return spinnerItems.size
}

override fun getItem(position: Int): Any { // *3
return spinnerItems[position]
}

override fun getItemId(position: Int): Long { // *4
return spinnerItems[position].id.toLong()
}

override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
return if(convertView == null) {
val view = LayoutInflater.from(context)
.inflate(R.layout.item_my_spinner, parent, false)
val viewHolder = ViewHolder(view)
viewHolder.bindItem(spinnerItems[position])
view.tag = viewHolder
view
} else {
val viewHolder = convertView.tag as ViewHolder
viewHolder.bindItem(spinnerItems[position])
convertView
}
}

fun getPositionById(id: Int): Int? { // *5
return positionById[id]
}
}
  1. BaseAdapter()を継承ます。
  2. Idをキーとして、PositionをバリューとしたMapを定義しています。
    getPositionById()メソッドで使用しています。
  3. selectedItemが呼ばれたときに返す値を定義します。
    data class MySpinnerData型で返しています。
  4. selectedItemIdが呼ばれたときに返す値を定義します。
    今回のサンプルでは使用していません。
  5. idからPositionを返す関数です。
    スピナーアイテムを設定するときのsetSelection(position)で使用したいため作成しました。

MainActivity.kt

package com.example.samplespinner

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.AdapterView
import com.example.samplespinner.databinding.ActivityMainBinding
import java.util.*

class MainActivity : AppCompatActivity(), AdapterView.OnItemSelectedListener {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)

// init spinner items *1
val mySpinnerItems = mutableListOf<MySpinnerData>()
mySpinnerItems.add(MySpinnerData(Calendar.MONDAY, getString(R.string.monday)))
mySpinnerItems.add(MySpinnerData(Calendar.TUESDAY, getString(R.string.tuesday)))
mySpinnerItems.add(MySpinnerData(Calendar.WEDNESDAY, getString(R.string.wednesday)))
mySpinnerItems.add(MySpinnerData(Calendar.THURSDAY, getString(R.string.thursday)))
mySpinnerItems.add(MySpinnerData(Calendar.FRIDAY, getString(R.string.friday)))
mySpinnerItems.add(MySpinnerData(Calendar.SATURDAY, getString(R.string.saturday)))
mySpinnerItems.add(MySpinnerData(Calendar.SUNDAY, getString(R.string.sunday)))
val adapter = MySpinnerAdapter(
this,
mySpinnerItems
)
binding.spnSample.adapter = adapter
binding.spnSample.onItemSelectedListener = this

// How to select spinner item. *2
val position = adapter.getPositionById(Calendar.WEDNESDAY)
if (position != null)
binding.spnSample.setSelection(position)
}

override fun onItemSelected(parent: AdapterView<*>?, view: View?, pos: Int, id: Long) {
when (parent) {
binding.spnSample -> {
val selectedItem = parent.selectedItem as MySpinnerData
var str = "spinner clicked."
str += "\npos:$pos"
str += "\nid:" + selectedItem.id.toString() // *3
str += "\nname:" + selectedItem.name // *3
binding.txvSample.text = str
}
}
}

override fun onNothingSelected(p0: AdapterView<*>?) {
// do nothing.
}
}
  1. スピナーを設定します。
  2. スピナーアイテムを指定しています。idからpositionを判断してsetSelectionで指定しています。
  3. selectedItemがMySpinnerData型なのでid属性とname属性が参照できます。

item_my_spinner.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<TextView
android:id="@+id/txvItem"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

strings.xml

<resources>
<string name="app_name">SampleSpinner</string>

<string name="sunday"></string>
<string name="monday"></string>
<string name="tuesday"></string>
<string name="wednesday"></string>
<string name="thursday"></string>
<string name="friday"></string>
<string name="saturday"></string>

</resources>
ホーム