Repeat Button in RecyclerView

Nathan Sokalski 4,111 Reputation points
2021-03-23T20:40:30.16+00:00

I have a RecyclerView with a ViewHolder that contains a Button. I want the Button to be a regular single-click Button or a hold & repeat Button depending on a checkbox. Some of the components I have looked at that may be of significance are:

  1. Making sure the handler is not added multiple times and is removed before adding the other one when switching between single-click and hold & repeat.
  2. Using the Button's Touch event to start/stop repeating when using hold & repeat
  3. Whether to use a timer, a while loop containing Task.Delay, or another method when doing hold & repeat
  4. Whether to have the hold & repeat manually raise the click event, manually call the click event handler, or just use separate code (the code I need the Button to execute is very short)

Avoiding adding multiple and removing existing event handlers in the Adapter of a RecyclerView is something that I have always found somewhat challenging. Does anyone have any suggestions on how to make a Button that meets my requirements? Thanks.

Developer technologies .NET Xamarin
{count} votes

1 answer

Sort by: Most helpful
  1. JessieZhang-MSFT 7,716 Reputation points Microsoft External Staff
    2021-03-25T10:02:34.677+00:00

    Hello,

    Welcome to our Microsoft Q&A platform!

    Here is a similar demo, you can refer to the following code:

    1. define the Ui in the item layout (PhotoCardView.axml)
       <LinearLayout              
           android:orientation="horizontal"  
           android:layout_width="match_parent"  
           android:layout_height="wrap_content">  
      
           <CheckBox  
      

    android:text="CheckBox"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/myCheckBox" />

            <TextView  
                android:id="@+id/mNumber"  
                 android:layout_width="wrap_content"  
                 android:layout_height="wrap_content"/>  
    
            <LinearLayout  
                android:orientation="vertical"  
                android:layout_width="wrap_content"  
                android:layout_height="wrap_content">  
                 <Button  
                android:text="+"  
                android:id="@+id/addBtn"  
                android:layout_width="wrap_content"  
                android:layout_height="wrap_content"/>  
                            <Button  
                android:text="-"  
                android:id="@+id/minusBtn"  
                android:layout_width="wrap_content"  
                android:layout_height="wrap_content"/>  
    
            </LinearLayout>  
        </LinearLayout>  
    

    2.define a ViewHolder(mine is PhotoViewHolder.cs)

      public class PhotoViewHolder: RecyclerView.ViewHolder  
    {  
         public int number { get; set; }  
    
        public TextView NumberTextView { get; private set; }  
    
         public CheckBox MyCheckBox { get; set; }  
        public Button AddButton { get; set; }  
    
        public Button MinusButton { get; set; }  
    
        public PhotoViewHolder(View itemView, Action<int> listener) : base(itemView)  
        {  
    
           MyCheckBox = itemView.FindViewById<CheckBox>(Resource.Id.myCheckBox);  
    
            // code here   
            NumberTextView = itemView.FindViewById<TextView>(Resource.Id.mNumber);  
            AddButton = itemView.FindViewById<Button>(Resource.Id.addBtn);  
            MinusButton = itemView.FindViewById<Button>(Resource.Id.minusBtn);  
    
            // Detect user clicks on the item view and report which item  
            // was clicked (by layout position) to the listener:  
            itemView.Click += (sender, e) => listener(base.LayoutPosition);  
            MyCheckBox.Click += delegate  
            {  
                if (MyCheckBox.Checked)  
                {  
                    Console.WriteLine("I can get the adapter position here {0}", AdapterPosition);  
                    IsChecked = true;  
                }  
                else  
                {  
                    Console.WriteLine("I can get the adapter position here {0}", AdapterPosition);  
                    IsChecked = false;  
                }  
            };  
        }  
    }  
    
    1. in your adapter (mine is PhotoAlbumAdapter.cs)
      public class PhotoAlbumAdapter: RecyclerView.Adapter  
       {  
           public event EventHandler<int> ItemClick;  
           public static List<Photo> mPhotoAlbum = new List<Photo>();  
      
           public static RecyclerView.Adapter adapter;  
      
           public PhotoAlbumAdapter(List<Photo> branchesList)  
           {  
               adapter = this;  
               mPhotoAlbum = branchesList;  
           }  
      
           public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)  
           {  
               View itemView = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.PhotoCardView, parent, false);  
      
               PhotoViewHolder vh = new PhotoViewHolder(itemView, OnClick);  
      
               return vh;  
           }  
      
           public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)  
           {  
               PhotoViewHolder vh = holder as PhotoViewHolder;  
               //***********************  
               Photo item=   mPhotoAlbum[position];  
      
               vh.Caption.Text = item.Caption;  
      
      
               vh.MyCheckBox.SetOnCheckedChangeListener(null);  
              vh.MyCheckBox.SetOnCheckedChangeListener(new MyCheckListener(item));  
              vh.MyCheckBox.Checked = item.isChecked;  
      
               vh.AddButton.SetOnClickListener(new MyAddItem(item, position));  
               vh.MinusButton.SetOnClickListener(new MyMinusItem(item,position));  
           }  
      
      
      
           class MyAddItem : Java.Lang.Object, View.IOnClickListener  
           {  
               Photo photo;  
               int position;  
               public MyAddItem(Photo item, int position)  
               {  
                   this.photo = item;  
                   this.position = position;  
               }  
      
               public void OnClick(View v)  
               {  
                   //add the number you want  and call NotifyDataSetChanged to update UI.  
                    photo.mNumber++;  
                   adapter.NotifyDataSetChanged();  
               }  
      
      
           }  
      
      
       class MyMinusItem : Java.Lang.Object, View.IOnClickListener  
       {  
           Photo photo;  
           int position;  
           public MyMinusItem(Photo item, int position)  
           {  
               this.photo = item;  
               this.position = position;  
           }  
      
           public void OnClick(View v)  
           {  
               photo.mNumber--;  
               adapter.NotifyDataSetChanged();  
           }  
       }  
      
       class MyCheckListener : Java.Lang.Object, CompoundButton.IOnCheckedChangeListener  
       {  
           Photo photo;  
      
           public MyCheckListener( Photo item)  
           {  
               this.photo = item;  
           }  
      
           public void OnCheckedChanged(CompoundButton buttonView, bool isChecked)  
           {  
               photo.isChecked = isChecked;  
           }  
       }  
      
           public override int ItemCount  
           {  
               get { return mPhotoAlbum.Count; }  
           }  
      
           // Raise an event when the item-click takes place:  
           void OnClick(int position)  
           {  
               if (ItemClick != null)  
                   ItemClick(this, position);  
           }  
       }  
      

    Note: You can choose the mode( single click and hold & repeat functionality) according to the value of CheckBox. And in default, it is a single click.

    Best Regards,

    Jessie Zhang

    ---
    If the response is helpful, please click "Accept Answer" and upvote it.

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.