Spinner(下拉列表)提供了从一个数据集合中快速选择一项值的办法。

默认情况下Spinner显示的是当前选择的值,点击Spinner会弹出一个包含所有可选值的下拉菜单,从该菜单中可以为Spinner选择一个新值。

下拉列表的展示方式有两种:

一种是在当前下拉框的正下方展示列表,此时把spinnerMode属性设置为 dropdown

另一种是在页面中部以对话框形式展示列表,此时把SpinnerMode属性设置为 dialog

一、最简单的Spinner

首先新建一个SpinnerTest项目,并让Android Studio自动创建活动。

在布局文件中添加Spinner控件,修改activity_main.xml中的代码,如下所示:

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

1、通过 android:entries 属性添加数据

首先,修改strings.xml字符串资源文件,使用<string-array>元素来包含一些<item>子元素,用于定义生肖名称。代码如下:

<resources>
    <string-array name="list_animals">
        <item>子鼠</item>
        <item>丑牛</item>
        <item>寅虎</item>
        <item>卯兔</item>
        <item>辰龙</item>
        <item>巳蛇</item>
    </string-array>
</resources>

在字符串资源文件中,增加<string-array>节点,定义name为list_animals,在该节点下增加<item>项目节点。

然后,修改Spinner控件,增加android:entries属性,属性值为@array/list_animals:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">
    <Spinner
        android:id="@+id/spAnimals"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:entries="@array/list_animals" />
</LinearLayout>

运行程序,效果如图显示:

2、通过适配器添加数据

首先,删除Spinner控件中的android:entries属性,再修改MainActivity中的代码,如下所示:

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
    private String[] animals = {"子鼠", "丑牛", "寅虎", "卯兔", "辰龙", "巳蛇", "午马", "未羊", "申猴", "酉鸡", "戌狗", "亥猪"};
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //声明一个下拉列表的数组适配器
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, animals);
        //从布局文件中获取名叫spAnimals的下拉框
        Spinner spAnimals = findViewById(R.id.spAnimals);
        //设置下拉框的数组适配器
        spAnimals.setAdapter(adapter);

这里使用的还是ArrayAdapter,和ListView用的ArrayAdapter一样。这里由于我们提供的数据都是字符串,因此将ArrayAdapter的泛型指定为String。

然后在ArrayAdapter的构造方法中依次传入当前上下文Spinner子项布局的id,以及要适配的数据。

这里的Spinner子项布局的id是android.R.layout.simple_spinner_item(列表-间距紧凑不好看)。

