Listview containing checkbox and text is getting r

2020-02-16 05:11发布

问题:

I have drawn a customized navigation drawer with ListView and header but when i scroll the List the checkbox in the List are getting unchecked.

Secondly when i click on the reset button in the header part I want that all the checkbox in the Listview should get get unchecked. I have been trying this to get it working but unable to find any solution..

The snippets are

public class NavigationDrawer extends Fragment{
   @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.filter_navigation_drawer, container,false);
        drawerListView= ( ListView ) view.findViewById( R.id.listDrawer );
        drawerListView.setOnItemClickListener(new FilterDrawerItemClickListener());

        dataList.add(new FilterDrawerItem("sample1",true));
        dataList.add(new FilterDrawerItem("sample2",true));
        dataList.add(new FilterDrawerItem("sample3",true));
        dataList.add(new FilterDrawerItem("sample4",true));
        dataList.add(new FilterDrawerItem("sample5",true));
        dataList.add(new FilterDrawerItem("sample2",true));
        dataList.add(new FilterDrawerItem("sample2",true));
        dataList.add(new FilterDrawerItem("sample2",true));
        dataList.add(new FilterDrawerItem("sample2",true));

        adapter = new FilterCustomDrawerAdapter(getActivity(), R.layout.drawer_filter,dataList,drawerStatus);
        drawerListView.setAdapter(adapter);
        adapter.getFilterList();

        resetBtn = (TextView)view.findViewById(R.id.filterby_reset);
        if(resetBtn != null){
            resetBtn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    application.setFilterStatus("reset");
                    for(int i=0; i<dataList.size(); i++){
                       dataList.get(i).setCheckBoxId(false);
                    }
                    adapter.notifyDataSetChanged();
                    // this.onCreateView();
                }
            });
        }

        return view;
    }
}

FilterCustomDrawerAdapter.java

public class FilterCustomDrawerAdapter extends ArrayAdapter<FilterDrawerItem> {

    Context context;
    List<FilterDrawerItem> drawerItemList;
    int layoutResID;
    int item = 0;
    String status;
    List<Integer> filterList = new ArrayList<Integer>();
    DrawerStatus drawerStatus;
    StataApplication application = StataApplication.getInstance();

    HashMap<Integer, Boolean> checked;   // newly added code

    public FilterCustomDrawerAdapter(Context context, int layoutResourceID,
                                     List<FilterDrawerItem> listItems,DrawerStatus drawerStatus) {
        super(context, layoutResourceID, listItems);
        this.context = context;
        this.drawerItemList = listItems;
        this.layoutResID = layoutResourceID;
        this.drawerStatus = drawerStatus;
        checked = new HashMap<Integer, Boolean>(getCount());
    }

    public FilterCustomDrawerAdapter(Context context, int layoutResourceID,
                                     List<FilterDrawerItem> listItems) {
        super(context, layoutResourceID, listItems);
        this.context = context;
        this.drawerItemList = listItems;
        this.layoutResID = layoutResourceID;
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        // TODO Auto-generated method stub

        final FilterDrawerItemHolder drawerHolder;
        View view = convertView;

        if (view == null) {
            LayoutInflater inflater = ((Activity) context).getLayoutInflater();
            drawerHolder = new FilterDrawerItemHolder();

            view = inflater.inflate(layoutResID, parent, false);
            drawerHolder.ItemName = (TextView) view.findViewById(R.id.drawer_filterName);
            drawerHolder.checkBox = (CheckBox) view.findViewById(R.id.drawer_cbox);

            view.setTag(drawerHolder);
        } else {
            drawerHolder = (FilterDrawerItemHolder) view.getTag();
        }

        FilterDrawerItem dItem = (FilterDrawerItem) this.drawerItemList.get(position);

        drawerHolder.ItemName.setText(dItem.getItemName());
        TextView resetView = (TextView)view.findViewById(R.id.filterby_reset);
        CheckBox checkBox = (CheckBox) view.findViewById(R.id.drawer_cbox);

        // Newly added code
        Boolean isChecked = checked.get(position);
        checkBox.setChecked(isChecked == null ? false : isChecked);

      // if(application.getFilterStatus() != null) {
           if(checkBox.isChecked()){
               drawerHolder.checkBox.setChecked(false);
           }
      // }

        checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) {
                if (isChecked) {
                    filterList.add(new Integer(position));
                    checked.put(position, true);
                } else {
                    filterList.remove(new Integer(position));
                    checked.put(position, false);
                }
            }
        });

        drawerHolder.checkBox.setTag(position);
        Log.d("FILTER_LIST_SIZE",String.valueOf(filterList.size()));

        return view;
    }

    private static class FilterDrawerItemHolder {
        TextView ItemName;
        CheckBox checkBox;
    }

    public List<Integer> getFilterList(){
        return filterList;
    }
}

In the image below when I scroll the list and if i make the checkbox sample1 and sample 2 checked it becomes unchecked on scrolling. and also on clicking reset button in the header i want all my checkbox to be unchecked.. Not able to get this working ...

UPDATE 1

 resetBtn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    List<FilterDrawerItem> adapterDataList = adapter.getDrawerItemList();
                    for(int i=0; i<adapterDataList.size(); i++){  // At this place i am getting the size as 9
                        adapterDataList.get(i).setCheckBoxId(false);
                    }
                    adapter.setDrawerItemList(adapterDataList);
                    adapter.notifyDataSetChanged();
                }
            });

回答1:

It because of recycling use of views in ListView. You should create some HashMap:

HashMap<Integer, Boolean> checked;

Then in your constructor do this:

checked = new HashMap<Integer, Boolean>(getCount());

After set OnCheckedChangeListener on your checkboxes, and in event method do this:

checked.put(position, yourCheckBoxCheckedState);

And in getView() method do this:

Boolean isChecked = checked.get(position);
checkBox.setChecked(isChecked == null ? false : isChecked)

Try this, I think it should help

UPDATE

resetBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                adapter.deselectAll();
            }
        });

Then in adapter create method:

 public void deselectAll() {
   checked = new HashMap<Integer, Boolean>(getCount());
   notifyDataSetChanged();
 }


回答2:

In your FilterDrawerItem class, make a boolean variable isChecked.

Now in your adapter class, write something like this:

if(dItem.isChecked){
    drawerHolder.checkBox.setChecked(true);
}
else{
    drawerHolder.checkBox.setChecked(false);
}

and in your OnCheckedChangeListener:

if (isChecked) {
    //your other code
    dItem.setChecked(true);
    notifyDataSetChanged();
} else {
    //your other code
    dItem.setChecked(false);
    notifyDataSetChanged();
}

@Orest Savchak's answer is also right, but keeping track of checkboxes in your POJO classes will help you to retrieve the checked items later and also do other things easier, like you want to uncheck all the checkboxes on click of "Reset" button. For that, in onClick() on reset button, you'll just need to do:

for(int i=0; i<FilterDrawerItem.size; i++){
    FilterDrawerItem.get(i).setChecked(false);
}
adapterObject.notifyDataSetChanged();

EDIT 1:

Create getter setter for drawerItemList in your adapter and then in onClick() of reset button, in place of dataList, do as following:

List<FilterDrawerItem> adapterDataList=adapter.getDataList();
for(int i=0; i<adapterDataList.size(); i++){
    adapterDataList.get(i).setCheckBoxId(false);
}
adapter.setDataList(adapterDataList);
adapter.notifyDataSetChanged();