Scrolling error


#1

When I scroll down and then back up on the CrimesListActivity, my checked values get all messed up. See pictures here: http://imgur.com/a/ax0c5. Below is my code for CrimeListFragment.java.

package com.icsfl.aschiff.criminalintent;

import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.view.View;
import android.view.ViewGroup;
import android.widget.*;

import java.util.ArrayList;

/**
 * Created by aschiff on 8/25/2014.
 */
public class CrimeListFragment extends ListFragment {
    private ArrayList<Crime> mCrimes;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getActivity().setTitle(R.string.crimes_title);
        mCrimes = CrimeLab.getCrimeLab(getActivity()).getCrimes();
        CrimeAdapter adapter = new CrimeAdapter(mCrimes);
        setListAdapter(adapter);
    }

    @Override
    public void onListItemClick(ListView listView, View view, int position, long id) {
        Crime crime = ((CrimeAdapter) getListAdapter()).getItem(position);
        Intent intent = new Intent(getActivity(), CrimePagerActivity.class);
        intent.putExtra(CrimeFragment.EXTRA_CRIME_ID, crime.getId());
        startActivity(intent);
    }

    @Override
    public void onResume() {
        super.onResume();
        ((CrimeAdapter) getListAdapter()).notifyDataSetChanged();
    }

    private class CrimeAdapter extends ArrayAdapter<Crime> {
        public CrimeAdapter(ArrayList<Crime> crimes) {
            super(getActivity(), android.R.layout.simple_list_item_1, crimes);
        }

        @Override
        public View getView(int position, View convertView, ViewGroup Parent) {
            if (convertView == null) {
                convertView = getActivity().getLayoutInflater().inflate(R.layout.list_item_crime, null);
            }
            final Crime crime = getItem(position);
            TextView titleTextView = (TextView) convertView.findViewById(R.id.crime_list_item_title_text_view);
            titleTextView.setText(crime.getTitle());
            TextView dateTextView = (TextView) convertView.findViewById(R.id.crime_list_item_date_text_view);
            dateTextView.setText(crime.getDateString());
            CheckBox solvedCheckBox = (CheckBox) convertView.findViewById(R.id.crime_list_item_solved_check_box);
            solvedCheckBox.setChecked(crime.isSolved());
            solvedCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    crime.setSolved(isChecked);
                }
            });
            return convertView;
        }
    }
}

Note that I have added the following code to what the book has:

            final Crime crime = getItem(position);

...

            solvedCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    crime.setSolved(isChecked);
                }
            });

This is because I was having trouble with the solved check boxes being saved when rotating views and when scrolling down. Is there another method of saving the checkboxes when rotating views or scrolling down then back up?

Here is my full code https://github.com/AlexanderSchiff/CriminalIntent. Thanks!


#2

I think part of the problem is that you’re setting the checkbox Listener in getView method of the adapter class. Every time you scroll the list, getView is called, and in effect, you’re registering the Listener all over again. Event handlers are usually set in the onCreate and onCreateView lifecycle methods.


#3

Okay, I have deleted the solvedCheckBox.setOnCheckedChangeListener method and reverted final Crime crime to just be Crime crime

So now when I hit a check box on the list screen, then view the same crime, the crime does not update. Which piece of code handles the communication between the list fragment and the crime fragment when a checkbox is hit?


#4

I’m not sure what part of the chapter you’re currently on and it’s been a while since I completed the entire Criminal Intent app. Looking over my code, there is a Callbacks interface defined in CrimeFragment and implemented in CrimeListFragment to handle update notifications. But this probably gets implemented later on in the book.


#5

I just finished with chapter 11. Maybe the authors can address whether a clicked checkbox on the CrimeListFragment is supposed to update the Crime on the CrimeFragment by chapter 11? And if so, how is it implemented? I have compared my code to the authors’ sample code and it looks almost the same, besides some formatting and naming conventions.


#6

This is what’s causing your checkboxes to be alternately checked:

private CrimeLab(Context appContext) { mAppContext = appContext; mCrimes = new ArrayList<Crime>(); for (int i = 0; i < 100; i++) { Crime crime = new Crime(); crime.setTitle("Crime #" + i); crime.setSolved(i % 2 == 0); mCrimes.add(crime); } }

This gets cleaned up in Ch 16 (pages 261-262).


#7

The problem I am now facing is that the checkboxes on the list do not seem to do anything. If you click one, then scroll down or rotate the screen, it gets unchecked. Further, if you click one then navigate to the crime, the crime does not get checked either.


#8

Okay, I figured it out. The book has the checkbox disabled in list_item_crime.xml:

<CheckBox android:id=... ... android:enabled="false" ... />

while I had the enabled set to be true. So now my question is, can you wire up the check box so that it does something?