与 ListView 战斗

Posted

技术标签:

【中文标题】与 ListView 战斗【英文标题】:Fighting with ListView 【发布时间】:2015-09-27 19:46:34 【问题描述】:

我的应用程序的一个片段中有一个ListView,还有一个按钮。

按钮显示一个对话框,显示一些CheckBoxes 供用户选择他/她希望将哪些添加到ListView

这行得通,当用户单击checkBox 时,该项目被添加到列表中,但是如果我单击所有checkBoxesListView 中的最后一个项目将获得第一个的文本一。

这是我的适配器:

public class ListaTributosAdapter extends BaseAdapter 

private ArrayList<ListaTributosBean> data;
private LayoutInflater inflater=null;

public ListaTributosAdapter(Context c, ArrayList<ListaTributosBean> data)

    this.data=data;
    inflater=LayoutInflater.from(c);

@Override
public int getCount() 
    return data.size();


@Override
public Object getItem(int position) 
    return data.get(position);


@Override
public long getItemId(int position) 
    return position;


@Override
public View getView(int position, View convertView, ViewGroup parent) 


    if (convertView == null) 
        convertView=inflater.inflate(R.layout.celda_listview_tributos, null);
        TextView texto=(TextView)convertView.findViewById(R.id.textView4);
        texto.setText(data.get(position).getTexto());
    

    return convertView;


ListaTributosBean 是一个只有一个 TextView 和一个 ImageView 的类,此时未使用。

这就是我设置适配器的方式,我有一个 Strings 和一个 ArrayList 数组来存储用户使用

复选框:

private String[] opciones="A", "B", "C", "D", "E";
private ArrayList<ListaTributosBean> datos;

我将适配器设置为 ListView:

adapter=new ListaTributosAdapter(c, datos);
listView.setAdapter(adapter);

我在 ArrayList 中添加了两个强制项:

datos.add(new ListaTributosBean("Mandatory1"));
datos.add(new ListaTributosBean("Mandatory2"));

当用户单击一个按钮时,会显示带有 checkBoxesDialog

button.setOnClickListener(new View.OnClickListener() 
        @Override
        public void onClick(View v) 

            AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
            builder.setTitle(getString(R.string.selectcheckboxes));
            builder.setMultiChoiceItems(opciones, null, new DialogInterface.OnMultiChoiceClickListener() 


                @Override
                public void onClick(DialogInterface dialog, int which, boolean isChecked) 

                    for (int i = 0; i < datos.size(); i++) 

                        if (datos.get(i).getTexto().equals(opciones[which])) 
                            Toast.makeText(c, getString(R.string.contains1) + " " + opciones[which] + " " + getString(R.string.contains2), Toast.LENGTH_LONG).show();
                            repe = true;
                         


                    
                    if (repe == true) 

                        repe = false;

                     else 
                        if (isChecked) 
                            datos.add(new ListaTributosBean(opciones[which]));

                        
                    

                
            );

            builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() 
                @Override
                public void onClick(DialogInterface dialog, int which) 

                    adapter.notifyDataSetChanged();
                    try 
                        dialog.dismiss();
                     catch (Exception e) 

                    
                
            ).create().show();
        
    );

如果我点击一个checkBox,没问题。我点了两个checkBoxes,没问题。

但如果我检查所有五个 checkBoxesListView 中的最后一项会得到第一个的文本,尽管我点击它,然后做

String selected = ((ListaTributosBean) parent.getItemAtPosition(position)).getTexto();

它返回正确的值。

ListView 中的其余项目看起来不错,并且在单击时响应正常。

为什么会这样?

谁能帮帮我?

谢谢。

【问题讨论】:

首先你的getView实现是错误的......如果你只使用1个textview然后把它作为标签到convertView......就像TextView txt = null; if (convertView == null) /*old code here (without setText)*/ txt = (TextView)convertView.findViewById(R.id.textView4); convertView.setTag(txt); else txt = (TextView)convertView.getTag(); txt.setText(data.get(position).getTexto());......如果你正在使用更多的意见使用持有人pattern ...接下来看看ArrayAdapter ...有一个Filter实现 【参考方案1】:

这个错误是因为您没有遵循Adapter 中的ViewHolder 设计模式。现在执行以下操作 添加下面的类作为你的Adapter的内部类

static class ViewHolder 
        public TextView texto;

并将适配器的 getView() 方法替换为以下内容

 @Override
    public View getView(int position, View convertView, ViewGroup parent) 
        ViewHolder holder;
        if (convertView == null) 
            convertView = inflater.inflate(R.layout.celda_listview_tributos, null);
            holder = new ViewHolder();
            holder.texto = (TextView) convertView.findViewById(R.id.textView4);
            convertView.setTag(holder);
         else 
            holder = (ViewHolder) convertView.getTag();
        
        holder.texto.setText(data.get(position).getTexto());
        return convertView;
    

【讨论】:

它现在工作正常。谢谢!我需要阅读 ViewHolder 模式,我一直在做没有它的适配器。是时候阅读了:)

以上是关于与 ListView 战斗的主要内容,如果未能解决你的问题,请参考以下文章

如何得到listview的总列数与总行数

布局与控件-ListView知多少(上)

ScrollView与ListView的冲突

ListView,减少 ListView 中一个元素与另一个元素之间的空间

Android listview 的用法? 越详细越好。

android ListView 与GridView 学习总结