由于项目的需要,要给用户显示一列表单项,让用户选择,之前使用LinerLayout加Button实现,费时费力,而且表现的内容都已经是写好的内容,对于内容可变的情况下,毫无招架之力。因此在新的项目当中使用了向ListView加入Spinner的方式来表现表单。开发过程中遇到些问题。
一、 遇到的问题:
1、对于Spinner状态的保持。
2、对Spinner做了相应事件之后,对于ListView的OnItemClick事件的相应的处理。
二、 问题的解决:
第一个问题在于,ListView侧重于对数据的表现,而对数据的交互方面是比较差的,因为随着ListView的上下滚动,其会对内部的数据进行重绘操作,当数据划出屏幕之后将数据移除,同时将划入的数据进行重绘。还有一个问题就是当你点击Spinner的时候,ListView并不知道你点击了哪个Spinner。以上两个原因就造成了,你点击的Spinner所选择的项目在屏幕滑来滑去的时候会改变本身的值,同时你无法获取所选的Spinner的值。
对于这个问题只要加一个Map将Spinner的状态保持住,让后在Listview重绘的时候,从这个Map当中取出ListView的值进行赋值操作即可。同时注意,因为ListView并不知道你点击了哪个Spinner,因此无法通过position作为键,这时候,可以首先将能够以为标识所点击Item的一个字段作为Spinner的Prompt,当你选中之后,Spinner的Prompt就是你点击的那个Item,获取到Prompt作为Map的键即可。
对于第二个问题,见我的另一篇博客listView当中有嵌套了有onClickListener的控件时ListView自身的onItemClick无响应的解决方案
三、 具体解决方案见主要代码:
问题一的主要代码(ListView的适配器):
package com.yang.adapter; import java.util.HashMap; import java.util.Map; import ouc.sei.R; import android.content.Context; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.BaseAdapter; import android.widget.Spinner; import android.widget.TextView; public class CheckListAdapter extends BaseAdapter { private Context mContext; private String[] checkListName; // 存储以名值对。存放Spinner的Prompt和用户选中的值 private Map<String, Integer> allValues; public CheckListAdapter(Context mContext, String[] checkListName) { this.mContext = mContext; this.checkListName = checkListName; allValues = new HashMap<String, Integer>(); putAllValues(); } private void putAllValues() { for (String str : checkListName) { allValues.put(str, 0); } } public void setAllValues(Map<String, Integer> allValues){ this.allValues = allValues; } @Override public int getCount() { return checkListName.length; } @Override public Object getItem(int position) { return checkListName[position]; } @Override public long getItemId(int position) { return 0; } private class ViewHolder { TextView checkinfo_item_name; Spinner checkinfo_item_value; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; if (convertView == null) { convertView = View.inflate(mContext, R.layout.checkinfo_list_item, null); holder = new ViewHolder(); holder.checkinfo_item_name = (TextView) convertView .findViewById(R.id.checkinfo_item_name); holder.checkinfo_item_value = (Spinner) convertView .findViewById(R.id.checkinfo_item_value); // 设置其adapter SpinnerAdapter adapter = new SpinnerAdapter(mContext); holder.checkinfo_item_value.setAdapter(adapter); holder.checkinfo_item_value .setOnItemSelectedListener(new ItemClickSelectListener( holder.checkinfo_item_value)); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } String checkedName = checkListName[position]; holder.checkinfo_item_name.setText(checkedName); //关键代码,配合下面的相应事件使用。 holder.checkinfo_item_value.setPrompt(checkedName); int spinnerOptionPosition = allValues.get(checkedName); Log.d("CheckList", checkedName + " = = " + spinnerOptionPosition); holder.checkinfo_item_value.setSelection(spinnerOptionPosition); return convertView; } private class ItemClickSelectListener implements OnItemSelectedListener { Spinner checkinfo_item_value ; public ItemClickSelectListener(Spinner checkinfo_item_value) { this.checkinfo_item_value = checkinfo_item_value; } @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { //关键代码 allValues.put(checkinfo_item_value.getPrompt().toString(), position); } @Override public void onNothingSelected(AdapterView<?> arg0) { } } //返回用于选中的所有值 public Map<String,Integer> getSelectValues() { return allValues; } }
问题二的主要代码:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:descendantFocusability="blocksDescendants" android:orientation="horizontal" > <TextView android:id="@+id/checkinfo_item_name" android:layout_width="wrap_content" android:layout_height="fill_parent" android:layout_alignParentLeft="true" android:layout_gravity="left" android:textColor="@android:color/black" android:textSize="18sp" /> <Spinner android:id="@+id/checkinfo_item_value" style="@style/SpinnerAsEditText" android:layout_width="125dip" android:layout_height="fill_parent" android:layout_alignParentRight="true" /> </RelativeLayout>
四、项目图片


五、整个项目的下载地址