I've been implementing an app where I use a listview with three items (Image view, text view and checkbox) the listview works fine (except for when scrolling down it does not keep the state of the views) but my question is why when I touch an icon of the action bar it changes completely the states of the checkboxes?
This is the normal behaviour of my app:
When I click on a checkBox it change the state to checked
But when I press on my action button of my toolbar this is what happens:
If you do not click on any action an click elsewhere to hide the action menu the states of the checkboxes becomes the normal state
I do not exactly why this is happening but I think it has to be something about the lifecycle of the fragment
Can you please help me?
This is the code of this fragment:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
establecimientosList = new ArrayList<HashMap<String, String>>();
rootView = inflater.inflate(R.layout.fragment_establecimientos,
container, false);
mDrawerToggle = new ActionBarDrawerToggle(getActivity(), null, 0, 0);
return rootView;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
// ListView lv = getListView();
if (savedInstanceState == null) {
new GetEstablecimientos().execute();
}
ListView lv = getListView();
lv.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
// TODO Auto-generated method stub
Fragment fragment = null;
fragment = new MostrarEstablecimientoFragment();
// mDrawerToggle.setDrawerIndicatorEnabled(false);
Bundle bundle = new Bundle();
bundle.putSerializable("HashMap",
establecimientosList.get(arg2));
bundle.putInt(ID, arg2);
fragment.setArguments(bundle);
android.app.FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.content_frame, fragment)
.addToBackStack(null).commit();
((ActionBarActivity) getActivity()).getSupportActionBar()
.setTitle(
establecimientosList.get(arg2).get(TAG_NOMBRE));
}
});
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// TODO Auto-generated method stub;
mDrawerToggle.setDrawerIndicatorEnabled(true);
return super.onOptionsItemSelected(item);
}
I have inside this fragment an Asystask for retrieving the ListView data from Internet
@Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
// Dismiss the progress dialog
if (pDialog.isShowing())
pDialog.dismiss();
/**
* Updating parsed JSON data into ListView
* */
if (!establecimientosList.isEmpty()) {
LazyAdapter mAdapter = new LazyAdapter(getActivity(),
establecimientosList, "RobotoTTF/Roboto-Thin.ttf");
setListAdapter(mAdapter);
} else {
TextView textoError = (TextView) rootView
.findViewById(R.id.textViewEstablecimientoError);
textoError.setVisibility(View.VISIBLE);
ListView lv = getListView();
lv.setVisibility(View.GONE);
Toast.makeText(getActivity(), "Error", Toast.LENGTH_LONG)
.show();
}
}
This is the code of the Adapter:
public class LazyAdapter extends BaseAdapter {
private Activity activity;
private ArrayList<HashMap<String, String>> data;
private static LayoutInflater inflater = null;
public ImageLoader imageLoader;
private Typeface tf;
private final ArrayList<Establecimiento> listEstab;
private SharedPreferences sharedP;
public LazyAdapter(Activity a, ArrayList<HashMap<String, String>> d,
String font, ArrayList<Establecimiento> posEstablecimiento) {
activity = a;
data = d;
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
imageLoader = new ImageLoader(activity.getApplicationContext());
tf = Typeface.createFromAsset(a.getAssets(), font);
sharedP = a.getSharedPreferences(PREFENCIAS_FAVORITOS,
Context.MODE_PRIVATE);
listEstab = posEstablecimiento;
}
public int getCount() {
return data.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
View vi = convertView;
final int pos = position;
if (convertView == null) // {
vi = inflater.inflate(R.layout.list_item, null);
TextView nombre = (TextView) vi
.findViewById(R.id.nombreEstablecimientoList);
TextView descripcion = (TextView) vi.findViewById(R.id.descripcionList);
TextView localidad = (TextView) vi.findViewById(R.id.localidadList);
// thumb image
ImageView thumb_image = (ImageView) vi.findViewById(R.id.list_image);
CheckBox checkFav = (CheckBox) vi.findViewById(R.id.imageList);
HashMap<String, String> establecimiento = new HashMap<String, String>();
establecimiento = data.get(position);
// Setting all values in listview
nombre.setText(establecimiento.get(TAG_NOMBRE));
descripcion.setText(establecimiento.get(TAG_DESCRIPCION));
localidad.setText(establecimiento.get(TAG_LOCALIDAD));
imageLoader.DisplayImage(establecimiento.get(TAG_IMAGEN_TIPO),
thumb_image);
checkFav.setChecked(listEstab.get(position).getFavorito());
checkFav.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
// Actualizo lo que vale en las variables de entorno
sharedP.edit()
.putBoolean(
String.valueOf(listEstab.get(pos).getId()),
!sharedP.getBoolean(String.valueOf(listEstab
.get(pos).getId()), false)).commit();
listEstab.get(pos).setFavorito(
!listEstab.get(pos).getFavorito());
Toast.makeText(activity,
String.valueOf(listEstab.get(pos).getFavorito()),
Toast.LENGTH_SHORT).show();
}
});
checkFav.setFocusable(false);
return vi;
}
}
But actually I don't think that the problem has to be with the adapter at all, because when you click on a item in the listview it opens another fragment with a detail list (this fragment does only consist of textviews and a checkbox). This is a screenshot o the problem:
This is what happend when I click on the setting menu
Weird thing because if you click on the hamburger icon of the drawer, the checkbox has it normal state (without any change)
This is the fragment for the last screenshot:
public class MostrarEstablecimientoFragment extends Fragment {
SharedPreferences editor;
HashMap<String, String> establecimiento = new HashMap<String, String>();
CheckBox favButton;
public MostrarEstablecimientoFragment() {
}
@Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
// ((ActionBarActivity) getActivity()).getSupportActionBar()
// .setDisplayHomeAsUpEnabled(true);
editor = getActivity().getSharedPreferences(PREFENCIAS_FAVORITOS,
Context.MODE_PRIVATE);
}
@SuppressWarnings("unchecked")
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(
R.layout.fragment_mostrar_establecimiento, container, false);
getActivity().setTitle("Mostrar información");
favButton = (CheckBox) rootView.findViewById(R.id.favorite_button);
if (getArguments() != null) {
establecimiento = (HashMap<String, String>) getArguments()
.getSerializable("HashMap");
Boolean isFav = editor.getBoolean(establecimiento.get(TAG_ID),
false);
if (isFav) {
if (favButton.isChecked() == false)
favButton.setChecked(true);
}
TextView tvTitle = (TextView) rootView
.findViewById(R.id.nameEstablecimiento);
tvTitle.setText(establecimiento.get(TAG_NOMBRE));
TextView tvHorario = (TextView) rootView
.findViewById(R.id.textViewHorario);
tvHorario.setText(establecimiento.get(TAG_HORARIO));
TextView tvDescp = (TextView) rootView
.findViewById(R.id.textViewDescp);
tvDescp.setText(establecimiento.get(TAG_DESCRIPCION));
TextView tvDirec = (TextView) rootView
.findViewById(R.id.textViewDirec);
tvDirec.setText(establecimiento.get(TAG_DIRECCION));
TextView tvLocal = (TextView) rootView
.findViewById(R.id.textViewLocalidad);
tvLocal.setText(establecimiento.get(TAG_LOCALIDAD));
TextView tvProv = (TextView) rootView
.findViewById(R.id.textViewProv);
tvProv.setText(establecimiento.get(TAG_PROVINCIA));
TextView tvCodPostal = (TextView) rootView
.findViewById(R.id.textViewCodigo);
tvCodPostal.setText(establecimiento.get(TAG_CODIGOPOSTAL));
TextView tvEmail = (TextView) rootView
.findViewById(R.id.textViewWeb);
tvEmail.setText(establecimiento.get(TAG_EMAIL));
TextView tvTlf1 = (TextView) rootView
.findViewById(R.id.textViewTlf1);
tvTlf1.setText(establecimiento.get(TAG_TLF1));
TextView tvTlf2 = (TextView) rootView
.findViewById(R.id.textViewTlf2);
tvTlf2.setText(establecimiento.get(TAG_TLF2));
}
favButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
// favButton.setActivated(true);
editor.edit().putBoolean(establecimiento.get(TAG_ID),
!editor.getBoolean(establecimiento.get(TAG_ID), false)).commit();
}
});
return rootView;
}
@Override
public void onPause() {
// TODO Auto-generated method stub
super.onPause();
editor.edit().commit();
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// TODO Auto-generated method stub
switch (item.getItemId()) {
case (R.id.action_back):
getFragmentManager().popBackStackImmediate();
break;
default:
getActivity().onBackPressed();
break;
}
return super.onOptionsItemSelected(item);
}
}
EDIT AdapterClass
I've been struggling and I have solved the first problem. The one that when the recycle views changes the rows it loses the state of the checkbox and causes that the checkboxes are constantly changing its state. I've made this by creating a new class of Establecimiento where I save all the data, then before calling the adapter I made an ArrayList saving the state along the other values. I've updated my Adapter Class to reflect this situation, now the checkboxes always maintain their state but when you click on the option menu and the option menu pop up while this is happening the checkboxes changes their states then when you click elsewhere it recover the normal state
There is a problem here:
You're setting checked to true, but never to false. That means that when views are recycled and then reused for a different row, they will show up as favorites even if they are not.
This should be something like: