RecyclerView Adapter highlight clicked or current item - java

As I'm new to android, I'm struggling to highlight Recyclerview clicked or current item. I have tried some workarounds but nothing helps. Basically I want to highlight selected item even after it is coming back from respective Fragment. Please check my code and help me to get done. Thanks.
public class ContentaAdapter extends RecyclerView.Adapter<ContentaAdapter.MyViewHolder> {
Context context;
ArrayList<String> ItemTitle;
ArrayList<String> ItemSource;
public ContentaAdapter(Context context, ArrayList<String> ItemTitle, ArrayList<String> ItemSource) {
this.context = context;
this.ItemTitle = ItemTitle;
this.ItemSource = ItemSource;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.home_items_layout, parent, false);
MyViewHolder vh = new MyViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
holder.ItemTitle.setText(ItemTitle.get(position));
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Fragment contentdisplay = new ViewContentFragment();
Bundle bundle=new Bundle();
bundle.putStringArrayList("ItemTitle",ItemTitle);
bundle.putStringArrayList("ItemSource",ItemSource);
bundle.putInt("position",position);
bundle.putInt("ItemCounts",ItemTitle.size());
contentdisplay.setArguments(bundle);
((MainActivity)context).replaceFragment(contentdisplay);
}
});
}
#Override
public int getItemCount() {
return ItemTitle.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView ItemTitle;
public MyViewHolder(View itemView) {
super(itemView);
ItemTitle = (TextView) itemView.findViewById(R.id.item_title);
}
}
}

you need to to add isSelected state in to your list item data model and change it onClick.
And when you know state you can change background in ViewHolder
if (isSelected) {
// set selected background here
} else {
// set not selected background here
}
And instead of keeping two lists in adapter you should create one with model ArrayList<DataModel> similar to this:
class DataModel {
String ItemTitle;
String ItemSource;
Boolean isSelected;
}
also you shouldn't pass both list to other fragment, instead take only what you need, for example yourList.get(position);

Related

Android RecyclerView content not updating after notifyItemInserted

