Android RecyclerView中TextView点击变色并持久化状态的实现方案
Got it, let's tackle this issue where your clicked TextView colors reset after restarting the app. Right now, you're only updating the text color in memory—once the app closes, that state is gone. We need to persist the click state and bind it to your data model so it sticks around between sessions. Here's how to do it step by step:
Step 1: Add a Click State Field to Your Model
First, update your Model class to include a boolean flag that tracks whether the item was clicked. This ties the state directly to your data, making it easy to restore later:
public class Model { public String title; public String subtitle; public String link; public String date; public boolean isClicked; // New field to track click state // Update your constructor and getters/setters to include isClicked }
Step 2: Use SharedPreferences for Persistence
We'll use SharedPreferences to save which items were clicked—it's lightweight and perfect for small amounts of data like this. We'll use the item's link (assuming it's unique per item) as the key to store the click state.
Step 3: Modify the RecyclerViewAdapter
Here's the updated adapter code with all necessary changes (I've marked key modifications with comments):
package com.ejobbox.ejobbox; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.graphics.Color; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.TextView; import java.util.ArrayList; public class RecyclerViewAdapter extends RecyclerView.Adapter{ private final int VIEW_TYPE_ITEM = 0; private final int VIEW_TYPE_LOADING = 1; private OnLoadMoreListener onLoadMoreListener; private boolean isLoading; private Activity activity; private ArrayList<Model> dataset; private Context mContext; private int visibleThreshold = 5; private int lastVisibleItem, totalItemCount; private SharedPreferences sharedPrefs; // Added for persistence public RecyclerViewAdapter(RecyclerView recyclerView, ArrayList<Model> mlist, Context context) { this.dataset=mlist; this.mContext=context; this.activity=(Activity) context; // Fixed potential null issue here this.sharedPrefs = mContext.getSharedPreferences("ClickedItems", Context.MODE_PRIVATE); // Initialize SharedPreferences // Restore saved click states when adapter is created restoreClickedStates(); final LinearLayoutManager linearLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager(); recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); totalItemCount = linearLayoutManager.getItemCount(); lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition(); if (!isLoading && totalItemCount <= (lastVisibleItem + visibleThreshold)) { if (onLoadMoreListener != null) { onLoadMoreListener.onLoadMore(); } isLoading = true; } } }); } // Method to restore saved click states from SharedPreferences private void restoreClickedStates() { for (Model item : dataset) { item.isClicked = sharedPrefs.getBoolean(item.link, false); } } public void setOnLoadMoreListener(OnLoadMoreListener mOnLoadMoreListener) { this.onLoadMoreListener = mOnLoadMoreListener; } @Override public int getItemViewType(int position) { return dataset.get(position) == null ? VIEW_TYPE_LOADING : VIEW_TYPE_ITEM; } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if (viewType == VIEW_TYPE_ITEM) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.postdetails,parent,false); return new ImageTypeViewHolder(view); } else if (viewType == VIEW_TYPE_LOADING) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.itemload,parent,false); return new LoadingViewHolder(view); } return null; } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) { if (holder instanceof ImageTypeViewHolder) { final Model object=dataset.get(position); final ImageTypeViewHolder imageTypeViewHolder=(ImageTypeViewHolder) holder; imageTypeViewHolder.title.setText(object.title); imageTypeViewHolder.subtitle.setText(object.subtitle); imageTypeViewHolder.link.setText(object.link); imageTypeViewHolder.date.setText(object.date); // Set text color based on saved state imageTypeViewHolder.title.setTextColor(object.isClicked ? Color.BLUE : Color.BLACK); // Set On Click Listener imageTypeViewHolder.title.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // Update the model's state object.isClicked = true; // Save state to SharedPreferences SharedPreferences.Editor editor = sharedPrefs.edit(); editor.putBoolean(object.link, true); editor.apply(); // Update the text color immediately imageTypeViewHolder.title.setTextColor(Color.BLUE); Intent intent=new Intent(mContext, WPPostDetails.class); intent.putExtra("itemPosition",position); intent.putExtra("link",object.link); mContext.startActivity(intent); } }); } else if (holder instanceof LoadingViewHolder) { LoadingViewHolder loadingViewHolder = (LoadingViewHolder) holder; loadingViewHolder.progressBar.setIndeterminate(true); } } public static class ImageTypeViewHolder extends RecyclerView.ViewHolder{ TextView title,subtitle,link,date; ImageView imageView; public ImageTypeViewHolder(View itemView){ super(itemView); this.title=(TextView)itemView.findViewById(R.id.title); this.link=(TextView)itemView.findViewById(R.id.link); this.subtitle=(TextView) itemView.findViewById(R.id.subtitle); this.imageView=(ImageView) itemView.findViewById(R.id.icon); this.date=(TextView)itemView.findViewById(R.id.date); } } @Override public int getItemCount() { return dataset == null ? 0 : dataset.size(); } public void setLoaded() { isLoading = false; } private class LoadingViewHolder extends RecyclerView.ViewHolder { public ProgressBar progressBar; public LoadingViewHolder(View view) { super(view); progressBar = (ProgressBar) view.findViewById(R.id.progressBar1); } } // Don't forget to define your OnLoadMoreListener interface if you haven't already public interface OnLoadMoreListener { void onLoadMore(); } }
Key Changes Explained
- SharedPreferences Initialization: We create a SharedPreferences instance to store click states under the name "ClickedItems".
- Restore State on Startup: The
restoreClickedStates()method loops through your dataset and sets each item'sisClickedflag based on saved values. - Bind Color to State: In
onBindViewHolder, we set the text color using theisClickedflag, so even after scrolling or restarting, the color stays correct. - Save State on Click: When the user clicks the title, we update the model's flag, save it to SharedPreferences, and update the color immediately.
This approach ensures that your click state persists across app restarts and RecyclerView refreshes.
内容的提问来源于stack exchange,提问作者ejobbox

