NotifyDataSetChanged не обновляет ListView

У меня есть DialogFragment, который имеет вид списка с CheckedTextView и флажок вверху, чтобы проверить и снять отметку со всех элементов в представлении списка. Я пытаюсь установить состояние CheckedTextView на Checked / Unchecked в зависимости от состояния флажка CheckAll. Но я не могу обновить представление соответственно, используя 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" /> 

Я пытаюсь установить состояние CheckedTextView на Checked / Unchecked в зависимости от состояния флажка CheckAll. Но я не могу обновить представление соответственно, используя notifyDataSetChanged.

В качестве примера моих ответов добавлен образец с кодом вопроса. Он работает и может быть найден здесь (посмотрите на него).

Кроме того, ответ разработчика Android-разработчика работает, потому что вы в основном перезагружаете адаптер с новыми элементами с правильным состоянием каждый раз, когда пользователь проверяет / отменяет выбор всех CheckBoxs . Это может быть расточительным (но приемлемым, если список относительно невелик). Также имейте в виду, что если класс categoryName в классе Category изменяется в диалоговом окне, вам необходимо убедиться, что вы создаете новые Categories с правильным именем (если вы не изменяете название категории, это не проблема) Когда действует вся CheckBox .

Попробуйте что-то вроде этого:

  1. Удалите categoriesListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); Если это в вашем коде
  2. OnCheckedChangeListener для проверки всех CheckBox следующим образом:

      @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(); } 
  3. Добавьте OnItemClickListener в свои категории ListView следующим образом:

      @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(); } 
  4. setChecked(boolean) и getCheckStatus() (я вижу, что у вас есть метод isChecked в Category вы могли бы использовать для получения логического статуса) – это методы в вашем классе Category для настройки и получения статуса этого элемента

  5. В getView() адаптера установите такой статус:

     holder.categoryName.setChecked(mCategories.get(position) .getCheckStatus()); 

Таким образом, вы пытаетесь установить все свои элементы на своем

setOnCheckedChangeListener

насколько я понимаю. Прежде всего, если вы хотите сделать свой

adapter.notifyDataSetChanged();

Чтобы работать, вы должны внести изменения в свое содержание. Ты используешь

List<Category> theCategories = new ArrayList<Category>();

Для заполнения вашего диалога и для его обновления вы должны использовать тот же самый с измененными данными или создать новый адаптер. Чтобы использовать тот же самый в своем setOnCheckedChangeListener вам нужно сделать что-то вроде этого:

 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(); } } }); 

Попробуйте это и позвольте мне теперь, если он сработает для вас. 🙂

В вашем цикле for

 for (int i = 0; i < adapter.getCount(); i++) { CategoriesListAdapter adapter = (CategoriesListAdapter) parent.getAdapter(); Category c = (Category) adapter.getItem(i); c.setChecked(!c.getChecked()); }