首页 > 解决方案 > Android - 如何保存 ListView 项目列表的 ImageView 布尔值的状态?

问题描述

这是我第一次尝试制作一个基本上是一个清单的应用程序,它可以帮助我跟踪收集的物品。很像游戏中的清单。我对 Android 非常缺乏经验,所以我找到了一些我根据自己的需要修改的模板。我基本上使用两个 .png 文件(选中和未选中的框)作为 ImageView,在单击时相互更改,从而模仿一个基本的复选框。显然,这种方法对我来说效果最好,即使我认为普通的复选框对象会更容易。当我使用常规复选框对象时,“选中”的状态在整个列表中移动......并且使用此 ImageView 方法,选中的框与我真正选中的框保持一致。

所以我想出了如何生成一个列表。稍后我将手动将列表更改为项目/名称/等。如我所愿,这不会是一个问题。该应用程序还设法让我选择多个项目,即使在其 onPause 之后,这些项目仍保持选中状态。我现在面临的问题是,在设备上破坏应用程序并重新启动应用程序时,所有选中的项目现在都未选中。这意味着根本没有存储该项目被检查的信息。

如果有人可以帮助我完成代码,我会很高兴...我不知道如何存储检查列表中的哪个项目的信息,更不用说在 onCreate 时重新加载了。

这里是activity_main.xml,基本上就是 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>

接下来是list_view_item.xml,其中声明了 Name、Subtitle 和 Checkbox ImageView。

<?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>

所以我有一个基本的UserModel.java和所有的 Getter 和 Setter。

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;
    }
}

然后我知道我需要一个CustomAdapter.java来做我想做的事情。我里面有一个 ViewHolder 和一个用于检查项目的更新程序。

    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;


    }
}

...和​​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);


            }

        });

    }

}

现在我知道我应该在MainActivity.java中使用 SharedPreferences但我不知道如何在这个特定的例子中......特别是当我用其他人所说的尝试它时,应用程序在我检查或当我只是尝试运行应用程序时。我实际上还不够好,我真的很想知道我通常认为理所当然的事情(应用程序会记住其中的内容)是如何以编程方式完成的。

我希望有人可以完成我的代码,以便应用程序记住选中了哪个框并在 onCreate 时重新加载...

标签: androidcheckboximageviewsharedpreferenceslistviewitem

解决方案


首先,你需要为你的用户模型添加一个独特的属性。像用户ID

private int userId

然后像其他属性一样添加 setter 和 getter。我想你可以使用 tinyDB 来存储这个 userId 的最新值。然后你可以在添加新用户模型时增加这个 userId。

 TinyDB tinydb = new TinyDB(context);
 int recentid = tinydb.getInt(recentUserId) == null ? 0:tinydb.getInt(recentUserId)
 tinydb.putInt("recentUserId",recentid++);
 userModel1.setUserId(recentid)

之后,您可以创建带有已检查 ID 的数组列表。如果用户检查了任何帖子,则更新该列表。如果用户未选中该列表,则从列表中删除 id。

 List<int> checkedList = new ArrayList<>;
    checkedList.add(..userid);

然后,当您使用以下命令更新该检查列表时,您可以更新 TinyDb。

tinydb.putList("checkedIdList", chekcedList);

当应用程序启动状态时,您需要调用此 tinydb 并使用以下命令获取检查列表

  tinydb.getList("checkedIdList");

然后你可以用选中和未选中状态更新你的列表

PS:你可以导航到https://github.com/kcochibili/TinyDB--Android-Shared-Preferences-Turbo这个并了解有关 tinydb 的信息。这是对共享偏好的一种很好的改进


您需要在 onCrete 方法中执行以下操作以避免始终更新 checkList。

  List<int> checkedList = new ArrayList<>;

  if(tinydb.getList("checkedIdList")!= null){
      checkedList = tinydb.getList("checkedIdList")
  }

推荐阅读