dimanche 28 octobre 2018

Android - How do I save the state of my ImageView boolean value of a ListView Item List?

It's my first time trying to make an App that is basically a checklist that helps me keep track of i.e. collected items. Much like a checklist in a game. I am veeeeery inexperienced with Android so I found some template that I modified for my own need. I'm basically using two .png files (checked and unchecked box) as ImageView which upon clicking change into one another, thus imitating a basic checkbox. Aparently this method worked best for me, even though I thought a normal checkbox object would be easier. When i used regular checkbox objects the status of 'checked' moved throughout the list... And with this ImageView method the checked boxes remained the same as the ones I really checked.

So I figured how to generate a List. Later on I will manually change the list to the Items/Names/etc. as I want that won't be a problem. The App also manages to let me select multiple Items and the items remain checked even after its onPause. The problem I face now is that upon distroying the app on the device and on restarting the app, all the checked Items are now unchecked. That means that the information that the item was check was not stored at all.

I would be so happy if someone can help me with completing the code... I have no idea how to store the information of which Item in List was checked and let alone be reloaded upon onCreate.

Here is activity_main.xml, which is basically the ListView.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="15dp"
    android:paddingTop="15dp"
    android:paddingStart="10dp"
    android:paddingEnd="10dp"
    tools:context="com.multiselect.MainActivity">

    <ListView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/listview"
        android:divider="@android:color/darker_gray"
        android:dividerHeight="2dp"/>

</RelativeLayout>

Next up is the list_view_item.xml where the Name, Subtitle and Checkbox ImageView are declared.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="60dp">

//NAME//
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/tv_user_name"
    android:gravity="center_vertical"
    android:layout_toEndOf="@+id/iv_check_box"
    android:paddingStart="10dp"
    android:textAppearance="?android:attr/textAppearanceLarge" />

//SUB
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/tv_user_sub"
    android:layout_alignStart="@+id/tv_user_name"
    android:layout_below="@+id/tv_user_name"
    android:paddingStart="10dp"
    android:textColor="@color/sub"
    android:textAppearance="?android:attr/textAppearanceMedium"
    tools:ignore="RtlSymmetry" />

//Checkbox
<ImageView
    android:layout_width="20dp"
    android:layout_height="20dp"
    android:id="@+id/iv_check_box"
    android:layout_alignParentStart="true"
    android:onClick="onCheckboxClicked"
    android:layout_centerVertical="true"
    android:background="@drawable/check"/>

</RelativeLayout>

So then I have a basic UserModel.java with all the Getters and Setters.

package com.multiselect;

public class UserModel {

    private boolean isSelected;
    private String userName;
    private String userSub;

    //create constructor and getter setter


    public UserModel(boolean isSelected, String userName, String userSub) {
        this.isSelected = isSelected;
        this.userName = userName;
        this.userSub = userSub;
    }

    public boolean isSelected() {
        return isSelected;
    }

    public void setSelected(boolean selected) {
        isSelected = selected;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getUserSub() {
        return userSub;
    }

    public void setUserSub(String userSub) {
        this.userSub = userSub;
    }
}

Then I know I need an CustomAdapter.java for what I wanna do. I have a ViewHolder inside together with an updater for the checle items.

    package com.multiselect;

import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;   
import android.widget.ImageView;
import android.widget.TextView;

import java.util.List;

public class CustomAdapter extends BaseAdapter {

    Activity activity;
    List<UserModel> users;
    LayoutInflater inflater;


    //short to create constructer using alt+insert or rightclick - generate - constructor

    public CustomAdapter(Activity activity) {
        this.activity = activity;
    }

    public CustomAdapter(Activity activity, List<UserModel> users) {
        this.activity = activity;
        this.users = users;

        inflater = activity.getLayoutInflater();
    }

    @Override
    public int getCount() {
        return users.size();
    }

    @Override
    public Object getItem(int i) {
        return i;
    }

    @Override
    public long getItemId(int i) {
        return i;
    }

    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        ViewHolder holder = null;

        if(view == null){
            view = inflater.inflate(R.layout.list_view_item, viewGroup, false);
            holder = new ViewHolder();

            holder.tvUserName = (TextView)view.findViewById(R.id.tv_user_name);
            holder.tvUserSub = (TextView)view.findViewById(R.id.tv_user_sub);
            holder.ivCheckBox = (ImageView) view.findViewById(R.id.iv_check_box);

            view.setTag(holder);
        }else
            holder = (ViewHolder) view.getTag();

        UserModel model = users.get(i);

        holder.tvUserName.setText(model.getUserName());
        holder.tvUserSub.setText(model.getUserSub());

        if (model.isSelected()) {
                holder.ivCheckBox.setBackgroundResource(R.drawable.checked);
        }
        else
                holder.ivCheckBox.setBackgroundResource(R.drawable.check);

        return view;
    }

    public void updateRecords(List<UserModel> users) {
        this.users = users;

        notifyDataSetChanged();

    }

    class ViewHolder{

        TextView tvUserName;
        TextView tvUserSub;
        ImageView ivCheckBox;


    }
}

...And MainActivity.java:

package com.multiselect;

import android.app.Activity;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.view.View;
import android.widget.AdapterView;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.ListView;
import android.content.SharedPreferences;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends Activity {


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ListView listView = (ListView) findViewById(R.id.listview);

        final List<UserModel> users = new ArrayList<>();

        for(int i = 0; i<20; i++) {
            users.add(new UserModel(false, "Name "+(i), "Subtitle " + (i)));
        }


        final CustomAdapter adapter = new CustomAdapter(this, users);
        listView.setAdapter(adapter);

        listView.setOnItemClickListener(new AdapterView.OnItemClickListener(){
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {


                UserModel model = users.get(i);


                if (model.isSelected())
                    model.setSelected(false);

                else
                    model.setSelected(true);

                users.set(i, model);

                //now update adapter
                adapter.updateRecords(users);


            }

        });

    }

}

And now I know I should use SharedPreferences in the MainActivity.java but I don't know how in this specific example... Especially when I try it out with what other people said the app just crashes either as soon as I check something or when I just try to Run the app. I'm literally not good enough for this and I really want to know how something I normally take for granted (that an app remembers whats been don in it) is done programmatically.

I hope that someone can complete my Code so that the app remembers which box was checked and reloads that upon onCreate...




Aucun commentaire:

Enregistrer un commentaire