如何将Android Button的启用/禁用状态保存到SharedPreferences?
问题说明
需要将列表适配器内的按钮启用/禁用状态持久化存储到SharedPreferences,解决底部导航切换回对应Fragment时按钮状态被重置的问题。项目共设置4个底部导航项,当前使用FirebaseRecyclerAdapter实现订单列表,现有代码包含四个按钮的点击逻辑,但未做状态持久化。
原有适配器代码如下:
package com.example.projectrefill; import android.content.SharedPreferences; import android.graphics.ColorSpace; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.Filter; import android.widget.Filterable; import android.widget.TextView; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.recyclerview.widget.RecyclerView; import com.firebase.ui.database.FirebaseRecyclerAdapter; import com.firebase.ui.database.FirebaseRecyclerOptions; import com.google.firebase.database.DatabaseReference; import com.google.firebase.database.FirebaseDatabase; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.Locale; public class adapter_clientside_order_list extends FirebaseRecyclerAdapter<client_model_home_orders,adapter_clientside_order_list.myviewholder> implements Filterable { public adapter_clientside_order_list(@NonNull FirebaseRecyclerOptions<client_model_home_orders> options) { super(options); } @Override protected void onBindViewHolder(@NonNull myviewholder holder, int position, @NonNull client_model_home_orders model) { holder.textView.setText(model.getName()); holder.btnchk.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { AppCompatActivity appCompatActivity=(AppCompatActivity) view.getContext(); appCompatActivity.getSupportFragmentManager().beginTransaction().replace(R.id.wrapper,new Checkordersbtn_client_Fragment(model.getName())).addToBackStack(null).commit(); } }); holder.btnacp.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Toast.makeText(view.getContext(), "accepting", Toast.LENGTH_SHORT).show(); String retailername,itemname,quan; Date c = Calendar.getInstance().getTime(); SimpleDateFormat df = new SimpleDateFormat("dd-MM-yyyy", Locale.getDefault()); String formattedDate = df.format(c).toString(); System.out.println("date to display for the system "+formattedDate); holder.btndel.setEnabled(true); holder.btnacp.setEnabled(false); holder.btncan.setEnabled(false); } }); holder.btncan.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Toast.makeText(view.getContext(), "cancelling", Toast.LENGTH_SHORT).show(); holder.btncan.setEnabled(false); holder.btnacp.setEnabled(false); holder.btndel.setEnabled(false); } }); holder.btndel.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { holder.btndel.setEnabled(false); holder.btnacp.setEnabled(false); holder.btncan.setEnabled(false); Toast.makeText(view.getContext(), "delivered", Toast.LENGTH_SHORT).show(); } }); } @NonNull @Override public myviewholder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.single_row_order_clientside_homepage,parent,false); return new myviewholder(view); } @Override public Filter getFilter() { return null; } public class myviewholder extends RecyclerView.ViewHolder { Button btnchk,btnacp,btncan,btndel; TextView textView; public myviewholder(@NonNull View itemView) { super(itemView); textView=itemView.findViewById(R.id.retailer_name); btnchk=itemView.findViewById(R.id.btn_checkorders); btnacp=itemView.findViewById(R.id.btn_accept); btncan=itemView.findViewById(R.id.btn_cancl); btndel=itemView.findViewById(R.id.btn_deli); } } }
实现方案
注意事项
- 存储状态时不要用列表position作为唯一标识,列表重排、数据增删时position会变化,会导致状态错乱,直接用Firebase数据项自带的唯一key作为标识前缀即可。
- 每次绑定列表项(onBindViewHolder触发时)先读取SharedPreferences中存储的状态,给按钮设置初始值,避免切换页面后状态重置。
- 每次点击按钮修改状态后,同步将最新状态写入SharedPreferences。
修改后完整代码
package com.example.projectrefill; import android.content.Context; import android.content.SharedPreferences; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.Filter; import android.widget.Filterable; import android.widget.TextView; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.recyclerview.widget.RecyclerView; import com.firebase.ui.database.FirebaseRecyclerAdapter; import com.firebase.ui.database.FirebaseRecyclerOptions; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.Locale; public class adapter_clientside_order_list extends FirebaseRecyclerAdapter<client_model_home_orders,adapter_clientside_order_list.myviewholder> implements Filterable { // 定义SharedPreferences存储文件名 private static final String SP_NAME = "order_btn_status"; public adapter_clientside_order_list(@NonNull FirebaseRecyclerOptions<client_model_home_orders> options) { super(options); } @Override protected void onBindViewHolder(@NonNull myviewholder holder, int position, @NonNull client_model_home_orders model) { Context context = holder.itemView.getContext(); SharedPreferences sp = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE); // 获取当前列表项对应的Firebase唯一key,作为状态存储的标识前缀 String itemKey = getRef(holder.getBindingAdapterPosition()).getKey(); holder.textView.setText(model.getName()); // 初始化按钮状态:读取sp中存储的值,未存储时使用默认初始状态 boolean acpEnabled = sp.getBoolean(itemKey + "_btn_acp", true); boolean canEnabled = sp.getBoolean(itemKey + "_btn_can", true); boolean delEnabled = sp.getBoolean(itemKey + "_btn_del", false); holder.btnacp.setEnabled(acpEnabled); holder.btncan.setEnabled(canEnabled); holder.btndel.setEnabled(delEnabled); holder.btnchk.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { AppCompatActivity appCompatActivity=(AppCompatActivity) view.getContext(); appCompatActivity.getSupportFragmentManager().beginTransaction().replace(R.id.wrapper,new Checkordersbtn_client_Fragment(model.getName())).addToBackStack(null).commit(); } }); holder.btnacp.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Toast.makeText(view.getContext(), "accepting", Toast.LENGTH_SHORT).show(); Date c = Calendar.getInstance().getTime(); SimpleDateFormat df = new SimpleDateFormat("dd-MM-yyyy", Locale.getDefault()); String formattedDate = df.format(c); // 修改按钮状态 holder.btndel.setEnabled(true); holder.btnacp.setEnabled(false); holder.btncan.setEnabled(false); // 同步最新状态到SharedPreferences SharedPreferences.Editor editor = sp.edit(); editor.putBoolean(itemKey + "_btn_acp", false); editor.putBoolean(itemKey + "_btn_can", false); editor.putBoolean(itemKey + "_btn_del", true); editor.apply(); } }); holder.btncan.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Toast.makeText(view.getContext(), "cancelling", Toast.LENGTH_SHORT).show(); // 修改按钮状态 holder.btncan.setEnabled(false); holder.btnacp.setEnabled(false); holder.btndel.setEnabled(false); // 同步最新状态到SharedPreferences SharedPreferences.Editor editor = sp.edit(); editor.putBoolean(itemKey + "_btn_acp", false); editor.putBoolean(itemKey + "_btn_can", false); editor.putBoolean(itemKey + "_btn_del", false); editor.apply(); } }); holder.btndel.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // 修改按钮状态 holder.btndel.setEnabled(false); holder.btnacp.setEnabled(false); holder.btncan.setEnabled(false); Toast.makeText(view.getContext(), "delivered", Toast.LENGTH_SHORT).show(); // 同步最新状态到SharedPreferences SharedPreferences.Editor editor = sp.edit(); editor.putBoolean(itemKey + "_btn_acp", false); editor.putBoolean(itemKey + "_btn_can", false); editor.putBoolean(itemKey + "_btn_del", false); editor.apply(); } }); } @NonNull @Override public myviewholder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.single_row_order_clientside_homepage,parent,false); return new myviewholder(view); } @Override public Filter getFilter() { return null; } public class myviewholder extends RecyclerView.ViewHolder { Button btnchk,btnacp,btncan,btndel; TextView textView; public myviewholder(@NonNull View itemView) { super(itemView); textView=itemView.findViewById(R.id.retailer_name); btnchk=itemView.findViewById(R.id.btn_checkorders); btnacp=itemView.findViewById(R.id.btn_accept); btncan=itemView.findViewById(R.id.btn_cancl); btndel=itemView.findViewById(R.id.btn_deli); } } }
代码中删除了未使用的冗余导包和无用变量,如果后续逻辑需要用到对应类,自行加回导包即可。如果需要清除某个已删除订单的按钮状态,直接调用
sp.edit().remove(itemKey + "_btn_acp").remove(itemKey + "_btn_can").remove(itemKey + "_btn_del").apply()就能清除对应存储值,避免无用数据占用存储空间。
内容的提问来源于stack exchange,提问作者Akash
相关产品推荐
相关产品推荐

