how to get selected items in recyclerview with checkbox
for example: item 1,2,3 and 4 are checked. when i clicked the button create it will toast make text the item selected with their name.
This is my viewholder
public class UserViewGroupHolder extends RecyclerView.ViewHolder {
#Bind(R.id.image_account)
CircleImageView mImageAccount;
#Bind(R.id.text_contact_email)
TextView mTextContactEmail;
#Bind(R.id.text_contact_name)
TextView mTextContactName;
#Bind(R.id.check_box_user)
CheckBox mCheckBoxUser;
public UserViewGroupHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
public void bind(final Account account, final User contact) {
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
mTextContactEmail.setText(contact.getEmail());
mTextContactName.setText(contact.getDisplayName());
}
}
And this is my Activity with onBindViewholder
#Override
public void onBindViewHolder(final UserViewGroupHolder holder, int position) {
holder.bind(mAccount, mUsers.get(position));
}
And this is my Activity with onBindViewholder
I suppose you meant Adapter, not Activity.
mTextContactEmail.setText(contact.getEmail());
mTextContactName.setText(contact.getDisplayName());
should be inside bind(...)
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
}
Must be set not on itemView in Holder, but on "Create" button in options menu.
You can obtain checked state of particular view by few means. One* is to keep in User class boolean field "checked" with getter/setter, and write function with for loop on users list kept in adapter, returning list of users with checked state "true".
Naturally, checked state of user have to be changed in bind(...).
Toast with names for create button click is easy-peasy right now: your new adapter's function returns list of checked users (can return list of Strings with their names as well).
*Notice, this could make User class mutable if it was immutable before.
Oww and you CAN'T base your checked state knowledge on Holders or Views, because they're reusable. If there were many users (more than 10), such state would work on few ListView items at once, which is really poor.
Related
I have a list of elements in recycler view, my need is to hide some elements by clicking a specific element of the same list. For instance, my list contains 10 elements and I want to hide all the elements from position 6 by clicking the element in the 5th position. how can I do that?
You have to remove that element from dataset and call notifyOnDataSetChanged Method, otherwise you can create a model class with boolean/hide show flag and then on item click listener you can set flag accordingly to remove/hide element.
Recyclerview react to notifyDatasetChanged method to redraw each visible row.
try to change behind model of recycler view then notifyDatasetChanged
bindViewHolder(VH holder, int position){
view.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
// Do you business to change data model in other position which
//identified whether the view must be visible or not
notifyDataSetChanged();
}
});
}
Just try this...
public void onBindViewHolder(final ViewHolder viewHolder,
final int position) {
viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// set your logic like this..
if(position==5){
if(list.size()>6){
list.remove(6); // here list will be your data list.
notifyDataSetChanged();
}
}
}
});
I got a RecyclerView and want to change the appearance of any clicked row. For that I have a callbackFunction in my Activity which I pass to the Adapter, which then is called inside the Adapter, as soon as I click on any row in the RecyclerView.
The clicked row is then changed, but it happens, that not only the clicked rows are changed but also other rows, that weren't clicked and were never clicked before. I checked the ArrayList that contains the data, but everything is fine there. Only the clicked elements contain the trigger to change the appearance of the row.
What is causing the other rows to change, although they have not been clicked?
Interface inside activity for callback
public interface onHeaderClickListener{
void onHeaderClicked(int index);
}
Inside RecyclerView Adapter
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, final int position) {
if (holder instanceof ViewHolderHeader){
((ViewHolderHeader)holder).dateHeaderTextView.setText( Integer.toString(((objClass_offerDateHeader) arrayList.get(position)).getDate()));
if(((objClass_offerDateHeader) arrayList.get(position)).isSelected()){
((ViewHolderHeader)holder).dateHeaderTextView.setBackgroundColor(Color.parseColor("#b642f4"));
}
((ViewHolderHeader)holder).dateHeaderTextView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onHeaderClickListener.onHeaderClicked(position);
}
});
}
}
Adapter initialisation inside activity
customAdapterRecyclerViewAddOffersTo = new customAdapterRecyclerViewAddOffers(offerArrayList,"dragTo", new onHeaderClickListener() {
#Override
public void onHeaderClicked(int index) {
if (offerArrayList.get(index) instanceof objClass_offerDateHeader){
if(((objClass_offerDateHeader) offerArrayList.get(index)).isSelected()){
((objClass_offerDateHeader) offerArrayList.get(index)).setSelected(false);
}
else {
((objClass_offerDateHeader) offerArrayList.get(index)).setSelected(true);
}
customAdapterRecyclerViewAddOffersTo.notifyDataSetChanged();
}
}
});
In your onBindViewHolder method you have to set the background of the unselected cell, keep in mind the the cells are reused and you only set the background of selected cells so when it is reused the background is not returned to the normal color
So in code you will have to add an else condition
if(((objClass_offerDateHeader) arrayList.get(position)).isSelected()){
((ViewHolderHeader)holder).dateHeaderTextView.setBackgroundColor(Color.parseColor("#b642f4"));
} else {
((ViewHolderHeader)holder).dateHeaderTextView.setBackgroundColor(Color.parseColor("#FFFFFF")); // I assume you need it to be white you can change it to any other color
}
You need to add an else condition here:
if(((objClass_offerDateHeader) arrayList.get(position)).isSelected()){
((ViewHolderHeader)holder).dateHeaderTextView.setBackgroundColor(Color.parseColor("#b642f4"));
}
Viewholders get recycled, so you cannot be sure of the current state when onBindViewHolder is called.
I have a ViewHolder with an OnClickListener, which sends the click over an Interface to the underlying Activity. The only information i send is the AdapterPosition. In the Activity i then get the information out of the Activitie's reference to the ArrayList (which also fills the Adapter), using the position i get passed from the Adapter. I then use this to open a new Activity where i show this data.
Now, this works, but i just came to mind that this could cause problems, if i don't properly call notifyDataSetChanged/ItemInserted/Removed etc. and the Adapter shows a different List than the actualy up-to-date List in the Activity. I am right about this? Should i get the values out of the Objects IN the Adapter and pass them to the Activity or is my approach correct?
ViewHolder:
public class ExampleViewHolder extends RecyclerView.ViewHolder {
public ImageView mImageView;
public TextView mTextViewCreator;
public TextView mTextViewLikes;
public ExampleViewHolder(View itemView) {
super(itemView);
mImageView = itemView.findViewById(R.id.image_view);
mTextViewCreator = itemView.findViewById(R.id.text_view_creator);
mTextViewLikes = itemView.findViewById(R.id.text_view_likes);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mListener != null) {
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION) {
mListener.onItemClick(position);
}
}
}
});
}
}
MainActivity OnItemClick implementation:
#Override
public void onItemClick(int position) {
Intent detailIntent = new Intent(this, DetailActivity.class);
ExampleItem clickedItem = mExampleList.get(position);
detailIntent.putExtra("imageUrl", clickedItem.getImageUrl());
detailIntent.putExtra("creatorName", clickedItem.getCreator());
detailIntent.putExtra("likeCount", clickedItem.getLikeCount());
startActivity(detailIntent);
}
The answer is simple: Always make sure that you notify the adapter about changes.
Otherwise its behavior becomes unpredictable.
Apart from that, your code seems to be fine
My personal preference is that you send the model to the activity, that's what it's interested in, it doesn't care about your adapter position, and even if in the future your list became an expandable list or even a ViewPager, all the Callback (Activity) wants is the model to start the new screen.
You can change your listener method to
onItemClick(ExampleItem item)
and then you can set your listener when onBindViewHolder is called.
I just want to custom RecyclerView, and I just want to know is it possible to change display button after click on item.
I know I am late to the party, but it might help someone. In your
onBindViewHolder
of the Adapter class, get the position of that particular element and register a click listener. Then do the changes you would like.
#Override
public void onBindViewHolder(MyViewHolder holder, int position){
//all your views binding code
holder.itemView.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v){
//reference your item attributes and manipulate them as you wish
}
});
}
Is there a way to make the RecyclerView have checkmarks like in ListView? Most of the example i see don't have checkmark-like features. They instead highlight the row when the user clicks on an item in the list which is not the behavior i desire. Please any suggestions? Thanks
I would do it like this :
First, Have a SparseBooleanArray in your adapter that you initialize in the constructor. SparseBooleanArrays map integers to booleans so you can know which view has been selected and which hasn't.
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.DataViewHolder> {
private SparseBooleanArray selectedItems;
public RecyclerAdapter(Context context, List<Data> dataList){
selectedItems = new SparseBooleanArray();
}
The ViewHolder implements a ClickListener:
public class DataViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
public DataViewHolder(View itemView) {
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
// the condition below returns false if the item isn't in the array.
if (selectedItems.get(getPosition(), false)) {
//if it is in the array we delete it. So clicking a second time on an item will uncheck it.
selectedItems.delete(getPosition());
((CheckBox)v.findViewById(R.id.checkbox)).setChecked(selectedItems.get(position, false));
}
else {
selectedItems.put(getPosition(), true);
// here get a ref to the view checkbox and *check* it
((CheckBox)viewHolder.itemView.findViewById(R.id.checkbox)).setChecked(true);
}
}
}
At this point you will have multiples items with a checked checkbox in your recyclerview since views are recycled. To prevent this and have only the checkboxes you want to be checked change your onBindViewHolder method so it checks or unchecks the checkbox at bind time :
#Override
public void onBindViewHolder(DataViewHolder viewHolder, int position) {
((CheckBox)viewHolder.itemView.findViewById(R.id.checkbox)).setChecked(selectedItems.get(position, false));
}
I didn't test it but I've almost the same code and it works. If you have a problem let me know.