如何在listview中保存视图状态

时间:2014-01-17 14:55:28

标签: java android listview android-listview

在我的应用中,我使用ListView显示检查列表。我的检查列表中的每一行都由一个模型表示,该模型是ChecklistenPunkt类的一个对象。有三种不同类型的行:

  1. 标题
  2. 附加文字
  3. 一个问题
  4. 第三种类型中有两个Buttons,由两个OnClickListeners链接:第一个Button用于肯定答案,第二个用于否定答案。构建视图时,它们都是灰色的,表示此问题尚未得到解答。如果单击左Button则变为绿色,第二个变为深灰色背景。如果单击右Button,它将变为红色,第一个变为深灰色背景。单击Button时,应答状态将另存为ChecklistenPunktStatus。这是一个Enum,有三个条目(好的,不行,没有回答)。

    以下是三行Buttons的小图片,显示了不同的状态:

    enter image description here

    这是我的适配器代码:

    public class ChecklisteAdapter extends ArrayAdapter<Object> {
    
        private List<ChecklistenPunkt> list;
        private SparseArray<ChecklistenPunktStatus> sparseArray;
        private Context context;
    
        public ChecklisteAdapter(Context context, List<ChecklistenPunkt> objects) {
            super(context, 0);
            list = objects;
            sparseArray = new SparseArray<ChecklistenPunktStatus>();
            for (int i = 0; i < list.size(); i++) {
                sparseArray.put(i, ChecklistenPunktStatus.NICHT_SELEKTIERT);
            }
            this.context = context;
        }
    
        @Override
        public int getCount() {
            return list.size();
        }
    
        @Override
        public ChecklistenPunkt getItem(int position) {
            return list.get(position);
        }
    
        @Override
        public int getItemViewType(int position) {
            ChecklistenPunkt p = (ChecklistenPunkt) list.get(position);
            return p.getTyp();
        }
    
        @Override
        public int getViewTypeCount() {
            return 3;
        }
    
        @Override
        public View getView(final int position, View convertView, ViewGroup parent) {
            View v = null;
            int type = getItemViewType(position);
            if (convertView == null) {
                LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                final ViewHolder viewHolder = new ViewHolder();
                switch (type) {
                    case Util.CHECKLISTE_FRAGE:
                        v = inflater.inflate(R.layout.pruefung_durchfuehren_list_item_frage, null);
                        viewHolder.nummer = (TextView) v.findViewById(R.id.check_nummer);
                        viewHolder.komponente = (TextView) v.findViewById(R.id.check_komponente);
                        viewHolder.funktion = (TextView) v.findViewById(R.id.check_funktion);
                        viewHolder.kriterium = (TextView) v.findViewById(R.id.check_kriterium);
                        viewHolder.erlaeuterung = (TextView) v.findViewById(R.id.check_erlaeuterung);
                        viewHolder.io = (Button) v.findViewById(R.id.button_i_o);
                        viewHolder.nio = (Button) v.findViewById(R.id.button_n_i_o);
                        viewHolder.io.setOnClickListener(new OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                viewHolder.io.setBackgroundColor(Color.GREEN);
                                viewHolder.io.setEnabled(false);
                                viewHolder.nio.setBackgroundColor(Color.GRAY);
                                viewHolder.nio.setEnabled(true);
                                sparseArray.put(position, ChecklistenPunktStatus.IN_ORDNUNG);
                            }
                        });
                        viewHolder.nio.setOnClickListener(new OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                viewHolder.nio.setBackgroundColor(Color.RED);
                                viewHolder.nio.setEnabled(false);
                                viewHolder.io.setBackgroundColor(Color.GRAY);
                                viewHolder.io.setEnabled(true);
                                sparseArray.put(position, ChecklistenPunktStatus.NICHT_IN_ORDNUNG);
                            }
                        });
                        ChecklistenPunktStatus status = sparseArray.get(position);
                        if (status == ChecklistenPunktStatus.IN_ORDNUNG) {
                            viewHolder.io.setBackgroundColor(Color.GREEN);
                            viewHolder.io.setEnabled(false);
                            viewHolder.nio.setBackgroundColor(Color.GRAY);
                            viewHolder.nio.setEnabled(true);
                        } else if (status == ChecklistenPunktStatus.NICHT_IN_ORDNUNG) {
                            viewHolder.nio.setBackgroundColor(Color.RED);
                            viewHolder.nio.setEnabled(false);
                            viewHolder.io.setBackgroundColor(Color.GRAY);
                            viewHolder.io.setEnabled(true);
                        } else if (status == ChecklistenPunktStatus.NICHT_SELEKTIERT) {
                            viewHolder.nio.setBackgroundColor(Color.parseColor("#cccccc"));
                            viewHolder.nio.setEnabled(true);
                            viewHolder.io.setBackgroundColor(Color.parseColor("#cccccc"));
                            viewHolder.io.setEnabled(true);
                        }
    
                        v.setTag(viewHolder);
                        break;
                    case Util.CHECKLISTE_UEBERSCHRIFT:
                        v = inflater.inflate(R.layout.pruefung_durchfuehren_list_item_head, null);
                        viewHolder.headline = (TextView) v.findViewById(R.id.check_headline);
                        viewHolder.headnummer = (TextView) v.findViewById(R.id.check_headnummer);
                        v.setTag(viewHolder);
                        break;
                    case Util.CHECKLISTE_ZUSATZTEXT:
                        v = inflater.inflate(R.layout.pruefung_durchfuehren_list_item_text, null);
                        viewHolder.text = (TextView) v.findViewById(R.id.check_text);
                        viewHolder.textnummer = (TextView) v.findViewById(R.id.check_textnummer);
                        v.setTag(viewHolder);
                        break;
                    default:
                        throw new IllegalArgumentException("ViewType " + type + " unbekannt!");
                }
            } else {
                v = convertView;
            }
    
            ChecklistenPunkt clp = getItem(position);
            ViewHolder viewHolder = (ViewHolder) v.getTag();
            if (clp != null) {
                switch (type) {
                    case Util.CHECKLISTE_FRAGE: {
                        viewHolder.nummer.setText(clp.getNummer());
                        viewHolder.komponente.setText(clp.getKomponente());
                        viewHolder.funktion.setText(clp.getFunktion());
                        viewHolder.kriterium.setText(clp.getKriterium());
                        viewHolder.erlaeuterung.setText(clp.getErlaeuterung());
                        ChecklistenPunktStatus status = sparseArray.get(position);
                        if (status == ChecklistenPunktStatus.IN_ORDNUNG) {
                            viewHolder.io.setBackgroundColor(Color.GREEN);
                            viewHolder.io.setEnabled(false);
                            viewHolder.nio.setBackgroundColor(Color.GRAY);
                            viewHolder.nio.setEnabled(true);
                        } else if (status == ChecklistenPunktStatus.NICHT_IN_ORDNUNG) {
                            viewHolder.nio.setBackgroundColor(Color.RED);
                            viewHolder.nio.setEnabled(false);
                            viewHolder.io.setBackgroundColor(Color.GRAY);
                            viewHolder.io.setEnabled(true);
                        } else if (status == ChecklistenPunktStatus.NICHT_SELEKTIERT) {
                            viewHolder.nio.setBackgroundColor(Color.parseColor("#cccccc"));
                            viewHolder.nio.setEnabled(true);
                            viewHolder.io.setBackgroundColor(Color.parseColor("#cccccc"));
                            viewHolder.io.setEnabled(true);
                        }
                        break;
                    }
                    case Util.CHECKLISTE_UEBERSCHRIFT: {
                        viewHolder.headline.setText(clp.getHeadline());
                        viewHolder.headnummer.setText(clp.getNummer());
                        break;
                    }
                    case Util.CHECKLISTE_ZUSATZTEXT: {
                        viewHolder.text.setText(Html.fromHtml(clp.getZusatz()));
                        viewHolder.textnummer.setText(clp.getNummer());
                        break;
                    }
                    default:
                        throw new IllegalArgumentException("ViewType " + type + " unbekannt!");
                }
            }
            return v;
        }
    
        public SparseArray<ChecklistenPunktStatus> getSparseArray() {
            return sparseArray;
        }
    
        static class ViewHolder {
            protected TextView nummer;
            protected TextView komponente;
            protected TextView kriterium;
            protected TextView funktion;
            protected TextView erlaeuterung;
            protected TextView text;
            protected TextView textnummer;
            protected TextView headline;
            protected TextView headnummer;
            protected Button io;
            protected Button nio;
        }
    }
    

    编辑:

    convertView为空时,我通过为我的布局充气来创建新的View。然后,我创建一个新的ViewHolder,根据TextViews Buttons找到不同的ViewsviewType,并将它们放入ViewHolder。之后,我将此ViewHolder设置为View的标记。我再次根据viewType进行区分,并在ViewHolder内设置视图的文本和监听器。然后我返回视图。

    convertView不为null时,我重用View。我使用ViewHolder方法获取getTag(),根据模型类设置文本和按钮状态,并返回方法末尾的视图。

    我的问题是,应答状态已正确保存在SparseArray中,但无法正确显示。当我在列表的第一行回答问题然后向下滚动时,回答的问题会出现在列表的末尾。通过向上和向下滚动,我可以完全搞乱回答状态。但是当发生这种情况时,sparseArray中的状态总是正确的。

    我在这里错过了什么吗?

1 个答案:

答案 0 :(得分:1)

我认为代码有问题。当您使用相同的单元格并且视图不为null时,您应该重用相同的持有者而不是convertView。这样的事情:

ViewHolder viewHolder = new ViewHolder();
if (convertView == null) {
    LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    .
    .
    .
} 
else {
    viewHolder = convertView.getTag();
}