Android:当我动态添加新的 ListView 条目时,ListView 中的 Spinners 会丢失它们的值

标签 android listview button spinner

我的 Activity 包含一个按钮和一个 ListView。 ListView 包含一个 Spinner 和一个 EditText View 。每次我想在 Activity 的 ListView 中插入新行条目时,我都会使用该按钮。

我已经按照以前的 stackoverflow 线程的说明进行操作,例如:Android Listview with spinner and a checkbox关于如何使用 Spinners 等可聚焦对象填充 ListView。

我的问题是,每次我在 ListView 中动态添加一个新的 ListView 条目时,先前 ListView 条目的 Spinner 值都会丢失(实际上 Spinner 返回到其默认设置)。为简单起见,假设我的微调器填充了以下数据:

 String spinner_data[] = {"apple", "banana", "pear", "watermelon", "strawberry"};

例如,如果我选择我的第一个 ListView 的 Spinner 值为“pear”,然后我用我的 Button 添加一个新的 ListView 条目,“pear”条目从第一个 ListView Spinner 中消失,默认值“apple”出现).

感谢任何帮助!

这是我的 Activity :

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    lv = (ListView) findViewById(R.id.lv);       
    da = new DataAdapter(this, new ArrayList<RawData>());
    lv.setAdapter(da);

    btn_new = (Button)findViewById(R.id.btn_new);

    btn_new.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            da.add(new RawData(this));
                      da.notifyDataSetChanged();
        }
    });

}

RawData 类是这个:

 public class RawData {
private int selected_position;
private ArrayAdapter<CharSequence> adapter;

public RawData(Context context)
{
    adapter = ArrayAdapter.createFromResource(context, R.array.data, android.R.layout.simple_spinner_item);
    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
}

public ArrayAdapter<CharSequence> getAdapter() 
{         
    return adapter;     
}

/**
 * get adapter's item text from selected position
 * @return
 */
public String getText() 
{         
    return (String) adapter.getItem(selected_position);     
}

public int getSelected() 
{   
    return selected_position;     
}

public void setSelected(int selected) 
{         
    this.selected_position = selected;     
}
 }

DataArrayAdapter 如下:

 public class DataArrayAdapter extends ArrayAdapter<RawData> {
private Activity myContext;
//private final List<RawData> list;

public DataArrayAdapter(Activity context, List<RawData> list) 
{         
    super(context, R.layout.row_view, list);         
    myContext = context;
} 

static class ViewHolder
{
    protected RawData data;
    protected Spinner spn;
    protected EditText edt;
}

@Override
public View getView(int position, View convertView, ViewGroup parent)
{
    View view = null;
    if ( convertView == null )
    {
        LayoutInflater inflator = myContext.getLayoutInflater();             
        view = inflator.inflate(R.layout.row_view, null);

        final ViewHolder viewHolder = new ViewHolder(); 

        viewHolder.edt = (EditText)view.findViewById(R.id.edt);
        viewHolder.data = new RawData(myContext);
        viewHolder.spn = (Spinner)view.findViewById(R.id.spn);
        viewHolder.spn.setAdapter(viewHolder.data.getAdapter());

    viewHolder.spn.setOnItemSelectedListener(new OnItemSelectedListener() {

        @Override
        public void onItemSelected(AdapterView<?> arg0, View arg1,
                    int arg2_position, long arg3) {
                // TODO Auto-generated method stub
    viewHolder.data.setSelected(arg2_position);
            }

            @Override
            public void onNothingSelected(AdapterView<?> arg0) {
                // TODO Auto-generated method stub

            }
        });

        // Update the TextView to reflect what's in the Spinner
        view.setTag(viewHolder);
    }
    else
    {
        view = convertView;
    }

    // This is what gets called every time the ListView refreshes
    ViewHolder holder = (ViewHolder) view.getTag();

               holder.spn.setSelection(getItem(position).getSelected());

    return view;
}

 }

最佳答案

getView 获取非空 convertView 时,您没有处理这种情况。在您的示例中,添加一个项目后,ListView 会自行刷新,应该显示“pear”的位置会获得一个现有的 convertView(之前用于显示“apple'),你只需将它传递给 ListView 而无需设置当前位置的数据。您不能依赖 ListView 项来存储任何数据,您应该始终在适配器的 getView 方法中为位置设置正确的内容。 需要明确的是,我看到您的代码在 getView 的末尾设置了选定位置,但问题是在传递给 getView 时标记到您的 convertView 的任何内容ListView 中的回收机制是随机的,可以与它之前显示的任何位置相关联。

要使您的应用程序正常工作,您必须为所有微调器创建 selectedItem 值数组,并将其作为成员附加到适配器。您必须更新每个 OnItemSelected 事件的相应值,并为每个“添加”按钮单击添加一个新值。当您在 getView 中准备 View 时,您只需将选定的微调器索引设置为数组中的相应值即可。

关于Android:当我动态添加新的 ListView 条目时,ListView 中的 Spinners 会丢失它们的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9149550/

相关文章:

java - 如何从 Android 中的 Activity 类中检索共享首选项到非 Activity 类中?

android - Gradle中每种产品 flavor 的属性

java - android ListView onclick

java - 将按钮添加到框架

java - Activity 关闭时运行代码

java - 在 DDMS View 中找不到 CSV 文件?

android - 在 ListView 中显示 firebase 子对象

Android SimpleCursorAdapter - 限制 ListView 结果

javascript - 如何在Javascript中动态制作按钮

html - 在表单中并排放置 html 按钮时出现问题