Android学习——Spinner实现下拉列表
一、Spinner简介
在Web开发中,HTML提供了下拉列表的实现,就是使用<select>元素实现一个下拉列表,在其中每个下拉列表项使用<option>表示即可。这是在Web开发中一个必不可少的交互性组件,而在Android中的对应实现就是Spinner。
在编码的同时,首先需要在布局中设定Spinner组件,然后将可选内容通过ArrayAdapter和下拉列表连接起来,最后要获得用户选择的选项,我们需要设计事件监听器setOnItemSelectedListener并实现onItemSelected,从而获得用户所选择的内容,最后通过setVisibility方法设置当前的显示项
二、使用方法
1、以资源方式,静态展示 Spinner 选项:
布局文件:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<Spinner android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/spinner2" android:entries="@array/spingarr" />
数据文件:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?xml version="1.0" encoding="utf-8"?> <resources> <string-array name="spingarr"> <item>北京</item> <item>上海</item> <item>广州</item> <item>深圳</item> </string-array> </resources>
效果图:
【注意】在<Spinner>标签中,通过android:prompt来设置弹出选择框的标题,通过android:entries来设置默认的列表选项,可以直接在xml布局文件中绑定数据源(也可以不在xml布局文件中设置,而在Activity中动态绑定)
2、以代码方式,动态展示 Spinner 选项(用适配器给Spinner添加数据)
布局文件:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<Spinner android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/spinner" />
自定数据源:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.example.testspanner; import java.util.ArrayList; import java.util.List; import android.app.Activity; import android.os.Bundle; import android.widget.ArrayAdapter; import android.widget.Spinner; public class MainActivity extends Activity { private Spinner spinner; private List<String> data_list; private ArrayAdapter<String> arr_adapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.spinner); spinner = (Spinner) findViewById(R.id.spinner); //数据 data_list = new ArrayList<String>(); data_list.add("北京"); data_list.add("上海"); data_list.add("广州"); data_list.add("深圳"); //适配器 arr_adapter= new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, data_list); //设置样式 arr_adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); //加载适配器 spinner.setAdapter(arr_adapter); } }
3、使用ArrayAdapter进行适配数据:
①:首先定义一个布局文件:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <Spinner android:id="@+id/spinner1" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout>
②:建立数据源,使用数组,这些数据将会在Spinner下来列表中进行显示:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?xml version="1.0" encoding="utf-8"?> <resources> <string-array name="spinnername"> <item>北京</item> <item>上海 </item> <item>广州</item> <item>深圳</item> </string-array> </resources>
③:接着在Activity中加入如下的代码(使用了系统定义的下拉列表的布局文件,当然也可以自定义)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
// 初始化控件 mSpinner = (Spinner) findViewById(R.id.spinner1); // 建立数据源 String[] mItems = getResources().getStringArray(R.array.spinnername); // 建立Adapter并且绑定数据源 ArrayAdapter<String> _Adapter=new ArrayAdapter<String>(this,android.R.layout.simple_spinner_item, mItems); //绑定 Adapter到控件 mSpinner.setAdapter(_Adapter);
下面是关于Spinner的点击事件(效果图如下图):
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
mSpinner.setOnItemSelectedListener(new OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { String str=parent.getItemAtPosition(position).toString(); Toast.makeText(SpinnerActivity.this, "你点击的是:"+str, 2000).show(); } @Override public void onNothingSelected(AdapterView<?> parent) { // TODO Auto-generated method stub } });
4、使用自定义的Adapter(重点)
①:定义每一个Item的布局文件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?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:orientation="horizontal" > <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:drawableLeft="@drawable/ic_launcher" android:paddingRight="8dip" android:paddingTop="8dip" android:text="TextView" android:textSize="25sp" /> <TextView android:id="@+id/textView2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingLeft="8dip" android:paddingTop="8dip" android:text="TextView" android:textSize="25sp" /> </LinearLayout>
②:建立Person类:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.jiangqq.csdn; public class Person { private String personName; private String personAddress; public Person(String personName, String personAddress) { super(); this.personName = personName; this.personAddress = personAddress; } public String getPersonName() { return personName; } public void setPersonName(String personName) { this.personName = personName; } public String getPersonAddress() { return personAddress; } public void setPersonAddress(String personAddress) { this.personAddress = personAddress; } }
③:创建MyAdapter继承与BaseAdapter,进行适配:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.jiangqq.csdn; import java.util.List; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView; /** * 自定义适配器类 * @author jiangqq <a href=http://blog.csdn.net/jiangqq781931404></a> * */ public class MyAdapter extends BaseAdapter { private List<Person> mList; private Context mContext; public MyAdapter(Context pContext, List<Person> pList) { this.mContext = pContext; this.mList = pList; } @Override public int getCount() { return mList.size(); } @Override public Object getItem(int position) { return mList.get(position); } @Override public long getItemId(int position) { return position; } /** * 下面是重要代码 */ @Override public View getView(int position, View convertView, ViewGroup parent) { LayoutInflater _LayoutInflater=LayoutInflater.from(mContext); convertView=_LayoutInflater.inflate(R.layout.item, null); if(convertView!=null) { TextView _TextView1=(TextView)convertView.findViewById(R.id.textView1); TextView _TextView2=(TextView)convertView.findViewById(R.id.textView2); _TextView1.setText(mList.get(position).getPersonName()); _TextView2.setText(mList.get(position).getPersonAddress()); } return convertView; } }
④:在Activity中加入如下代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
// 初始化控件 mSpinner = (Spinner) findViewById(R.id.spinner1); // 建立数据源 List<Person> persons=new ArrayList<Person>(); persons.add(new Person("张三", "上海 ")); persons.add(new Person("李四", "上海 ")); persons.add(new Person("王五", "北京" )); persons.add(new Person("赵六", "广州 ")); // 建立Adapter绑定数据源 MyAdapter _MyAdapter=new MyAdapter(this, persons); //绑定Adapter mSpinner.setAdapter(_MyAdapter);
运行效果如下截图:
监听事件和第一种方法相同
5、示例代码:
使用数组作为数据源
(1).新建一个android的工程
(2).工程的layout.xml文件如下:声明一个TextView控件和一个Spinner控件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TextView android:id="@+id/spinnerText" android:layout_width="fill_parent" android:layout_height="wrap_content"></TextView> <Spinner android:id="@+id/Spinner01" android:layout_width="fill_parent" android:layout_height="wrap_content"></Spinner> </LinearLayout>
(3)、java代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.ArrayAdapter; import android.widget.Spinner; import android.widget.TextView; public class SpinnerActivity extends Activity { private static final String[] m={"A型","B型","O型","AB型","其他"}; private TextView view ; private Spinner spinner; private ArrayAdapter<String> adapter; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.spinner); view = (TextView) findViewById(R.id.spinnerText); spinner = (Spinner) findViewById(R.id.Spinner01); //将可选内容与ArrayAdapter连接起来 adapter = new ArrayAdapter<String>(this,android.R.layout.simple_spinner_item,m); //设置下拉列表的风格 adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); //将adapter 添加到spinner中 spinner.setAdapter(adapter); //添加事件Spinner事件监听 spinner.setOnItemSelectedListener(new SpinnerSelectedListener()); //设置默认值 spinner.setVisibility(View.VISIBLE); } //使用数组形式操作 class SpinnerSelectedListener implements OnItemSelectedListener{ public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) { view.setText("你的血型是:"+m[arg2]); } public void onNothingSelected(AdapterView<?> arg0) { } } }
(4)、运行效果如下:
使用XML作为数据源
(1).新建一个android的工程
(2).在values文件夹下新建一个arryas.xml文件:声明一个TextView控件和一个Spinner控件,代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?xml version="1.0" encoding="utf-8"?> <resources> <string-array name="plantes"> <item>NOKIA</item> <item>MOTO</item> <item>HTC</item> <item>LG</item> <item>其他</item> </string-array> </resources>
(3).java代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.ArrayAdapter; import android.widget.Spinner; import android.widget.TextView; public class SpinnerActivity extends Activity { private TextView view2; private Spinner spinner2; private ArrayAdapter adapter2; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.spinner); spinner2 = (Spinner) findViewById(R.id.spinner02); view2 = (TextView) findViewById(R.id.spinnerText02); //将可选内容与ArrayAdapter连接起来 adapter2 = ArrayAdapter.createFromResource(this, R.array.plantes, android.R.layout.simple_spinner_item); //设置下拉列表的风格 adapter2.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); //将adapter2 添加到spinner中 spinner2.setAdapter(adapter2); //添加事件Spinner事件监听 spinner2.setOnItemSelectedListener(new SpinnerXMLSelectedListener()); //设置默认值 spinner2.setVisibility(View.VISIBLE); } //使用XML形式操作 class SpinnerXMLSelectedListener implements OnItemSelectedListener{ public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) { view2.setText("你使用什么样的手机:"+adapter2.getItem(arg2)); } public void onNothingSelected(AdapterView<?> arg0) { } } }
示例代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public class MainActivity extends Activity { private Spinner spinner; private TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); spinner = (Spinner) findViewById(R.id.spinner); textView = (TextView) findViewById(R.id.textViewId); // 创建一个ArrayAdapter // 静态使用xml文件设置下拉列表内容 /** * ArrayAdapter参数说明: * 第一个:上下文对象 * 第二个:下拉菜单数据来源的id * 第三个:下拉菜单的样式,这里使用了android标准下拉菜单的样式 */ // ArrayAdapter<CharSequence> adapter = // ArrayAdapter.createFromResource(this, R.array.ThreeDays, // android.R.layout.simple_spinner_item); // 调用setDropDownViewResource()方法设置下拉列表每一个选项的样式,这里也是用Android标准样式 // adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); // 动态设置下拉列表内容 List<String> list = new ArrayList<String>(); list.add("昨天"); list.add("今天"); list.add("明天"); /** * 参数 *第一个:上下文对象 *第二个:自定义下拉菜单的选项的样式 * 第三个:自定义下拉菜单选项控件的样式id * 第四个:列表数据 */ ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.list, R.id.list_textViewId, list); // 为spinner添加适配器 spinner.setAdapter(adapter); // 设置Spinner下拉列表的标题·· spinner.setPrompt("只有这三天"); // 为spinner绑定监听器 spinner.setOnItemSelectedListener(new SpinnerListener()); } // 该监听器用于监听用户多spinner的操作 class SpinnerListener implements OnItemSelectedListener { // 当用户选择先拉列表中的选项时会调用这个方法 /** * 参数说明: * 第一个:当前的下拉列表,也就是第三个参数的父view *第二个:当前选中的选项 *第三个:所选选项的位置 *第四个: 所选选项的id */ public void onItemSelected(AdapterView<?> adapterView, View view, int position, long id) { // 获取用户所选的选项内容 String selected = "您的选择是:" + adapterView.getItemAtPosition(position).toString(); textView.setText(selected); Toast.makeText(MainActivity.this, selected, Toast.LENGTH_SHORT) .show(); } // 当用户不做选择时调用的该方法 public void onNothingSelected(AdapterView<?> arg0) { Toast.makeText(MainActivity.this, "您没有选择任何选项", Toast.LENGTH_SHORT) .show(); } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.activity_main, menu); return true; } }
示例代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package cn.com; import java.util.ArrayList; import java.util.List; import android.app.Activity; import android.os.Bundle; import android.view.MotionEvent; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Spinner; import android.widget.TextView; public class SpinnerActivity extends Activity { /** Called when the activity is first created. */ private List<String> list = new ArrayList<String>(); private TextView myTextView; private Spinner mySpinner; private ArrayAdapter<String> adapter; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); //第一步:添加一个下拉列表项的list,这里添加的项就是下拉列表的菜单项 list.add("北京"); list.add("上海"); list.add("深圳"); list.add("福州"); list.add("厦门"); myTextView = (TextView)findViewById(R.id.TextView_city); mySpinner = (Spinner)findViewById(R.id.Spinner_city); //第二步:为下拉列表定义一个适配器,这里就用到里前面定义的list。 adapter = new ArrayAdapter<String>(this,android.R.layout.simple_spinner_item, list); //第三步:为适配器设置下拉列表下拉时的菜单样式。 adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); //第四步:将适配器添加到下拉列表上 mySpinner.setAdapter(adapter); //第五步:为下拉列表设置各种事件的响应,这个事响应菜单被选中 mySpinner.setOnItemSelectedListener(new Spinner.OnItemSelectedListener(){ public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) { // TODO Auto-generated method stub /* 将所选mySpinner 的值带入myTextView 中*/ myTextView.setText("您选择的是:"+ adapter.getItem(arg2)); /* 将mySpinner 显示*/ arg0.setVisibility(View.VISIBLE); } public void onNothingSelected(AdapterView<?> arg0) { // TODO Auto-generated method stub myTextView.setText("NONE"); arg0.setVisibility(View.VISIBLE); } }); /*下拉菜单弹出的内容选项触屏事件处理*/ mySpinner.setOnTouchListener(new Spinner.OnTouchListener(){ public boolean onTouch(View v, MotionEvent event) { // TODO Auto-generated method stub /** * */ return false; } }); /*下拉菜单弹出的内容选项焦点改变事件处理*/ mySpinner.setOnFocusChangeListener(new Spinner.OnFocusChangeListener(){ public void onFocusChange(View v, boolean hasFocus) { // TODO Auto-generated method stub } }); } }
三、根据城市的选择,自动显示后边的城区选择
.xml文件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<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="horizontal" tools:context=".MainActivity" > <Spinner android:id="@+id/ciyt" android:prompt="@string/city_prompt" android:layout_width="wrap_content" android:layout_height="wrap_content" android:entries="@array/cities"/> <Spinner android:id="@+id/area" android:prompt="@string/city_prompt" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </LinearLayout>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public class MainActivity extends Activity { // 城市 private Spinner city = null; // 城市下边的子成区 private Spinner area = null; private String[][] areaData = new String[][] { { "东城", "西城", "海淀", "上地" }, { "陆家嘴", "黄埔", "金融街" }, { "宝安区", "深圳区", "中山区" } }; private ArrayAdapter<CharSequence> adapterArea = null; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); this.city = (Spinner) super.findViewById(R.id.ciyt); this.area = (Spinner) super.findViewById(R.id.area); this.city.setOnItemSelectedListener(new OnItemSelectedListenerImp()); } private class OnItemSelectedListenerImp implements OnItemSelectedListener { public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { // 得到选择的选项 MainActivity.this.adapterArea = new ArrayAdapter<CharSequence>( MainActivity.this, android.R.layout.simple_spinner_item, MainActivity.this.areaData[position]); MainActivity.this.adapterArea .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); MainActivity.this.area.setAdapter(MainActivity.this.adapterArea); } public void onNothingSelected(AdapterView<?> arg0) { // TODO Auto-generated method stub } } }
values当中的city.xml
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?xml version="1.0" encoding="utf-8"?> <resources> <string-array name="cities"> <item>北京</item> <item>上海</item> <item>深圳</item> </string-array> </resources>
四、android spinner下拉样式介绍
1、更换android.R xml样式
以下为引用内容: ArrayAdapter< String> adapter = new ArrayAdapter< String>( this, android.R.layout.simple_spinner_item);
这里面的第二个参数是android.R系统自带的xml样式,我们更换这个时就会看到生成的spinner的直观样式如下:
图1
如果换成android.R.layoutbrowser_link_context_header那么样式变为:
图2
同理:android.R.pinner_dropdown:
android.R.preference_category:
图4
android.R.simple_spinner_item
图5
android.R.select_dialog_item:
图6
android.R.select_dialog_multichoice
图7
android.R.select_dialog_singlechoice
图8
android.R.simple_dropdown_item_1line
图9
android.R.simple_expandable_list_item_1
图10
android.R.simple_gallery_item
图11
android.R.simple_list_item_1
图12
android.R.simple_list_item_checked
图13
android.R.simple_list_item_multiple_choice
图14
android.R.simple_list_item_single_choice
图15
android.R.simple_spinner_dropdown_item
图16
android.R.simple_spinner_item
图17
android.R.test_list_item
图18
还有自定义的spinner.xml :
以下为引用内容: <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/text1" android:layout_width="60px" android:layout_height="wrap_content" android:singleLine="true" style="?android:attr/spinnerItemStyle" />
图19
2、下拉列表弹出样式
更换 xml 参数
以下为引用内容: adapter.setDropDownViewResource(android.R.layout.test_list_item);
android.R.browser_link_context_header :
图20
preference_category :
图21
select_dialog_item:
图22
select_dialog_multichoice:多选样式,可惜不能多选。
图23
select_dialog_singlechoice:
图24
simple_dropdown_item_1line:
图25
simple_list_item_checked:
图26
simple_list_item_single_choice:
图27