Search code examples
c#eventscross-platformxamarin.forms

Xamarin.Forms - Button Pressed & Released Event


I want to my event to trigger when button pressed and released, but I can only find Click event in Xamarin.Forms.

I believe there must be some work around to get this functionality. My basic need is to start a process when button is pressed and stop when released. It seems to be a very basic feature but Xamarin.Forms doesn't have it right now.

I tried TapGestureRecognizer on button, but button is firing only click event.

MyButton.Clicked += (sender, args) =>
{
  Log.V(TAG, "CLICKED");
};

var tapGestureRecognizer = new TapGestureRecognizer();
tapGestureRecognizer.Tapped += (s, e) => {
    Log.V(TAG, "TAPPED");
};
MyButton.GestureRecognizers.Add(tapGestureRecognizer);

Keep in mind that I need those events to be working in Android and iOS togather.


Solution

  • Finally I got the solution suggested by @Jason. Here we go...

    1. Create sub class of Xamarin.Forms.Button in PCL project, with event handling capability

      public class CustomButton : Button
      {
          public event EventHandler Pressed;
          public event EventHandler Released;
      
          public virtual void OnPressed()
          {
            Pressed?.Invoke(this, EventArgs.Empty);
          }
      
          public virtual void OnReleased()
          {
            Released?.Invoke(this, EventArgs.Empty);
          }
      }
      
    2. Create platform specific button renderer in respective project

      For Andorid

      [assembly: ExportRenderer(typeof(Button), typeof(CustomButtonRenderer))]
      namespace WalkieTalkie.Droid.Renderer
      {
          public class CustomButtonRenderer : ButtonRenderer
          {
              protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Button> e)
              {
                  base.OnElementChanged(e);
      
                  var customButton = e.NewElement as CustomButton;
      
                  var thisButton = Control as Android.Widget.Button;
                  thisButton.Touch += (object sender, TouchEventArgs args) =>
                  {
                      if (args.Event.Action == MotionEventActions.Down)
                      {
                          customButton.OnPressed();
                      }
                      else if (args.Event.Action == MotionEventActions.Up)
                      {
                          customButton.OnReleased();
                      }
                  };
              }
          }
      }
      

      For IOS

      [assembly: ExportRenderer(typeof(CustomButton), typeof(CustomButtonRenderer))]
      namespace WalkieTalkie.iOS.Renderer
      {
          public class CustomButtonRenderer : ButtonRenderer
          {
              protected override void    OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Button> e)
              {
                  base.OnElementChanged(e);
      
                  var customButton = e.NewElement as CustomButton;
      
                  var thisButton = Control as UIButton;
                  thisButton.TouchDown += delegate
                  {
                      customButton.OnPressed();
                  };
                  thisButton.TouchUpInside += delegate
                  {
                      customButton.OnReleased();
                  };
              }
          }
      }
      
    3. Instantiate your custom button in your page

      var myButton = new CustomButton
      {
          Text = "CustomButton",
          HorizontalOptions = LayoutOptions.FillAndExpand
      };
      myButton.Pressed += (sender, args) =>
      {
          System.Diagnostics.Debug.WriteLine("Pressed");
      };
      myButton.Released += (sender, args) =>
      {
           System.Diagnostics.Debug.WriteLine("Pressed");
      };
      

    Hope this help someone :)