頁面包含一組 RadioGroup(兩個 RadioButton)與一個 Spinner。根據用戶選擇的單選按鈕,Spinner 需動態載入不同的字串陣列資源(name_array 或 type_array)。核心邏輯在於:更換 Adapter 的資料集並通知更新。
<resources>
<string-array name="name_array">
<item>Alice</item>
<item>Bob</item>
<item>Charlie</item>
</string-array>
<string-array name="type_array">
<item>Type A</item>
<item>Type B</item>
<item>Type C</item>
<item>Type D</item>
</string-array>
</resources>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">
<RadioGroup
android:id="@+id/rg_source"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<RadioButton
android:id="@+id/rb_names"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="人名"
android:checked="true" />
<RadioButton
android:id="@+id/rb_types"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="類型" />
</RadioGroup>
<Spinner
android:id="@+id/spinner_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp" />
</LinearLayout>
class SpinnerDemoActivity : AppCompatActivity() {
private lateinit var spinner: Spinner
private lateinit var adapter: ArrayAdapter<String>
private val nameArray by lazy { resources.getStringArray(R.array.name_array).toList() }
private val typeArray by lazy { resources.getStringArray(R.array.type_array).toList() }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_spinner_demo)
spinner = findViewById(R.id.spinner_data)
val rgSource = findViewById<RadioGroup>(R.id.rg_source)
// 初始化 Adapter,預設顯示 name_array
adapter = ArrayAdapter(this, android.R.layout.simple_spinner_item, nameArray)
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
spinner.adapter = adapter
rgSource.setOnCheckedChangeListener { _, checkedId ->
when (checkedId) {
R.id.rb_names -> swapData(nameArray)
R.id.rb_types -> swapData(typeArray)
}
}
}
private fun swapData(newData: List<String>) {
adapter.clear()
adapter.addAll(newData)
adapter.notifyDataSetChanged() // 關鍵:通知 Spinner 重繪
}
}
public class SpinnerDemoActivity extends AppCompatActivity {
private Spinner spinner;
private ArrayAdapter<String> adapter;
private List<String> nameList, typeList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_spinner_demo);
spinner = findViewById(R.id.spinner_data);
RadioGroup rgSource = findViewById(R.id.rg_source);
nameList = Arrays.asList(getResources().getStringArray(R.array.name_array));
typeList = Arrays.asList(getResources().getStringArray(R.array.type_array));
adapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, nameList);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
rgSource.setOnCheckedChangeListener((group, checkedId) -> {
if (checkedId == R.id.rb_names) swapData(nameList);
else if (checkedId == R.id.rb_types) swapData(typeList);
});
}
private void swapData(List<String> newData) {
adapter.clear();
adapter.addAll(newData);
adapter.notifyDataSetChanged();
}
}
clear() + addAll() + notifyDataSetChanged(),效能更好、選中狀態保持更自然。Arrays.asList() 或 Kotlin .toList() 方便增刪改,ArrayAdapter 內部支援 List 操作。android:checked="true" 確保啟動時有確定資料源。若資料非靜態資源,而是異步獲取,邏輯同樣適用:
// 協程異步獲取後
viewModel.getNames().observe(this, names -> {
if (rbNames.isChecked) swapData(names); // 只有當前選中該源才更新
});
viewModel.getTypes().observe(this, types -> {
if (rbTypes.isChecked) swapData(types);
});
new ArrayAdapter() → 導致 Spinner 閃爍、選中位置重置。notifyDataSetChanged() → UI 不更新。OnCheckedChangeListener 中直接操作 spinner.setAdapter() → 同樣會重置狀態。Spinner 動態切換資料源的核心是 複用 Adapter 實例、操作其內部資料集、調用 notifyDataSetChanged()。配合 RadioGroup 統一監聽,代碼清晰且效能最優。此模式同樣適用於 ListView、RecyclerView 等 AdapterView 組件。