• 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 }

      效果展示:

     

    源码下载

    请支持原创,尊重原创,转载请注明出处。谢谢。

  • 相关阅读:
    吴军博士:物联网和人工智能将再造一个英特尔和微软 | 万物互联
    速来膜拜!20位活跃在Github上的国内技术大牛
    创建带Mipmap的osg::Image
    C#文件系统管理【转】
    C#文本文件(.txt)读写 [转]
    C#连接SQL Server数据库进行简单操作[转]
    shell脚本把一些请求量非常高的ip给拒绝掉
    linux获取精准进程PID之pgrep命令
    Kubernetes的Cron Job
    StatefulSet和Deployment的区别
  • 原文地址:https://www.cnblogs.com/hudabing/p/4515115.html
Copyright © 2020-2023  润新知