内置的布局样式还有:

  • android.R.layout.simple_spinner_dropdown_item:列表-间距较高比较好看
  • android.R.layout.simple_list_item_single_choice:单选按钮
  • android.R.layout.simple_list_item_checked:复选框-选中的有绿勾
  • android.R.layout.simple_spinner_item                android.R.layout.simple_spinner_dropdown_item

    注意:ArrayAdapter构造方法的第2个参数是指”未展开“时的布局样式,
    我们可以通过setDropDownViewResource()方法来指定”展开“时的布局样式。
    import androidx.appcompat.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.AdapterView;
    import android.widget.ArrayAdapter;
    import android.widget.Spinner;
    import android.widget.Toast;
    public class MainActivity extends AppCompatActivity {
        private String[] animals = {"子鼠", "丑牛", "寅虎", "卯兔", "辰龙", "巳蛇", "午马", "未羊", "申猴", "酉鸡", "戌狗", "亥猪"};
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            //声明一个下拉列表的数组适配器
            ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_dropdown_item, animals);
            // 设置下拉菜单展开时的样式
            adapter.setDropDownViewResource(android.R.layout.simple_list_item_checked);
            //从布局文件中获取名叫spAnimals的下拉框
            Spinner spAnimals = findViewById(R.id.spAnimals);
            //设置下拉框的数组适配器
            spAnimals.setAdapter(adapter);
    

    二、定制Spinner的界面

    1、定制”未展开“和”展开“的样式

    未展开样式item_select.xml

    <?xml version="1.0" encoding="utf-8"?>
    <TextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="45dp"
        android:background="@android:color/holo_blue_dark"
        android:gravity="center"
        android:textColor="@android:color/holo_red_light"
        android:textSize="14sp" />

    展开样式item_dropdown.xml

    <?xml version="1.0" encoding="utf-8"?>
    <TextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="45dp"
        android:gravity="center"
        android:textColor="@android:color/black"
        android:textSize="14sp" />

    修改布局文件activity_main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".MainActivity">
        <Spinner
            android:id="@+id/spAnimals"
            android:layout_width="200dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:background="@null"
            android:dropDownVerticalOffset="45dp"
            android:spinnerMode="dropdown" />
    </LinearLayout>

    修改MainActivity.java

    import androidx.appcompat.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.AdapterView;
    import android.widget.ArrayAdapter;
    import android.widget.Spinner;
    import android.widget.Toast;
    public class MainActivity extends AppCompatActivity {
        private String[] animals = {"子鼠", "丑牛", "寅虎", "卯兔", "辰龙", "巳蛇", "午马", "未羊", "申猴", "酉鸡", "戌狗", "亥猪"};
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            //声明一个下拉列表的数组适配器
            ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.item_select, animals);
            // 设置下拉菜单展开时的样式
            adapter.setDropDownViewResource(R.layout.item_dropdown);
            //从布局文件中获取名叫spAnimals的下拉框
            Spinner spAnimals = findViewById(R.id.spAnimals);
            //设置下拉框的数组适配器
            spAnimals.setAdapter(adapter);
    

    运行效果:

    2、Spinner的其他方法

    (1)设置下拉框的标题。

    只在dialog样式中显示,android:spinnerMode="dialog",如左图;不在dropdown样式下显示,android:spinnerMode="dropdown",如右图。

  • setPrompt(CharSequence prompt):参数为字符串
  • setPromptId(int promptId):参数为字符串的ID,如R.string.xxxx
  • (2)设置下拉框默认的显示第n项,注意该方法要在setAdapter()方法之后调用

  • setSelection(int position):
  • setSelectionInt(int position, boolean animate) :
  • 3、dropdown模式下的列表分割线

    在下图①中的位置添加自己的style,在②处进行使用。themes.xml文件可能会提示错误,可能是Android Studio语法检查误判,关闭再打开就好了。

    在style中添加如下代码即可,打开themes.xml文件。

    添加样式:

    <style name="XSpinnerStyle" parent="android:Widget.ListView.DropDown">
        <!-- 分隔线颜色 -->
        <item name="android:divider">#3F51B5</item>
        <item name="android:dividerHeight">1dp</item>
    </style>

    然后在AppTheme中调用:

    <item name="android:dropDownListViewStyle">@style/XSpinnerStyle</item>

    但注意,该分割线只有是dropdown样式时才会显示。运行结果:

    三、实现选择项事件

    调用setOnItemSelectedListener()方法来为Spinner绑定AdapterView.OnItemSelectedListener事件监听器,可以使用匿名类实现接口的方式。

    import androidx.appcompat.app.AppCompatActivity;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.widget.AdapterView;
    import android.widget.ArrayAdapter;
    import android.widget.Button;
    import android.widget.Spinner;
    import android.widget.TextView;
    import android.widget.Toast;
    import java.util.ArrayList;
    import java.util.List;
    public class MainActivity extends AppCompatActivity {
        private String[] animals = {"子鼠", "丑牛", "寅虎", "卯兔", "辰龙", "巳蛇", "午马", "未羊", "申猴", "酉鸡", "戌狗", "亥猪"};
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            //声明一个下拉列表的数组适配器
            ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.item_select, animals);
            // 设置下拉菜单展开时的样式
            adapter.setDropDownViewResource(R.layout.item_dropdown);
            //从布局文件中获取名叫spAnimals的下拉框
            Spinner spAnimals = findViewById(R.id.spAnimals);
            //设置下拉框的标题。只在dialog样式中显示,android:spinnerMode="dialog";不在dropdown样式下显示,android:spinnerMode="dropdown"。
            spAnimals.setPrompt("请选择你的生肖"); // 参数为字符串
    //        spAnimals.setPromptId(R.string.app_name); // 参数为字符串的ID,如R.string.xxxx
            //设置下拉框的数组适配器
            spAnimals.setAdapter(adapter);
            //设置下拉框默认的显示第一项,注意,该方法要在setAdapter()方法之后调用
            spAnimals.setSelection(1, true);
            //给下拉框设置选择监听器,一旦用户选中某一项,就触发监听器的onItemSelected方法
            spAnimals.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
                @Override
                public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                    // parent:为Spinner控件;view:显示文字的TextView;position:下拉选项的位置从0开始
                    Toast.makeText(MainActivity.this, "您选择的是:" + animals[position], Toast.LENGTH_SHORT).show();
                @Override
                public void onNothingSelected(AdapterView<?> parent) {
    

    运行结果: