Android中Spinner組件的使用解析
1,Spinner概述
Spinner是ViewGroup類得一個子孫類,其繼承關系如下:
View--->ViewGroup--->AdapterView--->AbsSpinner--->Spinner
默認情況下Spinner顯示的是當前選中的元素值,當每次點擊Spinner時,都會彈出菜單列表供用戶選擇,從該菜單列表中可以為Spinner選擇一個新的元素值.
2,Spinner的簡單用法
在activity_spinner_demo1.xml中添加Spinner控件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Spinner
android:id="@+id/spinner1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:entries="@array/languages" />
</LinearLayout>
其中android:entries="@array/languages"表示Spinner的數據集合是從資源數組languages中獲取的,languages數組資源定義在values/arrays.xml中:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="languages">
<item>c語言</item>
<item>java </item>
<item>php</item>
<item>xml</item>
<item>html</item>
</string-array>
</resources>
SpinnerDemo1Activity中通過OnItemSelectedListener的回調方法實現(xiàn)響應Spinner選擇事件:
/*
布局中獲取數據源
*/
public class SpinnerDemo1Activity extends AppCompatActivity {
protected Spinner spinner1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_spinner_demo1);
initView();
}
private void initView() {
//布局中獲取數據源
spinner1 = (Spinner) findViewById(R.id.spinner1);
spinner1.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
String[] array = getResources().getStringArray(R.array.languages);
Toast.makeText(SpinnerDemo1Activity.this, "選擇了" + array[position], Toast.LENGTH_LONG).show();
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
}
運行結果如下圖所示:


