问题
I have a DialogFragment which has a list view with CheckedTextView and a checkbox at the top to Check and uncheck all the items in the list view. I am trying to set the State of the CheckedTextView to Checked/Unchecked depending on the state of the CheckAll Check box. But i am not able to update the view accordingly using notifyDataSetChanged.
CategoriesDialogFragment.java
public class CategoriesDialogFragment extends SherlockDialogFragment {
CheckBox checkAll;
ListView categoriesListView;
CategoriesListAdapter adapter;
static Category category;
String[] categories = new String[] { "Hill Station", "Beach", "Historic",
"Wild Life", "Waterfall", "River", "Archeology", "Hill Station",
"Beach", "Historic", "Wild Life", "Waterfall", "River",
"Archeology" };
Boolean[] categories_state = new Boolean[] { true, false, true, true, true,
true, false, true, false, true, true, true, true, false };
public static CategoriesDialogFragment newInstance() {
CategoriesDialogFragment frag = new CategoriesDialogFragment();
Bundle args = new Bundle();
frag.setArguments(args);
return frag;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final Dialog dialog = new Dialog(MainActivity.context);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(R.layout.dialog_categories);
categoriesListView = (ListView) dialog
.findViewById(R.id.listViewDialog);
List<Category> theCategories = new ArrayList<Category>();
for (int i = 0; i < categories.length; i++) {
Boolean flag;
Category pl = new Category(categories[i], categories_state[i]);
theCategories.add(pl);
}
// categoriesListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
adapter = new CategoriesListAdapter(MainActivity.context,
R.layout.dialog_list_item_category, theCategories);
categoriesListView.setAdapter(adapter);
// List View Item Click Listener
categoriesListView
.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// TODO Auto-generated method stub
CategoriesListAdapter adapter = (CategoriesListAdapter) parent
.getAdapter();
Category c = (Category) adapter.getItem(position);
c.setChecked(!c.getChecked());
adapter.notifyDataSetChanged();
}
});
// CheckAll CheckBox
checkAll = (CheckBox) dialog.findViewById(R.id.checkBoxAll);
checkAll.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
Toast.makeText(MainActivity.context, "Check",
Toast.LENGTH_SHORT).show();
for (int i = 0; i < adapter.getCount(); i++) {
categoriesListView.setItemChecked(i, isChecked);
Log.i("Nomad", isChecked + " isChecked " + i);
}
adapter.notifyDataSetChanged();
/*
* if (isChecked) { Log.i("Nomad", "isChecked"); for (int i = 0;
* i < adapter.getCount(); i++) { category = adapter.getItem(i);
* category.setChecked(true); Log.i("Nomad", "isChecked "+i); }
* adapter.notifyDataSetChanged(); } else { Log.i("Nomad",
* "isUnChecked"); for (int i = 0; i < adapter.getCount(); i++)
* { category = adapter.getItem(i); category.setChecked(false);
* Log.i("Nomad", "isUnChecked "+i); }
* adapter.notifyDataSetChanged(); }
*/
}
});
return dialog;
}
private static class CategoriesListAdapter extends ArrayAdapter<Category> {
public Context mContext;
List<Category> mCategories;
public CategoriesListAdapter(Context context, int resource,
List<Category> categories) {
super(context, resource, categories);
// TODO Auto-generated constructor stub
this.mCategories = categories;
this.mContext = context;
}
public int getCount() {
return mCategories.size();
}
@Override
public Category getItem(int position) {
// TODO Auto-generated method stub
return mCategories.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
LayoutInflater viewInflater;
viewInflater = LayoutInflater.from(getContext());
convertView = viewInflater.inflate(
R.layout.dialog_list_item_category, null);
holder = new ViewHolder();
holder.categoryName = (CheckedTextView) convertView
.findViewById(R.id.categories_checkbox);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.categoryName.setText(mCategories.get(position)
.getCategoryName());
holder.categoryName.setChecked(mCategories.get(position)
.getChecked());
return convertView;
}
static class ViewHolder {
CheckedTextView categoryName;
}
}
}
Category.java
public class Category {
String categoryName = "";
private boolean checked = false;
public Category(String categoryName, boolean checked) {
this.categoryName = categoryName;
this.checked = checked;
}
public String getCategoryName() {
return categoryName;
}
public void setCategoryName(String categoryName) {
this.categoryName = categoryName;
}
public boolean getChecked() {
return checked;
}
public void setChecked(boolean checked) {
this.checked = checked;
}
}
dialog_categories.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/parentPanel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="8dip"
android:layout_marginStart="8dip"
android:background="@color/primary_white"
android:orientation="vertical" >
<LinearLayout
android:id="@+id/title_template"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="16dip"
android:layout_marginStart="16dip"
android:gravity="center_vertical|start"
android:orientation="horizontal"
android:paddingTop="5dp" >
<TextView
android:id="@+id/textView1"
style="?android:attr/textAppearanceLarge"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:paddingLeft="10dp"
android:text="@string/dialog_category_title"
android:textColor="@color/primary_color"
android:textSize="22sp" />
<TextView
android:id="@+id/all"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/dialog_category_checkbox"
android:textColor="@color/primary_color" />
<CheckBox
android:id="@+id/checkBoxAll"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="6dp" />
</LinearLayout>
<View
android:id="@+id/titleDivider"
android:layout_width="match_parent"
android:layout_height="2dip"
android:background="@color/black" />
<LinearLayout
android:id="@+id/contentPanel"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:minHeight="64dp"
android:orientation="vertical" >
<ListView
android:id="@+id/listViewDialog"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
<LinearLayout
android:id="@+id/buttonPanel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<Button
android:id="@+id/button_category_ok"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/dialog_category_btn_ok"
android:textSize="14sp" />
</LinearLayout>
</LinearLayout>
dialog_list_item_category.xml
<?xml version="1.0" encoding="utf-8"?>
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/categories_checkbox"
android:layout_width="fill_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:checkMark="?android:attr/listChoiceIndicatorMultiple"
android:gravity="center_vertical"
android:onClick="toggle"
android:paddingBottom="10dp"
android:paddingLeft="10dp"
android:paddingRight="12dp"
android:paddingTop="10dp"
android:text="sss" />
回答1:
I am trying to set the State of the CheckedTextView to Checked/Unchecked depending on the state of the CheckAll Check box. But i am not able to update the view accordingly using notifyDataSetChanged.
Added a sample with the question's code to as an example of my answers. It works and can be found here(have a look at it).
Also, Android-Developer's answer works because you'll basically reset the adapter with new items with the correct state each time the user checks/unchecks the all CheckBoxs
. This could be wasteful(but acceptable if the list is relatively small). Also keep in mind that if the categoryName
of the Category
class changes in the dialog you'll need to make sure you construct the new Categories
with the correct name(if you don't modify the category name then this isn't an issue) when the all CheckBox
is acted upon.
Try something like this:
- remove the
categoriesListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
if it's in your code modify the
OnCheckedChangeListener
for the check allCheckBox
like this:@Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { Toast.makeText(getActivity(), "Check", Toast.LENGTH_SHORT) .show(); Log.i("Nomad", "isChecked"); for (int i = 0; i < adapter.getCount(); i++) { adapter.getItem(i).setChecked(isChecked); Log.i("Nomad", "isChecked " + i); } adapter.notifyDataSetChanged(); }
add an
OnItemClickListener
to your categoriesListViewListView
like this:@Override public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) { CategoriesListAdapter adapter = (CategoriesListAdapter) arg0 .getAdapter(); Category c = (Category) adapter.getItem(arg2); c.setChecked(!c.getCheckStatus()); adapter.notifyDataSetChanged(); }
the
setChecked(boolean)
andgetCheckStatus()
(I see that you have aisChecked
method inCategory
you could use that for getting the boolean status) are methods in yourCategory
class for setting and getting the status of that itemin the
getView()
method of the adapter, set the status like this:holder.categoryName.setChecked(mCategories.get(position) .getCheckStatus());
回答2:
So you are trying to set all your items checked on your
setOnCheckedChangeListener
as I understand. First of all, if you want to make your
adapter.notifyDataSetChanged();
to work you have to make edits on your contents. You are using
List<Category> theCategories = new ArrayList<Category>();
to populate your dialog and to update it you have to use the same one with changed data or create a new adapter. To use the same one in your setOnCheckedChangeListener
you have to do something like this :
checkAll.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(isChecked){
theCategories.clear();
Toast.makeText(MainActivity.context, "Check", Toast.LENGTH_SHORT).show();
for (int i = 0; i < categories.length; i++) {
Category pl = new Category(categories[i], true);
theCategories.add(pl);
}
adapter.notifyDataSetChanged();
}
}
});
Try this and let me now if it works for you. : )
来源:https://stackoverflow.com/questions/14137760/notifydatasetchanged-fails-to-update-listview