I've got a RecyclerView that needs to update in real-time when content is received. It successfully shows all the content at first load. When attempting to add a new item dynamically, it makes no difference. Is there anything I'm doing wrong here? Much appreciated!
MainActivity:
RecyclerView rvClips;
ClipboardRVAdapter adapter;
ArrayList<Clip> clips = new ArrayList<>();
private void SetupRV() {
adapter = new ClipboardRVAdapter(clips);
rvClips.setAdapter(adapter);
adapter.setClickListener(this);
rvClips.setLayoutManager(new LinearLayoutManager(getActivity()));
}
//this method gets called everytime a new item is received. I confirmed that it gets called.
public void OnNewClipReceived(Clip clip) {
clips.add(0, clip);
adapter.notifyItemInserted(0);
}
Adapter:
Standard adapter code. Simply shows all the items in the recyclerview.
public class ClipboardRVAdapter extends RecyclerView.Adapter<ClipboardRVAdapter.ViewHolder> {
private ItemClickListener mClickListener;
ArrayList<Clip> clips;
public ClipboardRVAdapter(ArrayList<Clip> clips) {
this.clips = clips;
}
public void setClickListener(ItemClickListener itemClickListener) {
this.mClickListener = itemClickListener;
}
public interface ItemClickListener {
void onItemClick(View view, int position);
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
Context context = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(context);
// Inflate the custom layout
View contactView = inflater.inflate(R.layout.item_clipboard_clip, parent, false);
// Return a new holder instance
ViewHolder viewHolder = new ViewHolder(contactView);
return viewHolder;
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
Clip clip = clips.get(position);
holder.tvClipTitle.setText(clip.content);
}
#Override
public int getItemCount() {
return clips.size();
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView tvClipTitle;
public ViewHolder(View itemView) {
super(itemView);
tvClipTitle = itemView.findViewById(R.id.tvClipTitle);
}
#Override
public void onClick(View view) {
if (mClickListener != null) mClickListener.onItemClick(view, getAdapterPosition());
}
}
}
Since you mentioned 'realtime', I'm guessing this could be a thread issue. Your code seems correct. It could be that the adapter needs to be refreshed in a runOnUiThread function. Try this:
public void OnNewClipReceived(Clip clip) {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
clips.add(0, clip);
adapter.notifyItemInserted(0);
}
});
}
You would need this method in your RecyclerView adapter.
void addNewClip(Clip clip, int index) {
this.clips.add(index, clip);
notifyItemInserted(index);
}
Adding to clips(MainActivity's) won't make a difference because your adapter has it own ArrayList to work with.

How to get the item position in a ListView and GridView outside the adapter?

I'm trying to get a View position through his view hierarchy.
When I have a RecyclerView, for get the current view position I do:
if(view.getParent() instanceof RecyclerView){
RecyclerView rv = (RecyclerView)view.getParent();
if(rv.getLayoutManager()!=null) {
position = rv.getLayoutManager().getPosition(view);
}
}
But when a ListView or GridView appears, I'm not able to get a Layout Manager to get the position of the view. The idea is to make it in a generic way, without knowing the Custom Adapter the view has.
I have tried to get the position through the ListView and GridView adapter but I dont see any method that do that.
Someone can help me?
Thank you a lot!
Create interface for get position for outside adapter class
here is adapter code:
public class ReportMediaAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private ArrayList<File> reportMediaList = new ArrayList<>();
private Context context;
private int selectedPos = -1;
private OnRemoveImage onRemoveImage;
public ReportMediaAdapter(Context context, ArrayList<File> reportMediaList, OnRemoveImage onRemoveImage) {
this.reportMediaList = reportMediaList;
this.onRemoveImage = onRemoveImage;
this.context = context;
}
**public interface OnRemoveImage {
void onRemove(int pos);
}**
public class MyViewHolder extends RecyclerView.ViewHolder {
private ImageView iv_image, iv_remove;
public MyViewHolder(View itemView) {
super(itemView);
iv_image = itemView.findViewById(R.id.iv_image);
iv_remove = itemView.findViewById(R.id.iv_remove);
}
}
#Override
public int getItemCount() {
return reportMediaList.size()-1;
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_media, parent, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
try {
MyViewHolder menuItemHolder = (MyViewHolder) holder;
CommonMethods.loadImage(context, reportMediaList.get(position), menuItemHolder.iv_image);
menuItemHolder.iv_remove.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
**onRemoveImage.onRemove(position);**
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
}
Here is activity code:
#Override
public void onRemove(int pos) {
// use adapter position
}
I have found a solution:
if(view.getParent() instanceof ViewGroup) {
position = ((ViewGroup)view.getParent()).indexOfChild(view);
}

Saving State of RecyclerView Checkbox

I'm a bit new to Android development.
I was wondering how I can save state of checkboxes in a RecyclerView. I know there are existing solutions for this, but I have a list of items in another RecyclerView that uses the same set of checkboxes. When you click an item, it should show all checkboxes and check those previously checked checkboxes for that item.
I have seen posts using SharedPreferences to save the state but I have different checkboxes states for different item click in another RecyclerView and I do not know how to save these different states.
This is the Adapter class for the list of checkboxes named CurrentAddonAdapter.java:
public class CurrentAddonAdapter extends RecyclerView.Adapter<CurrentAddonAdapter.ViewHolder17> {
private Context context;
private ArrayList items3,price3;
private List<AddonList> addonlist1;
private OnItemClickListener17 mOnItemClickListener17;
CurrentAddonAdapter(Context context, ArrayList items3, ArrayList price3,List addonlist1,OnItemClickListener17 onItemClickListener17){
this.context = context;
this.items3 = items3;
this.price3 = price3;
this.addonlist1 = addonlist1;
this.mOnItemClickListener17 = onItemClickListener17;
}
#NonNull
#Override
public ViewHolder17 onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(context);
View view = layoutInflater.inflate(R.layout.addoncard,parent,false);
return new ViewHolder17(view,mOnItemClickListener17);
}
private SparseBooleanArray selecteditems = new SparseBooleanArray();
#Override
public void onBindViewHolder(#NonNull final CurrentAddonAdapter.ViewHolder17 holder, int position) {
holder.item1.setText(String.valueOf(items3.get(position)));
holder.price1.setText(String.valueOf(price3.get(position)));
final AddonList currentaddon = addonlist1.get(position);
holder.item1.setChecked(selecteditems.get(position));
holder.item1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(holder.item1.isChecked()){
holder.item1.setChecked(true);
mOnItemClickListener17.onItemCheck(currentaddon);
}
else{
holder.item1.setChecked(false);
mOnItemClickListener17.onItemUncheck(currentaddon);
}
}
});
}
#Override
public int getItemCount() {
return items3.size();
}
public class ViewHolder17 extends RecyclerView.ViewHolder implements View.OnClickListener{
TextView price1;
CheckBox item1;
OnItemClickListener17 onItemClickListener17;
public ViewHolder17(#NonNull View itemView, final OnItemClickListener17 onItemClickListener17) {
super(itemView);
item1 = itemView.findViewById(R.id.addoncheck);
price1 = itemView.findViewById(R.id.priceadd);
this.onItemClickListener17 = onItemClickListener17;
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
onItemClickListener17.onItemClick7(getAdapterPosition());
}
}
public interface OnItemClickListener17{
void onItemClick7(int position);
void onItemCheck(AddonList addonList);
void onItemUncheck(AddonList addonList);
}
}
This is the code for the item click. It shows a dialog box with the list of all checkboxes with CardView elements array named items3 and price3
Cursor viewaddon = db.viewalladdon();
while(viewaddon.moveToNext()){
items3.add(viewaddon.getString(2));
price3.add(viewaddon.getString(3));
addonlist1.add(new AddonList(viewaddon.getString(2)));
}
addrecycler.setHasFixedSize(true);
currentAddonAdapter = new CurrentAddonAdapter(getActivity(),items3,price3,addonlist1,this);
addrecycler.setAdapter(currentAddonAdapter);
addrecycler.setLayoutManager(new LinearLayoutManager(getActivity()));
Please, help. I've been trying to find a solution for weeks and I still can't find one. I just really need this for school.

