由于项目的需要,要给用户显示一列表单项,让用户选择,之前使用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>