如何使用Spinner(kotlin)

如何使用Spinner(kotlin)

情境

如果你想要從一個集合內選出一個值,Spinner 是一個很好用的工具,它會提供一個下拉式選單, 顯示清單內所有的值讓使用者選擇。
例如:
午餐吃什麼?
有[雞腿飯、魯肉飯、排骨飯、水餃、陽春麵]這些選項提供使用者選擇,但是使用者只能選一個選項,這樣就是一個Spinner的應用了。

完整程式碼

如果需要參考完整程式碼,可以到以下網址參考。

GitHub

程式碼 + 說明

建立一個Spinner有幾種方式。

方法一

你可以從程式碼內部直接建立,不需要在 XML 建立任何元件。

注意如果一開始你新建一個專案,記得將 xml內預設的TextView元件刪除,不然會出現TextView的Hello World。

下面的程式碼直接貼到 MainActivity.java 資料夾就可以執行了。

val spinner = Spinner(this)  
container.addView(spinner)

container 是最外圍的 RelativeLayout,記得在 xml 上給它一個命名。
呈現效果如下圖。


你會發現只有一個向下的箭頭,原因是目前Spinner沒有任何清單集合的值,稍後我們會說明如何將值填入。
而對於程式碼建構元件是比較不推薦使用的方式,原因是從程式碼建構元件,當元件一多,會造成之後程式碼維護的困難度增加以及可讀性降低,比較好的方式是在XML上面進行宣告,所以後面的都會以方法二來進行編譯。

方法二

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin">
    <Spinner
  android:id="@+id/spinner"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</RelativeLayout>

如下圖跟用程式宣告的效果是一樣的。


加入資料

前面提到 Spinner 需要加入資料才能跳出下拉式選單,在 Spinner 加入的資料的方法很多種。

加入資料 - 方法一

先在 res/strings 內加入一段程式碼。

<resources>
    <string name="app_name">SpinnerDemo</string>
    <string-array name="lunch">
        <item>雞腿飯</item>
        <item>魯肉飯</item>
        <item>排骨飯</item>
        <item>水餃</item>
        <item>陽春麵</item>
    </string-array>
</resources>

在 main_activity.xml 中加入 Spinner 元件的宣告。

<?xml version="1.0" encoding="utf-8"?>  
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
 xmlns:tools="http://schemas.android.com/tools"  
 android:id="@+id/container"  
 android:layout_width="match_parent"  
 android:layout_height="match_parent"  
 tools:context=".MainActivity">  
  <Spinner  android:id="@+id/spinner"  
  android:layout_width="wrap_content"  
  android:layout_height="wrap_content" />  
</RelativeLayout>

接著透過 ArrayAdapter.createFromResource 的靜態方法取得我們的字串表,這邊 simple_spinner_dropdown_item 是 Android 所提供的布局方式,還有其他的布局可以選擇,例如 simple_dropdown_item_1line 等等, 有興趣可以玩看看。
以下有個表可以使用各種的樣式。
https://developer.android.com/reference/android/R.layout.html#simple_spinner_dropdown_item

val adapter = ArrayAdapter.createFromResource(this, R.array.lunch, android.R.layout.simple_spinner_dropdown_item)  
spinner.adapter = adapter

轉換成下拉式選單。


下拉後出現資料列表

加入資料 - 方法二

除了可以直接透過 strings.xml 的字串表轉換以外,也可以透過程式直接加入。
透過自己所建立的字串 lunch,再利用 Android 內建的 ArrayAdapter 的方式,把程式內建立的字串塞進去,選擇好布局模式,就可以設定完成。

val lunch = arrayListOf("雞腿飯", "魯肉飯", "排骨飯", "水餃", "陽春麵")  
val adapter = ArrayAdapter(this, android.R.layout.simple_spinner_dropdown_item, lunch)  
spinner.adapter = adapter

這樣你就會看到這樣的畫面, 跟前面使用字串陣列表的呈現方式一樣。


下拉後出現資料列表

處理事件

如果要加入事件,會透過 Spinner 本身所提供,setOnItemSelectedListener 的方式來使用,注意:這邊不能使用 OnItemClickListener 否則會閃退

val lunch = arrayListOf("雞腿飯", "魯肉飯", "排骨飯", "水餃", "陽春麵")  
val adapter = ArrayAdapter(this, android.R.layout.simple_spinner_dropdown_item, lunch)  
spinner.adapter = adapter  
spinner.onItemSelectedListener = object: AdapterView.OnItemSelectedListener {  
    override fun onItemSelected(parent: AdapterView<*>, view: View, pos: Int, id: Long) =  
        Toast.makeText(this@MainActivity, "你選的是" + lunch[pos], Toast.LENGTH_SHORT).show()  
  
    override fun onNothingSelected(parent: AdapterView<*>) {}  
}

在 onItemSelected 事件中所代表的是當使用者按下 Spinner 的某個 item
該怎麼處理它們,這邊我們加入的一個提示訊息 Toast,它會在下方彈出一個小小的提示訊息, 並且在某段時間後就消失,如下圖所示。


下拉後出現資料列表。


如此一來就完成一個簡易的 Spinner 實作了。