How to add a recyclerview item dynamically when click a button in another activity?

I have a recyclerview in ShoppingCartActivity and a button in ProductDetailActivity. I want to send some data to ShoppingCartActivity when a button clicked in ProductDetailActivity and display them in recyclerview item that creates dynamically in ShoppingCartActivity.
I added addData method to recyclerview Adapter but it doesn't work and app crashes.
shop_btn = findViewById(R.id.add_to_shopping_cart);
shop_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent addToCart = new Intent(ProductDetailActivity.this, ShoppingCartActivity.class);
startActivity(addToCart);
}
});
//HERE IS MY RECYCLERVIEW ADAPTER
public class RecyclerViewAdapter_ShoppingCart extends RecyclerView.Adapter<RecyclerViewAdapter_ShoppingCart.MyViewHolder> {
private Context context;
List<CartItems> cartItemsList;
public RecyclerViewAdapter_ShoppingCart(Context context, List<CartItems> cartItemsList) {
this.context = context;
this.cartItemsList = cartItemsList;
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view;
LayoutInflater layoutInflater = LayoutInflater.from(context);
view = layoutInflater.inflate(R.layout.card_cart, parent, false);
return new MyViewHolder(view);
}
#NonNull
#Override
public void onBindViewHolder(#NonNull final MyViewHolder holder, final int position) {
holder.cart_title.setText(cartItemsList.get(position).getTitle());
holder.cart_price.setText(cartItemsList.get(position).getPrice());
Picasso.get().load(cartItemsList.get(position).getImageUrl()).into(holder.cart_img);
}
#Override
public int getItemCount() {
return cartItemsList.size();
}
public static class MyViewHolder extends RecyclerView.ViewHolder {
TextView cart_title, cart_price;
ImageView cart_img;
public MyViewHolder(View itemView) {
super(itemView);
cart_title = itemView.findViewById(R.id.cart_title);
cart_price = itemView.findViewById(R.id.cart_price);
//cart_delete = itemView.findViewById(R.id.cart_delete);
cart_img = itemView.findViewById(R.id.cart_image);
}
}
public void addItem(List<CartItems> cartItems) {
CartItems newValue = new CartItems();
newValue.setTitle("123");
newValue.setPrice("123");
newValue.setImageUrl("");
cartItems.add(newValue);
notifyDataSetChanged();
}
}
My goal is adding recyclerview items dynamically to ShoppingCartActivity when a button clicked in ProductDetailActivity but app crashes.

Calling activity from ViewHolder in RecyclerView?

I've got a RecyclerView which is loading the content of my String arrays which works fine, however I want to open a new activity depending on which view they have pressed.
What I have done is created an array called classes like so:
<array name="classes">
<item>ClassOne</item>
<item>ClassTwo</item>
<item>ClassThree</item>
<item>ClassFour</item>
</array>
These are stored in an array, and passed to my MainActivityList adapter below:
String[] classes = resource.getStringArray(R.array.classes);
MainActivityList adapter = new MainActivityList(titles,content, images, classes);
recyclerView.setAdapter(adapter);
I've managed to add the OnClickListener to the ViewHolder and output what class is assigned to each view to the log, however I cannot figure out or get working, how to launch another activity.
The class name would be something like ClassOne.class for example
public class MainActivityList extends RecyclerView.Adapter<MainActivityList.ViewHolder> {
private String[] mTitles;
private String[] mContent;
private String[] mClasses;
private TypedArray mImages;
private Context context;
public MainActivityList(String[] titles, String[] content, TypedArray images, String[] classes) {
this.mTitles = titles;
this.mContent = content;
this.mImages = images;
this.mClasses = classes;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup,int i) {
final View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.activity_main_card, viewGroup, false);
ViewHolder vh = new ViewHolder(v);
v.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
ViewHolder vh = (ViewHolder)v.getTag();
Log.v("DEBUG", "Clicked" + vh.classes);
}
});
return vh;
}
public void onBindViewHolder(ViewHolder holder, int position) {
holder.titleView.setText(mTitles[position]);
holder.contentView.setText(mContent[position]);
holder.imageView.setImageDrawable(mImages.getDrawable(position));
holder.classes = mClasses[position];
}
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView titleView;
public TextView contentView;
public ImageView imageView;
public String classes;
public ViewHolder(View v) {
super(v);
titleView = (TextView) v.findViewById(R.id.card_title);
contentView = (TextView) v.findViewById(R.id.card_content);
imageView = (ImageView)v.findViewById(R.id.card_image);
v.setTag(this);
}
}
#Override
public int getItemCount() {
return mTitles.length;
}
}
Intent intent = new Intent(viewObject.getContext(),ActivityName.class);
viewObject.getContext().startActivity(intent);
I was also looking for a solution, and I found this post:
http://venomvendor.blogspot.sg/2014/07/setting-onitemclicklistener-for-recycler-view.html
By using the OnItemClickListener interface, you should be able to call startActivity in your activity.
adapter.SetOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(View v , int position) {
// This is in an Activity so should be able to start new activity, etc.
}
});
Update: I have tested, the method mentioned in the blog worked for me.

Categories