Android--UI之Spinner
前言
最近一直在讲AndroidUI的开发,今天讲一下Spinner控件,这是一个列表选择框,可以弹出一个列表供用户选择。在本片博客中,会讲解Spinner的基本属性以及设置之后的效果,以及使用SimpleAdapter绑定自定义格式的数据到Spinner中。
Spinner
Spinner是一个列表选择框,会在用户选择后,展示一个列表供用户进行选择。Spinner是ViewGroup的间接子类,它和其他的Android控件一样,数据需要使用Adapter进行封装。
下面介绍一下Spinner的常用XML属性,Android也为其属性提供了相应的getter、setter方法:
- android:spinnerMode:列表显示的模式,有两个选择,为弹出列表(dialog)以及下拉列表(dropdown),如果不特别设置,为下拉列表。。
- android:entries:使用<string-array…/>资源配置数据源。
- android:prompt:对当前下拉列表设置标题,仅在dialog模式下有效。传递一个“@string/name”资源,需要在需要在资源文件中定义<string…/>。
作为一个列表选择控件,Spinner具有一些选中选项可以触发的事件,但它本身没有定义这些事件,均继承自间接父类AdapterView。Spinner支持的几个常用事件有以下几个:
- AdapterView.OnItemCLickListener:列表项被点击时触发。
- AdapterView.OnItemLongClickListener:列表项被长按时触发。
- AdapterView.OnItemSelectedListener:列表项被选择时触发。
PS:因为适配器可以设置各种不同的样式,有选择、单选、多选,所以OnItemCLickListener和OnItemSelectedListener是适用于不同场景的。
Spinner的数据绑定
对于Spinner展示的数据源,一般使用两种方式设定数据:
- 通过XML资源文件设置,这种方式比较死板,但是如果仅仅需要展示固定的、简单的数据,这种方式还是可以考虑的,比较直观。
- 使用Adapter接口设置,这是最常见的方式,动态、灵活,可以设定各种样式以及数据来源。
先来讲讲通过XML资源文件设置Spinner数据的方式,首先需要在/res/values目录下新建XML格式的资源文件,名字不重要,但是一般会使用strings.xml。在其中的<resourse…/>标签下,定义<string-array…/>标签,通过它中的<item…/>标签来设置选择数据。
XML文件结构:
<resource>
<string-array name=”arrayname”>
<item>item1</item>
<item>item2</item>
<item>item3</item>
</string-array>
<resource>
通过适配器Adapter可以设定比较复杂的展示效果,一般项目中比较常用的也是这种方式。但是如果对于动态的、简单的数据,可以使用ArrayAdapter对象来设置适配器,关于ArrayAdapter类的介绍,在我的另外一篇博客中有介绍,不了解的朋友可以先看看:Android–UI之AutoCompleteTextView 。
下面通过一个示例,讲解一下上面说的属性、事件,以及使用ArrayAdapter和XML资源文件设定简单数据,代码中注释已经说的很清楚了,这里就不再累述了。
布局代码:
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:orientation="vertical" > 6 7 <TextView 8 android:layout_width="wrap_content" 9 android:layout_height="wrap_content" 10 android:text="弹出的Spinner" /> 11 12 <Spinner 13 android:id="@+id/spinnerBase" 14 android:layout_width="match_parent" 15 android:layout_height="wrap_content" 16 android:spinnerMode="dialog" /> 17 18 <TextView 19 android:layout_width="wrap_content" 20 android:layout_height="wrap_content" 21 android:text="下拉的Spinner(默认)" /> 22 23 <Spinner 24 android:id="@+id/spinnerBase1" 25 android:layout_width="match_parent" 26 android:layout_height="wrap_content" 27 android:spinnerMode="dropdown" /> 28 29 <TextView 30 android:layout_width="wrap_content" 31 android:layout_height="wrap_content" 32 android:text="entries绑定数据源" /> 33 34 <Spinner 35 android:id="@+id/spinnerBase2" 36 android:layout_width="match_parent" 37 android:layout_height="wrap_content" 38 android:entries="@array/beijing" /> 39 40 <TextView 41 android:layout_width="wrap_content" 42 android:layout_height="wrap_content" 43 android:text="弹出带标题的Dialog,并且使用entries绑定数据源" /> 44 45 <Spinner 46 android:id="@+id/spinnerBase3" 47 android:layout_width="match_parent" 48 android:layout_height="wrap_content" 49 android:entries="@array/beijing" 50 android:prompt="@string/beij_prompt" 51 android:spinnerMode="dialog" /> 52 53 </LinearLayout>
实现代码:
1 package com.bgxt.datatimepickerdemo; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 import android.app.Activity; 7 import android.os.Bundle; 8 import android.view.View; 9 import android.widget.AdapterView; 10 import android.widget.AdapterView.OnItemSelectedListener; 11 import android.widget.ArrayAdapter; 12 import android.widget.Spinner; 13 import android.widget.Toast; 14 15 public class SpinnerBaseActivity extends Activity { 16 private Spinner spinner1, spinner2; 17 18 @Override 19 protected void onCreate(Bundle savedInstanceState) { 20 super.onCreate(savedInstanceState); 21 setContentView(R.layout.activity_spinnerbase); 22 23 spinner1 = (Spinner) findViewById(R.id.spinnerBase); 24 spinner2 = (Spinner) findViewById(R.id.spinnerBase1); 25 // 声明一个ArrayAdapter用于存放简单数据 26 ArrayAdapter<String> adapter = new ArrayAdapter<String>( 27 SpinnerBaseActivity.this, android.R.layout.simple_spinner_item, 28 getData()); 29 // 把定义好的Adapter设定到spinner中 30 spinner1.setAdapter(adapter); 31 spinner2.setAdapter(adapter); 32 // 为第一个Spinner设定选中事件 33 spinner1.setOnItemSelectedListener(new OnItemSelectedListener() { 34 35 @Override 36 public void onItemSelected(AdapterView<?> parent, View view, 37 int position, long id) { 38 // 在选中之后触发 39 Toast.makeText(SpinnerBaseActivity.this, 40 parent.getItemAtPosition(position).toString(), 41 Toast.LENGTH_SHORT).show(); 42 } 43 44 @Override 45 public void onNothingSelected(AdapterView<?> parent) { 46 // 这个一直没有触发,我也不知道什么时候被触发。 47 //在官方的文档上说明,为back的时候触发,但是无效,可能需要特定的场景 48 } 49 }); 50 51 } 52 53 private List<String> getData() { 54 // 数据源 55 List<String> dataList = new ArrayList<String>(); 56 dataList.add("北京"); 57 dataList.add("上海"); 58 dataList.add("南京"); 59 dataList.add("宜昌"); 60 return dataList; 61 } 62 63 }
XML资源文件:
1 <?xml version="1.0" encoding="utf-8"?> 2 <resources> 3 <string name="app_name">SpinnerDemo</string> 4 <string name="action_settings">Settings</string> 5 <string name="hello_world">Hello world!</string> 6 <string name="beij_prompt">北京区域</string> 7 <string-array name="beijing"> 8 <item>朝阳区</item> 9 <item>海淀区</item> 10 <item>房山区</item> 11 <item>丰台区</item> 12 <item>东城区</item> 13 <item>西城区</item> 14 </string-array> 15 </resources>
效果展示,图片顺序,从上到下:
SimpleAdapter配置Spinner数据
对于一个稍复杂的数据,如果想对其展示,光使用ArrayAdapter是无法满足需求的,现在在另外介绍一个Adapter,SimpleAdapter,同样继承自Adapter。
SimpleAdapter是一个简单的适配器,映射静态的XML格式的布局文件到视图中。可以指定一个List<Map<P,T>>格式的数据,List中的每一条数据对应一行,而Map中的每一条数据对应数据行的一列。这个数据用来映射到XML定义的布局控件中,对应关系通过构造函数的另外两个参数来指定,现在来介绍一下SimpleAdapter的构造函数。
SimpleAdapter(Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to)
- context:上下文对象,没什么好说的,一般就是当前的Activity。
- data:上面介绍的List<Map<S,T>>类型的数据。
- resource:XML资源的Id,通过R对象选中。
- from:一个String类型数组,每条数据对应data数据中,Map结构定义的Key。
- to:一个int类型数组,对应XML资源中控件的ID,注意顺序必须与from中指定数据的顺序一致。
下面通过一个示例讲解一下SimpleAdapter是如何设置自定义格式数据的。
布局代码:
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:orientation="vertical" > 6 7 <Spinner android:id="@+id/spinnerAdapter" android:layout_width="match_parent" 8 android:layout_height="wrap_content" /> 9 </LinearLayout>
XML布局资源代码:
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="wrap_content" 5 android:orientation="horizontal" > 6 7 <ImageView 8 android:id="@+id/imageview" 9 android:layout_width="60dp" 10 android:layout_height="60dp" 11 android:paddingLeft="10dp" 12 android:src="@drawable/ic_launcher" /> 13 14 <TextView 15 android:id="@+id/textview" 16 android:layout_width="match_parent" 17 android:layout_height="wrap_content" 18 android:gravity="center_vertical" 19 android:paddingLeft="10dp" 20 android:textColor="#000" 21 android:textSize="16dp" /> 22 23 </LinearLayout>
实现代码:
1 package com.bgxt.datatimepickerdemo; 2 3 import java.util.ArrayList; 4 import java.util.HashMap; 5 import java.util.List; 6 import java.util.Map; 7 8 import android.app.Activity; 9 import android.os.Bundle; 10 import android.view.View; 11 import android.widget.AdapterView; 12 13 import android.widget.AdapterView.OnItemSelectedListener; 14 import android.widget.SimpleAdapter; 15 import android.widget.Spinner; 16 import android.widget.Toast; 17 18 public class SpinnerAdapterActivity extends Activity { 19 private Spinner spinner; 20 21 @Override 22 protected void onCreate(Bundle savedInstanceState) { 23 // TODO Auto-generated method stub 24 super.onCreate(savedInstanceState); 25 setContentView(R.layout.activity_spinneradapter); 26 27 spinner = (Spinner) findViewById(R.id.spinnerAdapter); 28 //声明一个SimpleAdapter独享,设置数据与对应关系 29 SimpleAdapter simpleAdapter = new SimpleAdapter( 30 SpinnerAdapterActivity.this, getData(), R.layout.items, 31 new String[] { "ivLogo", "applicationName" }, new int[] { 32 R.id.imageview, R.id.textview }); 33 //绑定Adapter到Spinner中 34 spinner.setAdapter(simpleAdapter); 35 //Spinner被选中事件绑定。 36 spinner.setOnItemSelectedListener(new OnItemSelectedListener() { 37 38 @Override 39 public void onItemSelected(AdapterView<?> parent, View view, 40 int position, long id) { 41 //parent为一个Map结构的和数据 42 Map<String, Object> map = (Map<String, Object>) parent 43 .getItemAtPosition(position); 44 Toast.makeText(SpinnerAdapterActivity.this, 45 map.get("applicationName").toString(), 46 Toast.LENGTH_SHORT).show(); 47 } 48 49 @Override 50 public void onNothingSelected(AdapterView<?> arg0) { 51 52 } 53 }); 54 } 55 56 public List<Map<String, Object>> getData() { 57 //生成数据源 58 List<Map<String, Object>> list = new ArrayList<Map<String, Object>>(); 59 //每个Map结构为一条数据,key与Adapter中定义的String数组中定义的一一对应。 60 Map<String, Object> map = new HashMap<String, Object>(); 61 map.put("ivLogo", R.drawable.bmp1); 62 map.put("applicationName", "表情1"); 63 list.add(map); 64 Map<String, Object> map2 = new HashMap<String, Object>(); 65 map2.put("ivLogo", R.drawable.bmp2); 66 map2.put("applicationName", "表情2"); 67 list.add(map2); 68 Map<String, Object> map3 = new HashMap<String, Object>(); 69 map3.put("ivLogo", R.drawable.bmp3); 70 map3.put("applicationName", "表情3"); 71 list.add(map3); 72 return list; 73 } 74 }
效果展示:
请支持原创,尊重原创,转载请注明出处。谢谢。