question

njsokalski avatar image
0 Votes"
njsokalski asked RobCaplan edited

Repeat Button in RecyclerView

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.



dotnet-xamarin
· 2
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Hi @njsokalski , what do you mean by words I want the Button to be a regular single-click Button or a hold & repeat Button depending on a checkbox? I don't quite catch your meaning.
And what are you trying to achieve, I don't quite understand.

0 Votes 0 ·

A single-click Button is basically a Button that operates in the standard way, you click it & the Click event is triggered.
A hold & repeat Button is a Button that repeatedly triggers the Click event (or some other method, depending on how it gets implemented) until the user releases it (lifts or moves their finger).
I will be using the Button as part of an item in a RecyclerView. Each item will contain a TextView & 2 Buttons (which will increment or decrement the TextView), and I want to be able to specify (in the Adapter) whether the Buttons operate as single-click or hold & repeat. Hopefully this clarifies what I want, here is a screenshot of what I currently have & want it to look like:
80910-screenshot-1616555413.png


0 Votes 0 ·

1 Answer

JessieZhang-2116 avatar image
0 Votes"
JessieZhang-2116 answered njsokalski commented

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;
             }
         };
     }
 }

3.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.




· 6
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

First, is there a reason for DeleteButton in the ViewHolder? I think you misunderstood my question/goal. The checkbox I am referring to is not part of the RecyclerView or the Layout, ViewHolder, or Adapter, it is a standalone Checkbox in a set of options given to the user, and applies to all items in the RecyclerView. The purpose of the CheckBox is to determine whether the Button(s) are single-click or hold & repeat, but from what I can tell, your example only & always has a Click event handler, therefore being unable to perform as a hold & repeat button. The Button(s) in all the items in the RecyclerView will have the same type of handling (they will all be single-click or all hold & repeat), so I basically figured I would end up with an if statement based on the Checked property of my Checkbox to determine whether to add a handler for the Button's Click event or add a handler that gives it the hold & repeat functionality

0 Votes 0 ·

Sorry, the DeleteButton is the code in my demo,I forgot to remove it when I posted the answer.

they will all be single-click or all hold & repeat

For this ,I think you can listen the single click event(SetOnClickListener) and long click event(SetOnLongClickListener or Touch event) to differ them, instead of using a checkbox.

0 Votes 0 ·

What would I put in the Touch event to cause it to repeat? I have tried creating & starting a Timer whose Elapsed event executes the same code as the Click event, but that does not seem to work.

0 Votes 0 ·
Show more comments