3,通過適配器的方式獲取數據集合
使用這種方式來獲取數據源,就不要在activity_spinner_demo2.xml布局中設置 android:entries="@array/languages" 屬性了:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Spinner
android:id="@+id/spinner2"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:dropDownWidth="60dp"
android:gravity="center"
android:padding="10dp"
android:spinnerMode="dropdown" />
</LinearLayout>
這里我們使用的適配器為ArrayAdapter,SpinnerDemo2Activity代碼如下
//實例化控件
spinner2 = (Spinner) findViewById(R.id.spinner2);
//創(chuàng)建數據適配器并綁定數據
final ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this, R.array.languages, android.R.layout.simple_spinner_item);
spinner2.setAdapter(adapter);
spinner2.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
CharSequence item = adapter.getItem(position);
Toast.makeText(MainActivity.this, "---->" + item, Toast.LENGTH_SHORT).show();
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
4,使用自定義的BaseAdapter獲取數據集合
這種情況適用于Spinner的選擇條目比較復雜的情況,比如帶有圖標.
首先activity_spinner_mode_dropdown.xml布局放置控件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Spinner
android:dropDownVerticalOffset="40dp"
android:dropDownHorizontalOffset="10dp"
android:spinnerMode="dropdown"
android:id="@+id/spinner3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:dropDownWidth="wrap_content"
android:gravity="center"
android:padding="10dp"
/>
</LinearLayout>
SpinnerDemo3Activity中:
public class SpinnerDemo3Activity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
int mode = getIntent().getIntExtra("mode", Spinner.MODE_DROPDOWN);
if (mode == Spinner.MODE_DROPDOWN) {
setContentView(R.layout.activity_spinner_mode_dropdown);
} else {
setContentView(R.layout.activity_spinner_mode_dialog);
}
//使用自定義的BaseAdapter
Spinner spinner3 = (Spinner) findViewById(R.id.spinner3);
final List<Person> persons = new ArrayList<Person>();
persons.add(new Person("張三", "上海 "));
persons.add(new Person("李四", "上海 "));
persons.add(new Person("王五", "北京"));
persons.add(new Person("趙六", "廣州 "));
// 建立Adapter綁定數據源
MyAdapter pAdapter = new MyAdapter(this, persons);
spinner3.setAdapter(pAdapter);
spinner3.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(SpinnerDemo3Activity.this, "--->" + persons.get(position).getName() + "--" + persons.get(position).getCity(), Toast.LENGTH_SHORT).show();
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
}
實體對象Person:
public class Person {
private String name;
private String city;
public Person() {
}
public Person(String name,String city) {
super();
this.name = name;
this.city = city;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
}
MyAdapter:
public class MyAdapter extends BaseAdapter {
private List<Person> mPersons;
public MyAdapter(Context context, List<Person> persons) {
mPersons = persons;
}
@Override
public int getCount() {
return mPersons == null ? 0 : mPersons.size();
}
@Override
public Object getItem(int position) {
return mPersons.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
ViewHolder viewHolder = null;
if (convertView == null) {
convertView = layoutInflater.inflate(R.layout.item_spinner_person, null);
viewHolder = new ViewHolder(convertView);
convertView.setTag(viewHolder);
}else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.tvName.setText(mPersons.get(position).getName());
viewHolder.tvCity.setText(mPersons.get(position).getCity());
return convertView;
}
static class ViewHolder {
protected TextView tvName;
protected TextView tvCity;
ViewHolder(View rootView) {
initView(rootView);
}
private void initView(View rootView) {
tvName = (TextView) rootView.findViewById(R.id.tv_name);
tvCity = (TextView) rootView.findViewById(R.id.tv_city);
}
}
}
item_spinner_person.xml菜單條目:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:src="@mipmap/ic_launcher_round"
android:layout_width="30dp"
android:layout_height="30dp" />
<TextView
android:id="@+id/tv_name"
android:layout_marginLeft="10dp"
android:text="張三"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tv_city"
android:layout_marginLeft="10dp"
android:text="上海"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
運行效果:

5,Spinner的菜單顯示方式
Spinner有兩種顯示形式,一種是下拉菜單,一種是彈出框,菜單顯示形式是spinnerMode屬性決定的:
android:spinnerMode="dropdown"
android:spinnerMode="dialog"
以上用的都是下拉菜單的顯示,我們接下來看看彈出框的顯示,只需將SpinnerDemo3Activity中的布局使用activity_spinner_mode_dialog.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Spinner
android:spinnerMode="dialog"
android:id="@+id/spinner3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:dropDownWidth="match_parent"
android:gravity="center"
android:padding="10dp"
android:prompt="@string/dialog_title"
/>
</LinearLayout>
其運行效果如下:

6,Spinner的常用其他xml屬性匯總:
entries: 直接在xml布局文件中綁定數據源
android:entries="@array/languages"
prompt:在Spinner彈出選擇對話框的時候對話框的標題
android:prompt="@string/dialog_title"
dropDownVerticalOffset:
spinnerMode=”dropdown”時,下拉的項目選擇窗口在垂直方向相對于Spinner窗口的偏移量
android:dropDownVerticalOffset="40dp"
對應代碼中的方法:
public void setDropDownVerticalOffset(int pixels){}
dropDownWidth:
在spinnerMode=”dropdown”時,設定下拉框的寬度
android:dropDownWidth="wrap_content"
對應代碼中的方法:
public void setDropDownWidth(int pixels) {}
dropDownSelector:
用于設定spinnerMode=”dropdown”時列表選擇器的顯示效果
popupBackground:設置下拉框背景色
android:popupBackground="@drawable/bg_d_sp_spinner"
對應代碼中的方法:
public void setPopupBackgroundResource(int resId) { }
7,自定義Spinner下三角樣式
隱藏下三角:
1,自己寫一個xml背景不帶小圖標,把原來的背景替換掉
<Spinner
android:id="@+id/spinner3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:background="@drawable/bg_d_sc_spinner_no_icon"
android:dropDownHorizontalOffset="10dp"
android:dropDownVerticalOffset="40dp"
android:dropDownWidth="wrap_content"
android:gravity="center"
android:spinnerMode="dropdown" />
bg_d_sc_spinner_no_icon.xml如下:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<layer-list>
<item>
<shape>
<padding android:bottom="3dp" android:right="3dp" />
</shape>
</item>
</layer-list>
</item>
2,只需將spinner的背景設置為透明即可
<Spinner
android:id="@+id/spinner3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:background="@android:color/transparent"
android:drawableEnd="@mipmap/ic_launcher_round"
android:drawableRight="@mipmap/ic_launcher_round"
android:dropDownHorizontalOffset="10dp"
android:dropDownVerticalOffset="40dp"
android:dropDownWidth="wrap_content"
android:gravity="center"
android:spinnerMode="dropdown" />
運行效果如下圖:

自定義一個下三角或者其他圖標:
自己寫一個xml背景帶小圖標,把原來的背景替換掉
<Spinner
android:id="@+id/spinner3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_d_sc_spinner"
android:dropDownWidth="wrap_content"
android:spinnerMode="dropdown" />
bg_d_sc_spinner.xml如下:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<layer-list>
<item>
<shape>
<padding android:bottom="3dp" android:right="3dp" />
</shape>
</item>
<item>
<bitmap android:gravity="right" android:src="@mipmap/ic_find_next_holo_light" />
</item>
</layer-list>
</item>
</selector>