Spinner
列表选择框控件,可让用户从一组数据中快速选择一个值。默认状态下,列表选择框控件显示其当前所选的值。轻触可显示列表选择框,其中列有所有可用值,用户可从中选择任意一个数据。
列表选择框控件有两种风格的选择模式,通过spinnerMode
属性设置为dropdown
,下拉选择框模式;SpinnerMode
属性设置为dialog
,是在页面中部以对话框形式展示列表。
# 基本属性
android:dropDownHorizontalOffset
:设置下拉列表框的水平偏移距离android:dropDownVerticalOffset
:设置下拉列表框的垂直偏移距离android:dropDownSelector
:下拉列表框被选中时的背景android:dropDownWidth
:设置下拉列表框的宽度android:gravity
:设置里面组件的对其方式android:popupBackground
:设置列表框的背景android:prompt
:设置对话框模式的列表框的提示信息(标题),只能够引用 string.xml 中的资源id,而不能直接设置字符串(在代码中可以设置资源id或者字符串)android:spinnerMode
:列表框的模式,有两个可选值: dialog:对话框风格的窗口 dropdown:下拉菜单风格的窗口(默认)android:entries
:使用数组资源设置列表选择框中的列表选择项目android:overlapAnchor
:dropdown样式情况下,列表框是否覆盖控件显示
# 相关方法
setAdapter
:设置适配器setSelection
:设置当前选中哪项,注意该方法要在 setAdapter 方法之后调用setOnItemSelectedListener
:设置下拉列表的选择监听器,接收 OnItemSelectedListener,onNothingSelected 通知
# 基本使用
基本使用示例,使用最简单的ArrayAdapter显示一行文字选项的列表选择框。
xml布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical">
<!-- 下拉选择样式列表选择框 -->
<Spinner
android:id="@+id/sp_dropdown"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:overlapAnchor="false"
android:spinnerMode="dropdown" />
<!-- 弹窗选择样式列表选择框 -->
<Spinner
android:id="@+id/sp_dialog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:spinnerMode="dialog" />
<!-- 使用entries属性指定资源id对应的列表数据 -->
<Spinner
android:id="@+id/sp_entries"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:entries="@array/sp_data"
android:overlapAnchor="false"
android:spinnerMode="dropdown" />
</LinearLayout>
示例代码:
// 数组数据
String[] data = {"羽毛球", "乒乓球", "橄榄球", "篮球", "排球", "网球", "足球"};
// 数组适配器
ArrayAdapter<String> adapter = new ArrayAdapter<>(this,
android.R.layout.simple_spinner_dropdown_item,
data);
// 下拉列表选择框
Spinner spDropDown = findViewById(R.id.sp_dropdown);
// 设置适配器
spDropDown.setAdapter(adapter);
// 设置选择项为数据项中的第一项
spDropDown.setSelection(0);
// 设置选项监听器,监听选中项
spDropDown.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
Log.i(TAG, "onItemSelected: spDropDown, position = " + position);
Toast.makeText(getApplicationContext(),
"下拉列表选择框:选择了" + data[position],
Toast.LENGTH_SHORT).show();
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
Log.i(TAG, "onItemSelected: spDropDown");
}
});
// 对话弹窗列表选择框
Spinner spDialog = findViewById(R.id.sp_dialog);
// 设置弹窗的提示标题
spDialog.setPrompt("请选择一种感兴趣的球类:");
spDialog.setAdapter(adapter);
spDialog.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
Log.i(TAG, "onItemSelected: spDialog, position = " + position);
Toast.makeText(getApplicationContext(),
"弹窗列表选择框:选择了" + data[position],
Toast.LENGTH_SHORT).show();
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
Log.i(TAG, "onNothingSelected: spDialog");
}
});
// 通过entries属性指定资源id对应的列表数据的列表选择框
Spinner spEntries = findViewById(R.id.sp_entries);
spEntries.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
Log.i(TAG, "onItemSelected: spEntries, position = " + position);
Toast.makeText(getApplicationContext(),
"Entries数据列表选择框:选择了" + data[position],
Toast.LENGTH_SHORT).show();
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
Log.i(TAG, "onNothingSelected: spEntries");
}
});
效果图:
# 自定义
自定义 Item 布局和自定义 BaseAdapter。
- 自定义列表项View布局layout_spinner_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/iv_icon"
android:layout_width="50dp"
android:layout_height="50dp" />
<TextView
android:id="@+id/tv_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:paddingStart="10dp"
android:paddingEnd="20dp"
android:textSize="22sp" />
</LinearLayout>
- xml布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical">
<!-- 下拉选择样式列表选择框 -->
<Spinner
android:id="@+id/sp_dropdown"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:overlapAnchor="false"
android:spinnerMode="dropdown" />
<!-- 弹窗选择样式列表选择框 -->
<Spinner
android:id="@+id/sp_dialog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:spinnerMode="dialog" />
</LinearLayout>
- 自定义适配器 CustomAdapter
/**
* 自定义适配器,继承自BaseAdapter,实现其必要的适配方案.
*/
public class CustomAdapter extends BaseAdapter {
private String[] data;
public CustomAdapter(String[] data) {
// 初始化数据
this.data = data;
}
@Override
public int getCount() {
// 实现获取item数量
return data == null ? 0 : data.length;
}
@Override
public String getItem(int position) {
// 实现获取指定位置的Item数据
return data == null ? null : data[position];
}
@Override
public long getItemId(int position) {
// 实现获取指定位置的ItemId,一般返回其位置,也可以根据需要实现
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// 实现获取指定位置的View对象
View view = LayoutInflater
.from(parent.getContext())
.inflate(R.layout.layout_spinner_item, parent, false);
ImageView ivIcon = view.findViewById(R.id.iv_icon);
TextView tvContent = view.findViewById(R.id.tv_content);
if (position % 2 == 0) {
ivIcon.setBackgroundResource(R.drawable.rating_off);
} else {
ivIcon.setBackgroundResource(R.drawable.rating_on);
}
tvContent.setText(getItem(position));
return view;
}
}
- 示例代码
// 数据列表
String[] data = {"羽毛球", "乒乓球", "橄榄球", "篮球", "排球", "网球", "足球"};
// 自定义适配器
CustomAdapter customAdapter = new CustomAdapter(data);
// 下拉列表选择框
Spinner spDropDown = findViewById(R.id.sp_dropdown);
// 设置自定义适配器
spDropDown.setAdapter(customAdapter);
// 设置选择项为数据项中的第一项
spDropDown.setSelection(0);
spDropDown.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
Log.i(TAG, "onItemSelected: spDropDown, position = " + position);
Toast.makeText(getApplicationContext(),
"下拉列表选择框:选择了" + data[position],
Toast.LENGTH_SHORT).show();
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
Log.i(TAG, "onItemSelected: spDropDown");
}
});
// 对话弹窗列表选择框
Spinner spDialog = findViewById(R.id.sp_dialog);
// 设置弹窗的提示标题
spDialog.setPrompt("请选择一种感兴趣的球类:");
spDialog.setAdapter(customAdapter);
spDialog.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
Log.i(TAG, "onItemSelected: spDialog, position = " + position);
Toast.makeText(getApplicationContext(),
"弹窗列表选择框:选择了" + data[position],
Toast.LENGTH_SHORT).show();
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
Log.i(TAG, "onNothingSelected: spDialog");
}
});
- 效果图
提示:
ArrayAdapter 也可以实现自定义布局,但是只能绑定单个布局中的 TextView 文本控件进行文本的适配绑定。如果有多个元素的控件则无法进行默认适配,需要自定义 BaseAdapter 来实现。
ArrayAdapter(@NonNull Context context, @LayoutRes int resource,
@IdRes int textViewResourceId, @NonNull List<T> objects)
resource
:自定义布局的资源idtextViewResourceId
:自定义布局中需要绑定数据的文本控件objects
:数据
如上面自定义示例只绑定文本,则可以这样使用:
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(getApplicationContext(),
R.layout.layout_spinner_item, // 自定义布局
R.id.tv_content, // 自定义自定义布局中需要绑定数据的TextView的Id
data); // 数据列表
spDropDown.setAdapter(arrayAdapter);
# 结束
本节介绍了 Android 中默认的列表选择控件(Spinner)常用属性以及相关使用方法,自定义实现的布局和适配器的方法,更多属性和用法请参考:Spinner (opens new window)。