问题
I have custom ListView. I'm using array adapter to fill my ListViews rows. It worked perfectly. When I select the ListView row, my checkedtextview become visible. After scrolling my checked situation disapper. How can i remember my checks ?
Thanks in helpings.
Here my Adapter
package test.cbsmobil.ibb;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CheckedTextView;
import android.widget.TextView;
import java.util.ArrayList;
public class ListViewItemsAdapter extends ArrayAdapter<Item> {
private Context context;
private ArrayList<Item> items;
private LayoutInflater vi;
private int resLayout;
private CheckedTextView ctv;
private int selectedIndex;
public ListViewItemsAdapter(Context context, ArrayList<Item> items) {
super(context, 0, items);
this.context = context;
this.items = items;
vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
selectedIndex = -1;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
final Item i = items.get(position);
if (i != null) {
if (i.isSection()) {
ListViewItemsSection si = (ListViewItemsSection) i;
v = vi.inflate(R.layout.list_item_section, null);
v.setOnClickListener(null);
v.setOnLongClickListener(null);
v.setLongClickable(false);
final TextView sectionView = (TextView) v.findViewById(R.id.list_item_section_text);
sectionView.setText(si.getTitle());
} else {
ListViewItems ei = (ListViewItems) i;
v = vi.inflate(R.layout.list_item_entry,null);
final TextView title = (TextView) v.findViewById(R.id.list_item_entry_title);
if (title != null)
title.setText(ei.title);
}
}
return v;
}
}
Here is my MainActivity; Let me explain this activitys code block. layerlist is my ListView. I use choice mode multiple for multiple selection in ListView.
layerlist.setAdapter(adapter);
layerlist.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
layerlist.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if(!items.get(position).isSection()){
ListViewItems item = (ListViewItems) items.get(position);
//adapter.setSelectedIndex(position);
Log.d("ListView", "Position " + item.toString());
//View v = layerlist.getChildAt(position);
View v = getViewByPosition(position,layerlist);
CheckedTextView ctv = (CheckedTextView) v.findViewById(R.id.ctv);
if (!ctv.isChecked()) {
ctv.setChecked(true);
Log.d("Checked", "Açıldı" + " " + ctv.isChecked());
} else {
ctv.setChecked(false);
Log.d("Checked", "Kapandı" + " " + ctv.isChecked());
}
}
}
});
return rootView;
}
private View getViewByPosition(int pos, ListView listView) {
final int firstListItemPosition = listView.getFirstVisiblePosition();
final int lastListItemPosition = firstListItemPosition + listView.getChildCount() - 1;
if (pos < firstListItemPosition || pos > lastListItemPosition ) {
return listView.getAdapter().getView(pos, null, listView);
} else {
final int childIndex = pos - firstListItemPosition;
return listView.getChildAt(childIndex);
}
}
回答1:
You should use use the "view holder" design pattern as described by developer.android.com and explained with details on this post.
The most important here is:
- Create the ViewHolder class;
- Store the ViewHolder instance in a tag if the convertView is null;
- Restore the ViewHolder instance from a tag if it is not.
That is my Adapter's code:
package br.com.inovant.pm;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.*;
import java.util.List;
public class ContactsAdapter extends ArrayAdapter<CheckedContact>{
public ContactsAdapter(Context context, List<CheckedContact> contacts) {
super(context, 0, contacts);
}
static class ViewHolder {
protected CheckedTextView checkedTextView;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(android.R.layout.select_dialog_multichoice, parent, false);
viewHolder = new ViewHolder();
viewHolder.checkedTextView = (CheckedTextView) convertView.findViewById(android.R.id.text1);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
final CheckedContact checkedContact = getItem(position);
final CheckedTextView checkedTextView = viewHolder.checkedTextView;
checkedTextView.setText(checkedContact.getContact().getDisplayName());
checkedTextView.setChecked(checkedContact.isChecked());
return convertView;
}
@Override
public long getItemId(int position) {
return getItem(position).getContact().getId().hashCode();
}
@Override
public boolean hasStableIds() {
return true;
}
}
回答2:
I was got same problem so, i had used following methods in my custom adapter, i got solution.
Add following methods inside your ListViewItemsAdapter:
@Override
public int getCount() {
return alUpgradeTour.size();
}
@Override
public int getItemViewType(int position) {
return position;
}
@Override
public int getViewTypeCount() {
return getCount();
}
Try it, you will also get solution.
回答3:
Android's ListView recycles all its individual views, that is, when a list item is scrolled off of the screen its view is recycled to be used by the one that just scrolled into the visible screen area. Now when an older list item is scrolled back into view it gets some other recycled view to draw itself in. Because of this the checkmark is lost or any data that was changed / updated, for that matter.
The solution to this is you save your changes in the list item, in your case - ListViewItems. Say you have a flag boolean isChecked = false
in the class definition of ListViewItems and in the onItemClick where you call the setChecked method, set isChecked = true
This will help you persist the check mark.
Hope it helps.
来源:https://stackoverflow.com/questions/28714738/checkedtextview-disappears-when-scroll-in-listview