想尝试做一个简易的关于食物List的app,所以想到使用spinner级联方式先对用户所在位置进行确定,然后再获取相应位置的食物列表,使用ListView来展示出来。
一、如何将级联的内容:城市、行政区、位置商圈这三级内容保存并在spinner中级联获取呢?好像一共有三种方法:方法一:最暴力的就是直接用字符串数组写在代码里面;方法二:单独使用一个专门的Java类来存这些数据,同样是使用数组保存(其实大同小异,不过代码分离开了,重用度高,易于修改);方法三:定义一个arrays.xml文件,将所有数据以结点方式写入,在获取时可通过相应代码直接读取,该方法对于大量数据应该是最简便的吧。
由于初次使用,本想尝试通过在arrays.xml文件中将所有需要用到的地址位置写入,再在使用spinner时通过事件监听处理分别获取对应的item。但是实现时还没有太搞清楚,有点乱,时间比较紧所以先尝试用最简单的在类里面进行字符串数组定义,然后通过适配器获取数组对应值来显示。改进过程后续再进行。
这部分具体过程:
- 使用Spinner实现城市级联下拉框
- * Spinner最简单使用方式步骤如下:
- * 第一步:在布局文件中添加Spinner控件。
- * 第二步:在Acitvity中通过id找到它。
- * 第三步:给Spinner绑定一个适配器。
- * 第四步:绑定监听器就可以用了。
在设计开发过程中,同样的,先设计一个简单的界面,activity_food.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:orientation="vertical" android:id="@+id/LinearLayout1" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.example.food.MainActivity" android:background="@drawable/food" > <TextView android:id="@+id/place" android:text="请选择您当前所在位置区域" android:textSize="22dp" android:layout_width="match_parent" android:layout_height="wrap_content" /> <LinearLayout android:layout_marginTop="15dp" android:layout_width="280dp" android:layout_height="wrap_content" android:orientation="horizontal" android:layout_gravity="center" android:padding="8dp" > <TextView android:id="@+id/tip1" android:text="市" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <Spinner android:id="@+id/city" android:layout_width="58dp" android:layout_height="wrap_content" /> <TextView android:id="@+id/tip2" android:text="区" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <Spinner android:id="@+id/area" android:layout_width="70dp" android:layout_height="wrap_content" /> <TextView android:id="@+id/tip3" android:text="位置" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <Spinner android:id="@+id/spot" android:layout_width="150dp" android:layout_height="wrap_content" /> </LinearLayout> <Button android:layout_marginTop="55dp" android:layout_gravity="center" android:id="@+id/done" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="选好位置啦,点我去找吃的!" /> </LinearLayout>界面效果图如下:
初始时默认选择长沙市岳麓区,可以通过spinner下拉选择岳阳市,三层级联到岳阳相关位置。 FoodActivity.java实现逻辑处理,在这里用的是笨方法主要是通过数组来存储显示的内容, 关键代码1.适配器的使用,通过层级嵌套使用适配器关联数组内容到显示框中; 2. OnItemSelectedListener.选择事件的监听,传入参数到适配器中。
package com.example.eat; import java.security.PublicKey; import com.example.eat.*; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.Spinner; public class FoodActivity extends Activity { private Spinner city;//定义各个组件 private Spinner area; private Spinner spot; private Button done; String tCity; String Tarea; String Tspot; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_food);//获取组件 city=(Spinner)findViewById(R.id.city); area=(Spinner)findViewById(R.id.area); spot=(Spinner)findViewById(R.id.spot); done=(Button)findViewById(R.id.done); String[] cityStrings=new String[]{//定义需要获取的资源数据,数组形式存储 "长沙","岳阳","衡阳","株洲" }; final String[][] areaStrings=new String[][]{{"岳麓区","芙蓉区","雨花区","天心区"},{"南湖区","…"},{"市区","祁东"},{"市区"}}; final String[][][] spotStrings=new String[][][]{ { {"湖南大学天马学生公寓","湖南大学软件学院","湖南大学徳智园"},{"芙蓉广场"},{"长沙南站"},{"定王广场"} },{ {"南湖公园","南湖路"},{"…"} },{ {"衡阳市商业街"},{"……"} },{ {"方特"} }}; //为城市spinner定义一个适配器 ArrayAdapter<String>adapter1=new ArrayAdapter<String>(FoodActivity.this,android.R.layout.simple_spinner_item,cityStrings); city.setAdapter(adapter1); city.setOnItemSelectedListener(new OnItemSelectedListener() {//添加选择响应事件 int q; @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { // TODO Auto-generated method stub //创建适配器 ArrayAdapter<String> adapter2=new ArrayAdapter<String>(FoodActivity.this, android.R.layout.simple_spinner_item, areaStrings[position]); q=position; area.setAdapter(adapter2); area.setOnItemSelectedListener(new OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { // TODO Auto-generated method stub //创建适配器 ArrayAdapter<String> adapter3=new ArrayAdapter<String>(FoodActivity.this, android.R.layout.simple_spinner_item,spotStrings[q][position]); spot.setAdapter(adapter3); } @Override public void onNothingSelected(AdapterView<?> parent) { // TODO Auto-generated method stub } }); } @Override public void onNothingSelected(AdapterView<?> parent) { // TODO Auto-generated method stub } }); done.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub Intent i1=new Intent(FoodActivity.this,Dinner.class); startActivity(i1); } }); } }
二、ListView完成食物清单
先尝试了一下最简单的ListView:其实关键部分也就是使用了一个适配器来获取data[]数组内容,逐条逐行地显示。
public class Dinner extends Activity{ private String data[]={"湖南大学","岳麓山下","爱晚亭,"水果超市1","黄焖鸡",www.ee.com","咨询邮箱","综合楼","中南大学","天马公寓"}; private ListView listview; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.dinnerlist); this.listview=new ListView(this); this.listview.setAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_expandable_list_item_1,this.data)); //定义适配器,每行显示一条数据,并设置组件内容 super.setContentView(listview); } }
在此基础之上,跟着学姐博客试了一下食物清单。
因为对于这类清单,每个ListView格式都是一样的,所以使用了一个定义的模板xml文件。主要用来对要展示的图片pic.主题title,分类author,评分score,以及地区位置type作出布局的设计。
① data_list.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/LinearLayout1" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" > <ImageView android:id="@+id/pic" android:padding="3px" android:layout_width="130px" android:layout_height="wrap_content" /> <LinearLayout android:layout_width="200px" android:layout_height="wrap_content" android:gravity="left" android:orientation="vertical" > <TextView android:id="@+id/title" android:padding="3px" android:textSize="26px" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="TextView" /> <TextView android:id="@+id/author" android:padding="3px" android:textSize="15px" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="TextView" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > <ImageView android:id="@+id/score" android:padding="5px" android:layout_width="50px" android:layout_height="wrap_content" /> <TextView android:id="@+id/type" android:padding="5px" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="TextView" /> </LinearLayout> </LinearLayout>②dinnerlist.xml主要用于展示
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/LinearLayout1" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" > <TextView android:id="@+id/textView1" android:textSize="50px" android:layout_gravity="center_horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="食物清单~" /> <ListView android:id="@+id/datalist" android:layout_width="fill_parent" android:layout_height="wrap_content" ></ListView> </LinearLayout>③Dinner.java
package com.example.eat; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; import android.os.Bundle; import android.view.View; import android.widget.ArrayAdapter; import android.widget.ImageView; import android.widget.ListView; import android.widget.SimpleAdapter; import android.widget.Toast; public class Dinner extends Activity{ private int[]pic=new int[]{R.drawable.f1,R.drawable.f2,R.drawable.f3,R.drawable.f4,R.drawable.f5,R.drawable.f6}; private String data[][]=new String[][]{{"芝根芝底","西餐"},{"一面","西餐"},{"coffeeTeam","西餐"},{"爱.火烧","小吃"},{"小杨生煎","小吃"},{"sweety","甜品"}}; private List<Map<String,String>>list=new ArrayList<Map<String, String>>(); private ListView dataList; private SimpleAdapter simpleAdapter=null; private ImageView image; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.dinnerlist); dataList=(ListView)findViewById(R.id.datalist); for(int i=0;i<data.length;i++){ Map map=new HashMap<String,String>(); map.put("pic", String.valueOf(pic[i])); map.put("title", data[i][0]); map.put("author",this.data[i][1]); map.put("score",String.valueOf(R.drawable.pf) ); map.put("type", "湖南大学天马学生公寓"); list.add(map); } simpleAdapter=new SimpleAdapter(Dinner.this,list, R.layout.data_list,new String[]{"pic","title","author","score","type"},new int[]{R.id.pic,R.id.title,R.id.author,R.id.score,R.id.type}); dataList.setAdapter(simpleAdapter); } }这部分代码在理解上,主要是泛型以及HashMap的使用,还有适配器SimpleAdapter。
SimpleAdapter adapter=new SimpleAdapter( context,data,resource,from,to)括号中的参数的意思
第一个context,是这个SimpleAdapter所在的Activity(一般而言),所以这个参数一般是“前Activity的名字.this”
第二个是一个泛型只要是一个List就行,这一般会想到是ArrayList,而他内部存储的则是Map或者继承自Map的对象,比如HashMap,这里作为数据源,而且每一个ArraList中的一行就代表着呈现出来的一行,Map的键就是这一行的列名,值也是有列名的。
第三个资源文件,就是说要加载这个两列所需要的视图资源文件,一般在Layout建立相应的.xml文件,你可以左边一个TextView右边一个TextView,目的在于呈现左右两列的值。
第四个参数是一个String数组,主要是将Map对象中的名称映射到列名,一一对应
第五个是将第四个参数的值一一对象的显示(一一对应)在接下来的int形的id数组中,这个id数组就是LayOut的xml文件中命名id形成的唯一的int型标识符。
后期还可以再对适配器进一步学习,可以加入对话框功能。然后再对spinner读取xml数据文件再调试一下。