Oshant
Oshant

Reputation: 158

Xamarin.Android ButtonRenderer longclick and touch

I'm trying to implement the functionality of the android button through a ButtonRender. The problem occurs when I try to join ".LongClick" and ".touch", since it does not launch the long click event.

 protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Button> e)
        {

        this.SetBackgroundResource(Resource.Drawable.button);

        base.OnElementChanged(e);
        Android.Widget.Button thisButton = Control as Android.Widget.Button;

        thisButton.LongClickable = true;


        thisButton.LongClick += delegate
        {
            string s = "";
        };



        thisButton.Touch += (object sender, Android.Views.View.TouchEventArgs e2) =>
        {

            if (e2.Event.Action == MotionEventActions.Down)
            {
               .
               .
               .
            }
            else if (e2.Event.Action == MotionEventActions.Up)
            {
               .
               .
               .
            }
            else if (e2.Event.Action == MotionEventActions.HoverExit || e2.Event.Action == MotionEventActions.Cancel)
            {
               .
               .
               .
            }
            else if (e2.Event.Action == MotionEventActions.Move)
            {
               .
               .
               .
             }

            };
  }

Upvotes: 0

Views: 1442

Answers (1)

Grace Feng
Grace Feng

Reputation: 16652

To invoke the event of native control, we need to create event handlers in our custom control, and together an interface which inherits from IViewController in order to set values from renderers.

Here is my demo, first of all, create a custom button:

public class MyButton : Xamarin.Forms.Button, IMyButtonController
{
    public event EventHandler Touched;

    void IMyButtonController.SendTouched()
    {
        Touched?.Invoke(this, EventArgs.Empty);
    }

    public event EventHandler LongClicked;

    void IMyButtonController.SendLongClicked()
    {
        LongClicked?.Invoke(this, EventArgs.Empty);
    }

    public event EventHandler Released;

    void IMyButtonController.SendReleased()
    {
        Released?.Invoke(this, EventArgs.Empty);
    }
}

The IMyButtonController inherits from IViewController like this:

public interface IMyButtonController : IViewController
{
    void SendTouched();

    void SendLongClicked();

    void SendReleased();
}

Then in android project, implement the ButtonRenderer and IMyButtonController like this:

[assembly: ExportRenderer(typeof(MyButton), typeof(MyButtonRenderer))]
namespace ProjectNameSpace.Droid
{
    public class MyButtonRenderer : Xamarin.Forms.Platform.Android.ButtonRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Button> e)
        {
            base.OnElementChanged(e);
            if (e.NewElement != null)
            {
                if (Control != null)
                {
                    Control.SetOnTouchListener(ButtonTouchListener.Instance.Value);
                    Control.LongClickable = true;
                    Control.SetOnLongClickListener(ButtonLongClickListener.Instance.Value);
                }
            }
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (Control != null)
                {
                    Control.SetOnTouchListener(null);
                    Control.SetOnLongClickListener(null);
                }
            }

            base.Dispose(disposing);
        }

        private class ButtonTouchListener : Java.Lang.Object, Android.Views.View.IOnTouchListener
        {
            public static readonly Lazy<ButtonTouchListener> Instance = new Lazy<ButtonTouchListener>(() => new ButtonTouchListener());

            public bool OnTouch(Android.Views.View v, Android.Views.MotionEvent e)
            {
                var renderer = v.Tag as ButtonRenderer;
                if (renderer != null)
                {
                    var buttonController = renderer.Element as IMyButtonController;
                    if (e.Action == Android.Views.MotionEventActions.Down)
                    {
                        buttonController?.SendTouched();
                    }
                    else if (e.Action == Android.Views.MotionEventActions.Up)
                    {
                        buttonController?.SendReleased();
                    }
                }
                return false;
            }
        }

        private class ButtonLongClickListener : Java.Lang.Object, Android.Views.View.IOnLongClickListener
        {
            public static readonly Lazy<ButtonLongClickListener> Instance = new Lazy<ButtonLongClickListener>(() => new ButtonLongClickListener());

            public bool OnLongClick(Android.Views.View v)
            {
                var renderer = v.Tag as ButtonRenderer;
                ((IMyButtonController)renderer?.Element)?.SendLongClicked();
                return true;
            }
        }
    }
}

Upvotes: 5

Related Questions