Reputation: 1037
In my app, I display a check list using a ListView
. Every row in my check list is represented by a model, which is an object of the ChecklistenPunkt
class. There are three different types of rows:
The third type has two Buttons
in it which are linked by two OnClickListeners
: The first Button
is for a positive answer, the second one for a negative answer. When the view is build, both of them are gray, indicating that this question is not yet answered. If the left Button
is clicked it turns green and the second one is getting a dark gray background. If the right Button
is clicked it turns red and the first one is getting a dark gray background. When a Button
is clicked the answering state is saved as an ChecklistenPunktStatus
. This is an Enum
which has three entries (okay, not okay, not answered).
Here is a little image of the Buttons
in three rows, showing the different states:
Here is my adapter code:
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;
}
}
EDIT:
When the convertView
is null, I create a new View
by inflating my layout. Then I create a new ViewHolder
, find the different TextViews
and Buttons
according to the Views
viewType
and put them into the ViewHolder
. After that, I set this ViewHolder
as the tag of the View
. I distinguish according to the viewType
again and set the text and Listeners of the Views inside the ViewHolder
. Then I return the view.
When the convertView
is not null I reuse the View. I get the ViewHolder
with the getTag()
method, set the text and Button state according to the model class and return the view at the end of the method.
My problem is that the answering state is correctly saved in the SparseArray
, but it is not displayed correctly. When I answer a question in the first rows of my list and then scroll down, answered questions appear at the end of the list. By scrolling up and down I can mess up the answering states completely. But while this is happening, the states in the sparseArray are always correct.
Am I missing something here?
Upvotes: 0
Views: 229
Reputation: 1768
I suppose there is something wrong with the code. When you use the same cell and when the view is not null you should reuse the same holder and not the convertView. Something like that:
ViewHolder viewHolder = new ViewHolder();
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
.
.
.
}
else {
viewHolder = convertView.getTag();
}
Upvotes: 1