I'm facing the next problem.
I have a RecyclerView with the Adapter, the items, etc.
What I need is: Select an item in the recycler, change the color of that item, and then I have to disable the rest of the other items. It's like a RadioButton list.
I select one and disable the others. If I select again the same item, enable all the list.
I already have the onClick Button listener. I need to know if I have to reload again de list, If I have to loop and disable item by item, etc.
Thanks
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private List<Human> humans;
private HumanClick selectedHuman;
#Inject
public MyAdapter() {
}
public void init(List<Human> humanList, SelectedHumanClick humanClick){
this.humans = humanList;
this.humanClick = humanClick;
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_Human, parent, false);
return new MyViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull final MyViewHolder holder, int position) {
final Human human = Humans.get(position);
holder.bind(Humans.get(position));
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
selectedHumanClick.onSelectedHumanClick(Human);
}
});
}
#Override
public int getItemCount() {
return humans != null ? Humans.size() : 0;
}
public final class MyViewHolder extends RecyclerView.ViewHolder {
#BindView(R.id.text_view_human_name)
TextView textView;
#BindView(R.id.image_view_profile)
ImageView imageViewProf;
#BindView(R.id.image_view_radio_btn)
ImageView imageViewRB;
private boolean isChecked = false;
public MyViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
public void bind(final Human Human) {
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
humanClick.onSelectedHumanClick(Human);
}
});
textView.setText(human.getName());
}
public void changeRBImage() {
if(!isChecked){
isChecked = true;
imageViewRB.setBackground(ContextCompat.getDrawable(imageViewRB.getContext(), R.drawable.selected));
}
else{
isChecked = false;
imageViewRB.setBackground(ContextCompat.getDrawable(imageViewRB.getContext(), R.drawable.not_selected));
}
}
}
My Recycler is defined inside a fragment here:
public class HumansFragment implenets HumanClick{
#BindView(R.id.recycler_humans)
RecyclerView humansRecyclerView;
#Inject
MyAdapter myAdapter;
.
.
.
public void loadHumans(List<Human> humans) {
myAdapter.init(Humans, this);
humansRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
humansRecyclerView.setAdapter(myAdapter);
}
#Override
public void humansClick(Human human) {
//TODO
}
}
I'm thinking in something like this, using setOnItemClickListener and check the position of the item clicked. The position is the index of the item clicked check the last event and new, if both are equal change color, if not dont do anything like disabling.
private ViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
textView = (TextView)view.findViewById(android.R.id.text1);
}
#Override
public void onClick(View view) {
Toast.makeText(view.getContext(), "position = " + getLayoutPosition(), Toast.LENGTH_SHORT).show();
//go through each item if you have few items within recycler view
if(getLayoutPosition()==0){
//Do whatever you want here
}else if(getLayoutPosition()==1){
//Do whatever you want here
}else if(getLayoutPosition()==2){
}else if(getLayoutPosition()==3){
}else if(getLayoutPosition()==4){
}else if(getLayoutPosition()==5){
}
//or you can use For loop if you have long list of items. Use its length or size of the list as
for(int i = 0; i<exampleList.size(); i++){
}
}
}
Or something smaller
RecyclerView recyclerView = findViewById(R.id.recycler);
recyclerView.addOnItemTouchListener(
new RecyclerItemClickListener(context, recyclerView ,new
RecyclerItemClickListener.OnItemClickListener() {
#Override public void onItemClick(View view, int position) {
// do whatever
}
#Override public void onLongItemClick(View view, int position) {
// do whatever
}
})
);
Related
I have a simple RecyclerView with an Interface that is linked to the activity. The Issue is the items in the recyclerView need double click in order to perform an action.
This is the AllProductsAdapter Code :
public class AllProductsAdapter extends RecyclerView.Adapter<AllProductsAdapter.ViewHolder> {
RecyclerViewClickInterfaceNew recyclerViewClickInterface;
List<ProductsModel> productsModelList;
Context context;
public AllProductsAdapter(List<ProductsModel> productsModelList, Context context, RecyclerViewClickInterfaceNew recyclerViewClickInterface) {
this.productsModelList = productsModelList;
this.context = context;
this.recyclerViewClickInterface = recyclerViewClickInterface;
}
#NonNull
#Override
public AllProductsAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.product_items, parent, false);
return new AllProductsAdapter.ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull AllProductsAdapter.ViewHolder holder, int position) {
ProductsModel productsModel = productsModelList.get(position);
PicassoTrustAll.getInstance(context)
.load(productsModel.getProduct_image())
.into(holder.catImage);
}
#Override
public int getItemCount() {
return productsModelList.size();
}
class ViewHolder extends RecyclerView.ViewHolder {
ImageView catImage;
TextView catName;
CardView categoryCard;
public ViewHolder(#NonNull View itemView) {
super(itemView);
catImage = itemView.findViewById(R.id.catImage);
catName = itemView.findViewById(R.id.catName);
categoryCard = itemView.findViewById(R.id.categoryCard);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (recyclerViewClickInterface != null)
recyclerViewClickInterface.onItemClick(v, getAdapterPosition());
}
});
}
}
This is my RecyclerViewClickInterfaceNew :
public interface RecyclerViewClickInterfaceNew {
void onItemClick(View view , int position);
void onLongItemClick(int position);
}
This is my MainActivity code :
#Override
public void onItemClick(View view , int position) {
ImageView img= view.findViewById(R.id.catImage);
img.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(AllProductsList.this, "Imgclciked", Toast.LENGTH_SHORT).show();
}
});
}
Here in the MainActivity, the Toast shows after clicking 2 times on the Image. How can i fix it to a normal single click ? Please let me know your answer.
From this code
#Override
public void onItemClick(View view , int position) {
//when different item is FIRST clicked, a new instance of catImage is produced
ImageView img= view.findViewById(R.id.catImage);
//the img onClick is set here to require a second click
img.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(AllProductsList.this, "Imgclciked", Toast.LENGTH_SHORT).show();
}
});
}
For each new item on the Recycler View, you reset the click handling.
I'll suggest you set the onClickListener ON the ViewHolder. It's not the best practice but it'll suffice for your code
I think that's because of you are using NestedScrollView ,
you should add this line to your recyclerview
android:nestedScrollingEnabled="false"
I have a recyclerview from a list of Food Items. When you click on the item, I want the item to be greyed out. Now this does work, and the first item I press, does indeed turn grey. However when I press it again, some other cells turn grey. Then it turns into a big mess, with random ones greyed out?
I have set it up that when you click the item, the FoodItem instance has a boolean set. Then I refresh the data of the recyclerview, so that items with the boolean set, have a grey overlay.
Here is my adapter:
[
public class FoodAdapter extends RecyclerView.Adapter<FoodAdapter.MyViewHolder> {
ClickListener clickListener;
private List<FoodItem> foodList;
public void setClickListener(ClickListener clickListener) {
this.clickListener = clickListener;
}
public interface ClickListener {
void ItemClicked(View v, int position);
}
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView name;
public TextView quantity;
public RelativeLayout background;
public LinearLayout eatenOverlay;
public MyViewHolder(View view) {
super(view);
name = (TextView) view.findViewById(R.id.textView_item_name);
quantity = (TextView) view.findViewById(R.id.textView_item_quantity);
background = (RelativeLayout) view.findViewById(R.id.food_item_background_relative_layout);
eatenOverlay = (LinearLayout) view.findViewById(R.id.eaten_overlay);
}
}
public FoodAdapter(List<FoodItem> foodList) {
this.foodList = foodList;
}
#Override
public FoodAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.food_item_list, parent, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(FoodAdapter.MyViewHolder holder, final int position) {
FoodItem currentFoodItem = foodList.get(position);
if(currentFoodItem.isHasBeenEaten()){
holder.eatenOverlay.setVisibility(View.VISIBLE);
}
Resources res = holder.itemView.getContext().getResources();
holder.name.setText(currentFoodItem.getName());
holder.quantity.setText(currentFoodItem.getQuantity());
holder.background.setBackgroundResource(currentFoodItem.getImage());
holder.background.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (clickListener != null) {
clickListener.ItemClicked(v, position);
}
}
});
}
#Override
public int getItemCount() {
return foodList.size();
}
}
And the main activity implements the interface, so when the item is clicked, in the main acitivty I have this code;
#Override
public void ItemClicked(View v, int position) {
foodList.get(position).setHasBeenEaten(true);
Log.d(TAG,foodList.get(position).getName() + " clicked");
Log.d(TAG,"position: " + position);
mAdapter.notifyDataSetChanged();
}
Why is this happening? Thanks
You are just missing the other option.
if(currentFoodItem.isHasBeenEaten()){
holder.eatenOverlay.setVisibility(View.VISIBLE);
} else {
holder.eatenOverlay.setVisibility(View.INVISIBLE);
}
needed an else branch, otherwise because of the recycling you may reuse the previous view, with the previous "configuration".
I am using Firebase UI FirebaseRecyclerAdapter to populate a RecyclerView. I managed to get click events from components of my item view (the title), but not for anywhere in the item view, which is what I need. I followed google sample.
In my Activity:
private void setRecyclerView() {
recyclerView = (RecyclerView) findViewById(R.id.recycler_view_gigs);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
mAdapter = new FirebaseRecyclerAdapter<Gig, GigViewHolder>(Gig.class,
R.layout.list_item_card,
GigViewHolder.class,
reference) {
#Override
protected void populateViewHolder(final GigViewHolder viewGig, Gig model, final int position) {
viewGig.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.i(Utils.TAG, "onItemClickGeneral: position " + position);
// this doesn't work
}
});
viewGig.bindToGig(model, new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.i(Utils.TAG, "onItemClickTitle: position " + position);
// this works
}
});
}
};
recyclerView.setAdapter(mAdapter);
}
and my ViewHolderClass:
public class GigViewHolder extends RecyclerView.ViewHolder {
ImageView ivIconArtist;
TextView tvArtist;
TextView tvVenue;
TextView tvDate;
public GigViewHolder(View view) {
super(view);
ivIconArtist = (ImageView) view.findViewById(R.id.iv_list_item_icon_artist);
tvArtist = (TextView) view.findViewById(R.id.tv_list_item_artist);
tvVenue = (TextView) view.findViewById(R.id.tv_list_item_venue);
tvDate = (TextView) view.findViewById(R.id.tv_list_item_date);
}
public void bindToGig(Gig gig, View.OnClickListener clickListener) {
tvArtist.setText(gig.getArtist());
tvVenue.setText(gig.getVenue());
tvDate.setText(gig.getDate());
tvArtist.setOnClickListener(clickListener);
}
}
I tried the custom onclicklistener + interface suggested in other answers, no luck either.
Implementing click and long click listener for entire row / items in FirebaseRecyclerViewAdapter.
I did this in this way.
First, define an interface in your ViewHolder class to send callbacks.
Inside its constructor, you can set click/long-click listener for entire row or a single componnent.
Then override onCreateViewHolder of FirebaseRecyclerAdapter where you will implement this interface.
IMPLEMENTATION
My FirebaseViewHolder class.
public class FirebaseViewHolder extends RecyclerView.ViewHolder {
public ImageView mImageView;
public TextView mPostTitle;
public TextView mPostDesc;
public FirebaseViewHolder(View itemView) {
super(itemView);
mImageView = (ImageView) itemView.findViewById(R.id.image_recyclerview);
mPostTitle = (TextView) itemView.findViewById(R.id.tv_title_recyclerview_item);
mPostDesc = (TextView) itemView.findViewById(R.id.tv_desc_recyclerview_item);
//listener set on ENTIRE ROW, you may set on individual components within a row.
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mClickListener.onItemClick(v, getAdapterPosition());
}
});
itemView.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
mClickListener.onItemLongClick(v, getAdapterPosition());
return true;
}
});
}
private FirebaseViewHolder.ClickListener mClickListener;
//Interface to send callbacks...
public interface ClickListener{
public void onItemClick(View view, int position);
public void onItemLongClick(View view, int position);
}
public void setOnClickListener(FirebaseViewHolder.ClickListener clickListener){
mClickListener = clickListener;
}
}
Creating the FirebaseRecyclerAdapter.
FirebaseRecyclerAdapter<Post, FirebaseViewHolder> adapter = new FirebaseRecyclerAdapter<Post, FirebaseViewHolder>(
Post.class,
R.layout.recyclerview_list_item,
FirebaseViewHolder.class,
databaseReference
) {
#Override
protected void populateViewHolder(FirebaseViewHolder viewHolder, Post model, int position) {
Picasso.with(getActivity())
.load(model.image_url)
.into(viewHolder.mImageView);
Log.v(TAG, model.image_url);
//viewHolder.mImageView.setImageResource(R.mipmap.ic_launcher);
viewHolder.mPostTitle.setText(model.title);
viewHolder.mPostDesc.setText(model.desc);
}
#Override
public FirebaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
FirebaseViewHolder viewHolder = super.onCreateViewHolder(parent, viewType);
viewHolder.setOnClickListener(new FirebaseViewHolder.ClickListener() {
#Override
public void onItemClick(View view, int position) {
Toast.makeText(getActivity(), "Item clicked at " + position, Toast.LENGTH_SHORT).show();
}
#Override
public void onItemLongClick(View view, int position) {
Toast.makeText(getActivity(), "Item long clicked at " + position, Toast.LENGTH_SHORT).show();
}
});
return viewHolder;
}
};
There are several answers to this question. One that worked for me was the answer provided by Frank van Puffelen how-to-implement-a-setonitemclicklistener-firebaserecyclerviewadapter
You need to change few things.
Before GigViewHolder constructor inside your public class GigViewHolder extends RecyclerView.ViewHolder define a global variable like this View itemView;
Inside GigViewHolder constructor, assign this variable the view passed as a parameter on your constructor like this this.itemView= view;
Then use this itemView in your populateViewHolder method as you had done as also shown
viewGig.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.i(Utils.TAG, "onItemClickGeneral: position " + position);
// This WORKS, write your TODO here
}
});
You can also explore other options on the following links:
RecyclerView onClick
i made a onClickListener for my recyclerView but it just didn't work.
When i click an item from the recyclerView the log doesnt appear, the commands i put in the OnClickListener arent called ,i spend already 2-3 days to find the problem but i didn't see something wrong in my code it should cost the problem, probably its a small stupid mistake
but pls if anyone can help me get the problem i will be very happy.
In my adapter class i assigned the onClick to check and uncheck a checkbox
and in the MainActivity i assigned to save it in the dataBase
this is in my main activity
private void setUpGUI() {
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
cardView = (CardView) findViewById(R.id.cardView);
recyclerView = (RecyclerView) findViewById(R.id.recylerView);
adapter = new ItemAdapter(new ItemAdapter.ItemClickListener() {
#Override
public void onItemClicked(TodoItem item) {
Log.d(TAG, "on item click");
Uri uri = Uri.parse(TodoItemsContentProvider.CONTENT_URI + "/" + item.getId());
getContentResolver().update(uri, item.toContentValues(), null, null);
}
});
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
final FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
showAddItemPopup();
}
});
this is my adapter class
public class ItemAdapter extends RecyclerView.Adapter<ItemAdapter.ViewHolder> {
private static final String TAG = "item adapter";
private List<TodoItem> items = new ArrayList<>();
private ItemClickListener itemClickListener;
public ItemAdapter(ItemClickListener listener) {
itemClickListener = listener;
}
public void addItem(TodoItem item) {
if (!items.contains(item)) {
items.add(item);
Collections.sort(items);
notifyItemInserted(items.indexOf(item));
}
}
public void addItems(Collection<TodoItem> newItems) {
for (TodoItem item : newItems) {
if (!items.contains(item)) {
items.add(item);
}
}
Collections.sort(items);
notifyDataSetChanged();
}
public TodoItem getItem(int position) {
return items.get(position);
}
public void removeItem(int position) {
items.remove(position);
notifyItemRemoved(position);
}
// This listener listens for clicks to the viewholder. The viewholder passes back the position it is.
private final ClickListener clickListener = new ClickListener() {
#Override
public void onItemClicked(int position) {
Log.d(TAG, "on click adapter");
// Get the item that was clicked
TodoItem item = items.get(position);
// Set the completed state
item.setCompleted(!item.isCompleted());
//Update the UI
notifyItemChanged(position);
// Pass the item back the the itemclicklistener
itemClickListener.onItemClicked(item);
}
};
#Override
public ViewHolder onCreateViewHolder(final ViewGroup parent, final int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.todo_list_item, parent, false);
return new ViewHolder(v, clickListener);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
TodoItem item = items.get(position);
holder.textView.setText(item.getText());
holder.subTextViewA.setText(item.getSubText());
holder.checkBox.setChecked(item.isCompleted());
//holder.backgroundLayout.setBackgroundColor(Color.parseColor("#ec48e418"));
}
#Override
public int getItemCount() {
return items.size();
}
// The view holder listens to clicks on the
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
// private RelativeLayout backgroundLayout;
final TextView textView, subTextViewA;
final CheckBox checkBox;
final ClickListener clickListener;
public ViewHolder(View itemView, ClickListener clickListener) {
super(itemView);
textView = (TextView) itemView.findViewById(R.id.textView);
subTextViewA = (TextView) itemView.findViewById(R.id.subTextViewA);
checkBox = (CheckBox) itemView.findViewById(R.id.checkBox);
//backgroundLayout = (RelativeLayout) itemView.findViewById(R.id.backgroundLayout);
itemView.setOnClickListener(this);
this.clickListener = clickListener;
}
#Override
public void onClick(View v) {
clickListener.onItemClicked(getAdapterPosition());
}
}
// Private listener fot the adapter to know about view clicks
private interface ClickListener {
void onItemClicked(int position);
}
// Public listener to pass the item back to the activity
public interface ItemClickListener {
void onItemClicked(TodoItem item);
}
}
When you click on your checkox, itemView.OnClickListener does not invoke. http://screencast.com/t/moP30Lfc49X
You can set click listener for checkbox and save (or remove) items from database like that http://screencast.com/t/Iw1K3Ld8nna
holder.checkBox.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onItemClickListener.onItemClick(item, holder.checkBox.isChecked());
}
});
public interface OnItemClickListener {
void onItemClick(MainActivity.Item item, boolean save);
}
In your activity:
adapter.setOnItemClickListener(new RecyclerViewAdapter.OnItemClickListener() {
#Override
public void onItemClick(Item item, boolean save) {
if (save) {
// Save
} else {
// Remove from db
}
}
});
I am having trouble removing items from RecyclerView. When I click on delete, the item is removed from RecyclerView, but comes back when I open the app again. I'm hoping it is just a minor issue that someone here can point out or direct me to what area to troubleshoot. The removeItem(String item) in bold is what I think is the issue. You can't see it in this post, but it is "not used".
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.MyViewHolder> {
private List<Grocery> mListData;
private SQLGroceryHelper helper;
RecyclerViewAdapter adapter;
//Adapter's Constructor//
public RecyclerViewAdapter(List<Grocery> mDataList) {
this.mListData = mDataList;
}
//Provide a reference to the views for each contact item//
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView rowItem;
ImageButton purchasedButton;
ImageButton deleteButton;
LinearLayout linearLayout;
public MyViewHolder(View itemView) {
super(itemView);
linearLayout = (LinearLayout) itemView.findViewById(R.id.recycler_row);
rowItem = (TextView) itemView.findViewById(R.id.item_field1);
purchasedButton = (ImageButton) itemView.findViewById(R.id.item_purchased);
deleteButton = (ImageButton) itemView.findViewById(R.id.delete_item);
}
}
//Inflate the view based on the viewtype provided//
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//Create a new view by inflating the row item xml//
View row = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_row, parent, false);
//Set the view to the ViewHolder//
MyViewHolder holder = new MyViewHolder(row);
return holder;
}
//Display data at the specified position//
#Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
holder.rowItem.setText(mListData.get(position).getTextItem());
holder.purchasedButton.setOnClickListener(new View.OnClickListener() {
//Ignore this click for now//
#Override
public void onClick(View v) {
removeItem(position);
}
});
holder.deleteButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
removeItem(position);
}
});
}
public void **removeItem**(String item) {
int position = mListData.indexOf(item);
if (position != -1) {
mListData.remove(item);
notifyItemRemoved(position);
}
}
public void removeItem(int position) {
mListData.remove(position);
notifyItemRemoved(position);
}
#Override
public int getItemCount() {
if (mListData == null) {
return 0;
}
return mListData.size();
}
}
You are removing the data from local object, mListData I guess the original data object remains intact. Remove the data item from the original data object as well
Declare a interface
public interface AdapterCommunication{
void removeStringItem(int position);
}
then in your adapter
private AdapterCommunication mListener;
public void setOnClickListener(AdapterCommunication listener){
mListener = listener;
}
Then from your activity where you initialize the adapter
RecyclerViewAdapter adapter = new RecyclerViewAdapter(list);
adapter.setOnClickListener(new AdapterCommunication{
public void removeStringItem(int position){
list.remove(position);
adapter.notifyDataSetChanged();
}
});
In your adaper,
holder.deleteButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mListener.remove(position);
}
});