Xamarin.Forms Content of a button

后端 未结 6 1048
我寻月下人不归
我寻月下人不归 2021-02-15 16:13

I\'m trying to add a custom content to a button in Xamarin Forms.

By default Button is created like this:

6条回答
  •  既然无缘
    2021-02-15 16:41

    Here is my implementation of a button with content, that has some additional things to better mimic an actual button:

    • ICommand Command
    • object CommandParameter
    • Events:
      • Clicked
      • Pressed
      • Released
      • VisuallyPressedChanged (Occurs when the style of the button should be changed to let the user know that the button has been pressed)

    It uses TouchTracking.Forms package for handling touch events, you can download it using NuGet.

    public class ContentButton : ContentView
    {
        public static readonly BindableProperty CommandProperty = BindableProperty.Create(nameof(Command), typeof(ICommand), typeof(ContentButton), null, BindingMode.Default);
        public static readonly BindableProperty CommandParameterProperty =
    BindableProperty.Create(nameof(CommandParameter), typeof(object), typeof(ContentButton));
    
        /// 
        /// Occurs when the Button is clicked.
        /// 
        public event EventHandler Clicked;
        /// 
        /// Occurs when the Button is pressed.
        /// 
        public event EventHandler Pressed;
        /// 
        /// Occurs when the Button is released.
        /// The released event always occur before the clicked event.
        /// 
        public event EventHandler Released;
        /// 
        /// Occurs when the style of the button should be changed to let the user know that the button has been pressed.
        /// If the argument is true, it means that the Button was just pressed.
        /// If the argument is false, it means that the Button was just released or that the user has moved his finger out of the buttons boundaries.
        /// 
        public event EventHandler VisuallyPressedChanged;
    
        /// 
        /// Gets or sets the command to invoke when the button is activated. This is a bindable property.
        /// 
        public ICommand Command
        {
            get => (ICommand)GetValue(CommandProperty);
            set => SetValue(CommandProperty, value);
        }
        /// 
        /// Gets or sets the parameter to pass to the Command property. This is a bindable property.
        /// 
        public object CommandParameter
        {
            get => GetValue(CommandParameterProperty);
            set => SetValue(CommandParameterProperty, value);
        }
    
        private bool isVisuallyPressed;
    
        public ContentButton()
        {
            var touchEffect = new TouchEffect
            {
                Capture = true
            };
            touchEffect.TouchAction += TouchEffect_TouchAction;
            Effects.Add(touchEffect);
        }
    
        protected override void OnChildAdded(Element child)
        {
            base.OnChildAdded(child);
    
            // so that the touch events are ignored and bypassed to this control
            if(child is VisualElement visualChild) {
                visualChild.InputTransparent = true;
            }
        }
    
        private long? currentId;
        private object touchEffect_lock = new object();
        private void TouchEffect_TouchAction(object sender, TouchActionEventArgs e)
        {
            // only track one touch
            if(currentId != e.Id && e.Type!=TouchActionType.Pressed) {
                return;
            }
    
            lock(touchEffect_lock) {
                switch(e.Type) {
                    case TouchActionType.Pressed:
                        currentId = e.Id;
                        Pressed?.Invoke(this, EventArgs.Empty);
                        isVisuallyPressed = true;
                        VisuallyPressedChanged?.Invoke(this, true);
                        break;
                    case TouchActionType.Moved:
                        if(isVisuallyPressed) {
                            bool isInside = e.Location.X >= 0 && e.Location.Y >= 0 && e.Location.X <= Bounds.Width && e.Location.Y <= Bounds.Height;
                            if(!isInside) {
                                isVisuallyPressed = false;
                                VisuallyPressedChanged?.Invoke(this, false);
                            }
                        }
                        break;
                    case TouchActionType.Cancelled:
                        currentId = null;
                        isVisuallyPressed = false;
                        VisuallyPressedChanged?.Invoke(this, false);
                        break;
                    case TouchActionType.Released:
                        currentId = null;
                        if(isVisuallyPressed) {
                            Released?.Invoke(this, EventArgs.Empty);
                            Clicked?.Invoke(this, EventArgs.Empty);
                            if(Command != null && Command.CanExecute(CommandParameter)) {
                                Command.Execute(CommandParameter);
                            }
                            isVisuallyPressed = false;
                            VisuallyPressedChanged?.Invoke(this, false);
                        }
                        break;
                }
            }
        }
    }
    

提交回复
热议问题