0

I have an Activity that inflates a List of fragments that contain 2 text boxes and a checkbox. My list populates fine, but when I check the checkbox, it references to the last fragment called by getView() instead of its correlating fragment (IE when I check Box 2, box 8 would expand if it was the last item called by getView() on the list) How do I fix this? Code follows:

 package com.bango.chdebug;

import java.util.ArrayList;
import java.util.UUID;

import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ListView;
import android.widget.TextView;

public class VoteListFragment extends ListFragment {
    private ArrayList<MediaItem> myML;
    public static boolean myCheckBoxState = false;
    private ArrayList<UUID> voteList;
    private MediaItem temp;
    private int maxVote = 0;
    private CheckBox voteBox;
    public static String VOTE_KEY = "vote";
    public String TAG = "NewMediaList";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        temp = new MediaItem();
        if(savedInstanceState != null){
        myCheckBoxState = savedInstanceState.getBoolean(VOTE_KEY, false);
        }
        getActivity().setTitle("New Movie List");
        voteList = new ArrayList<UUID>();
        myML = MediaDB.get(getActivity()).getVoteMediaItems();
        MediaAdapter medAdapt = new MediaAdapter(myML);
        setListAdapter(medAdapt);
    }

    private class MediaAdapter extends ArrayAdapter<MediaItem> {
        public MediaAdapter(ArrayList<MediaItem> mediaItems) {
            super(getActivity(), 0, mediaItems);
            // mediaItems = parseOfficialList(mediaItems);
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            // TODO Auto-generated method stub
            if (convertView == null) {
                convertView = getActivity().getLayoutInflater().inflate(
                        R.layout.new_media_list_item, null);
            }
            temp = getItem(position);
            TextView medTitle = (TextView) convertView
                    .findViewById(R.id.vote_media_title);
            TextView medDate = (TextView) convertView
                    .findViewById(R.id.vote_media_date);
            voteBox = (CheckBox) convertView
                    .findViewById(R.id.vote_media_cb);
            medTitle.setText(temp.getMyTitle());
            voteBox.setEnabled(true);
            voteBox.setOnCheckedChangeListener(new OnCheckedChangeListener(){
                @Override
                public void onCheckedChanged(CompoundButton buttonView,
                        boolean isChecked) {
                    // TODO Auto-generated method stub
                    Log.d("onresume", "On Check called for " + temp.getMyTitle());  
                }
            });
            return convertView;
        }   
    }   
    }

1 Answers1

0

This question have been asked number of times already, refer to listview-checkbox-trouble, listview-with-checkbox-and-all-clickable or get-selected-item-using-checkbox-in-listview.

There's absolutely no warranty that last call to getView() should happen to clicked CheckBox. It's not mentioned in any documentation / example, so you shouldn't rely on that. Your list it's just view to show data. Data itself should be stored in different entity. In your code that entity is not used. You should store checked / not checked state in it and store back reference in view (e.g. data position in storage).

Here's slightly reworked fragment presented below. Please note, that I've added new checked field to MediaItem in order to store checkbox state. You can use separate array to store that state if needed.

public class VoteListFragment extends ListFragment {
    private ArrayList<MediaItem> myML;
    public static boolean myCheckBoxState = false;
    private ArrayList<UUID> voteList;
    private MediaItem temp;
    private int maxVote = 0;
    private CheckBox voteBox;
    public static String VOTE_KEY = "vote";
    public String TAG = "NewMediaList";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        temp = new MediaItem("item");
        if(savedInstanceState != null){
            myCheckBoxState = savedInstanceState.getBoolean(VOTE_KEY, false);
        }
        getActivity().setTitle("New Movie List");
        voteList = new ArrayList<UUID>();
        myML = getVoteMediaItems(getActivity());
        MediaAdapter medAdapt = new MediaAdapter(myML);
        setListAdapter(medAdapt);
    }

    private ArrayList<MediaItem> getVoteMediaItems(final Activity activity) {
        final ArrayList<MediaItem> items = new ArrayList<MediaItem>();

        for (int i = 0; i < 100; i++) {
            items.add(new MediaItem(String.valueOf(i) + " item"));
        }

        return items;
    }

    private class MediaAdapter extends ArrayAdapter<MediaItem> {

        private CompoundButton.OnCheckedChangeListener mCheckedListener = new CompoundButton.OnCheckedChangeListener(){
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                Integer position = (Integer) buttonView.getTag();

                if (position != null) {
                    Toast.makeText(getActivity(), "On Check called for " + getItem(position).getMyTitle(), Toast.LENGTH_LONG).show();
                    getItem(position).checked = isChecked;
                }
            }
        };

        public MediaAdapter(ArrayList<MediaItem> mediaItems) {
            super(getActivity(), 0, mediaItems);
            // mediaItems = parseOfficialList(mediaItems);
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            // TODO Auto-generated method stub
            if (convertView == null) {
                convertView = getActivity().getLayoutInflater().inflate(
                        R.layout.new_media_list_item, null);
            }

            temp = getItem(position);

            // Consider using of ViewHolder pattern instead of call findViewById() to improve performance
            TextView medTitle = (TextView) convertView
                    .findViewById(R.id.vote_media_title);
            TextView medDate = (TextView) convertView
                    .findViewById(R.id.vote_media_date);
            voteBox = (CheckBox) convertView
                    .findViewById(R.id.vote_media_cb);
            medTitle.setText(temp.getMyTitle());
            voteBox.setEnabled(true);
            voteBox.setOnCheckedChangeListener(null);
            voteBox.setChecked(temp.checked);
            voteBox.setTag(position);

            voteBox.setOnCheckedChangeListener(mCheckedListener);
            return convertView;
        }
    }

    public class MediaItem {
        private String myTitle;
        // Newly added field
        private boolean checked = false;

        MediaItem(String title) {
            myTitle = title;
        }

        public String getMyTitle() {
            return myTitle;
        }
    }
}
Community
  • 1
  • 1
sandrstar
  • 12,503
  • 8
  • 58
  • 65