I want to control the ViewHolder inflated Views of my RecyclerView from outside of the ViewHolder and the RecyclerView classes. In other words, I want to have control of these views from other methods/classes.
In my specific case, I made a photo gallery activity which allows the user to perform selection and deselection of each inflated view, notifying which items are selected by highlighting them.
For now, the user is able to do that by clicking each generated object / View; then, actions on specific child of RecyclerView / adapter are possible thanks to "setOnClickListener" and "setOnLongClickListener" methods, which perform the corresponding actions in methods inside the ViewHolder class.
But when activity is restarted (i.e. for device rotation) the selection goes lost and the user should perform the selection again (i.e. for deleting photos).
Assuming that positions of the selected photos are kept (for example via bundle, or via an array) is possible to restore selection (i.e. highlighting the corresponding item / views) on the adapter views after that the activity is re-started? If yes, how?
The code below contains the Recyclerview class and the AdapterView class, which both are child of an activity Class.
private class ImageGalleryAdapter extends RecyclerView.Adapter<ImageGalleryAdapter.MyViewHolder> {
private ArrayList<PhotoObject.PhotoElement> photoAL;
private Context mContext;
public ImageGalleryAdapter(Context context, ArrayList<PhotoObject.PhotoElement> photosToPreviewInGallery) {
mContext = context;
photoAL = photosToPreviewInGallery;
}
@Override
public ImageGalleryAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Context context = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(context);
// Inflate the layout
View itemView = inflater.inflate(R.layout.item_photo, parent, false);
ImageGalleryAdapter.MyViewHolder viewHolder = new ImageGalleryAdapter.MyViewHolder(itemView);
// Retrieving the itemView
return viewHolder;
}
@Override
public void onBindViewHolder(ImageGalleryAdapter.MyViewHolder holder, int position) {
PhotoObject.PhotoElement previewPhotoInGallery = photoAL.get(position);
ImageView imageView = holder.mPhotoImageView;
GlideApp.with(mContext)
.load(previewPhotoInGallery.getUrl())
.placeholder(R.drawable.ic_cloud_off_red)
.into(imageView);
}
//The method which gives back the number of items to load as photo.
@Override
public int getItemCount() {
return (photoAL.size());
}
// The class that assigns a view holder for each Image and checkbox in the RecyclerView.
public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
public ImageView mPhotoImageView;
public CheckBox mPhotoCheckBox;
public MyViewHolder(View item_view) {
super(item_view);
mPhotoImageView = (ImageView) item_view.findViewById(R.id.item_photo_iv);
mPhotoCheckBox = (CheckBox) item_view.findViewById(R.id.item_photo_checkbox);
item_view.setOnClickListener(this);
item_view.setOnLongClickListener(this);
// Retrieving the item_view
}
// The method for managing the click on an image.
@Override
public void onClick(View view) {
itemSelection(view);
}
// Manages the selection of the items.
private void itemSelection(View item) {
// Retrieving the item
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION) {
if (!item.isSelected()) {
// Add clicked item to the selected ones
MultiPhotoShootingActivity.manageSelection(true, position);
// Visually highlighting the ImageView
item.setSelected(true);
mPhotoCheckBox.setChecked(true);
mPhotoCheckBox.setVisibility(View.VISIBLE);
} else {
// Remove clicked item from the selected ones
MultiPhotoShootingActivity.manageSelection(false, position);
// Removing the visual highlights on the ImageView
item.setSelected(false);
mPhotoCheckBox.setChecked(false);
mPhotoCheckBox.setVisibility(View.INVISIBLE);
}
}
}
// The method for managing the long click on an image.
@Override
public boolean onLongClick(View view) {
int position = getAdapterPosition();
if(position != RecyclerView.NO_POSITION) {
Intent intent = new Intent(mContext, PhotoDetail.class);
intent.putExtra("KEY4URL", activityPhotoObject.getPath(position));
startActivity(intent);
}
// return true to indicate that the click was handled (if you return false onClick will be triggered too)
return true;
}
}
}
Thank you for your time.
Find out that for solving the problem I had to accomplish two little tasks:
So, I had to modify some code.
Before proceeding, I would like to point out that the Activity
class has a sub-class, which is the Adapter
class (named ImageGalleryAdapter); the Adapter
subclass, in turn, has its own subclass, which is the ViewHolder
class (named MyViewHolder).
So: Activity
class -> Adapter
class -> ViewHolder
class
activity
class, in which the RecyclerView
is)@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
adapter.onSaveInstanceState(outState);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
adapter.onRestoreInstanceState(savedInstanceState);
}
In the onSaveInstanceState
and onRestoreInstanceState
methods, I added the references for saving and restoring instance states of the "adapter" sub-class.
private boolean [] selectedItemsArray;
private void onSaveInstanceState(Bundle outState) {
outState.putBooleanArray("my_array_key" , selectedItemsArray = mpsaPO.getItemsSelected());
}
private void onRestoreInstanceState(Bundle state) {
if (state != null) {
selectedItemsArray = state.getBooleanArray("my_array_key");
}
}
The selectedItemsArray
is a boolean array in which the information of which elements of the RecyclerView are selected (true = selected; false = not selected) is contained.
Then, adding this element in the saved instance and retrieved via the activity class, makes the app able to know which are the views selected after that the activity is re-created.
if (selectedItemsArray != null) {
if (selectedItemsArray[position]) {
holder.itemView.setSelected(true);
holder.mPhotoCheckBox.setChecked(true);
holder.mPhotoCheckBox.setVisibility(View.VISIBLE);
}
}
With this last part of code, we are applying the selection to the corresponding views based on which items/views were selected before that the activity was saved.
The holer
object contains the itemView
and mPhotoCheckBox
objectsm on which we can perform the selection.