1 year ago

#289110

test-img

Nethia

Xamarin forms disable imagebutton when pressed, incorrect background

I had problem with android image button background. I had implementation of long press on image button based on Pressed/Released events. First problem was with Released event when I disabled button. I resolve it by call PropagateUpReleased, on iOS it is enough, but on android I had problem that when I set button to enabled again I had a background of button like it was pressed:

  • long press on up arrow, button have dark gray color
  • get the maximum, set button to disabled
  • propagate release button
  • release of ImageButton (XamarinForms) is call
  • disabled button have light gray color
  • click on down arrow, up arrow set to enabled, background color is dark gray My implementation of ImageButtonRenderer:

        public CustomButtonRenderer(Context context) : base(context)
        {
        }

        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {

            base.OnElementPropertyChanged(sender, e);

            if (e.PropertyName == nameof(Button.IsEnabled) && !Element.IsEnabled && Element.IsPressed)
            {
                PropagateRelease();
            }
        }

        public override bool OnTouchEvent(MotionEvent e)
        {
            if (e.Action == MotionEventActions.Cancel)
                PropagateRelease();
            return base.OnTouchEvent(e);
        }

        private void PropagateRelease()
        {
            Element.PropagateUpReleased();
            ((IButtonController)Element).SendReleased();

            Invalidate();
            PostInvalidate();
        }

Edit:

This is my implementation of behavior:

 public class LongPressBehavior : Behavior<ImageButton>
    {
        private readonly object syncObject = new object();
        private const int DurationStartLongPress = 500;
        private const int DurationNextLongPress = 150;
        private ImageButton button;


        private Timer startTimer;
        private Timer nextTimer;
        private volatile bool isReleased;

        public static readonly BindableProperty CommandProperty = BindableProperty.Create(nameof(Command),
            typeof(ICommand), typeof(LongPressBehavior), default(ICommand));

        public ICommand Command
        {
            get => (ICommand)GetValue(CommandProperty);
            set => SetValue(CommandProperty, value);
        }

        #region Cnt
        public LongPressBehavior()
        {
            isReleased = true;
        }
        #endregion

        #region LifeCycles
        protected override void OnAttachedTo(ImageButton button)
        {
            this.button = button;
            base.OnAttachedTo(button);
            this.BindingContext = button.BindingContext;

            button.Pressed += Button_Pressed;
            button.Released += Button_Released;
        }

        protected override void OnDetachingFrom(ImageButton button)
        {
            base.OnDetachingFrom(button);
            this.BindingContext = null;
            
            button.Pressed -= Button_Pressed;
            button.Released -= Button_Released;
        }
        #endregion

        #region Events
        private void Button_Pressed(object sender, EventArgs e)
        {
            Debug.WriteLine("Pressed...");
            isReleased = false;
            InitializeStartTimer();
        }

        private void Button_Released(object sender, EventArgs e)
        {
            
            Debug.WriteLine("Released...");
            isReleased = true;

            DeInitializeTimer(ref startTimer);
            DeInitializeTimer(ref nextTimer);
        }

        protected virtual void OnLongPressed()
        {
            if (button.Command != null)
            {
                Debug.WriteLine("Longpress execute...");
                button.Command.Execute(null);
            }

            if (nextTimer == null)
                InitializeNextTimer();
        }

        private void Timer_Elapsed(object state)
        {
            if (isReleased)
            {
                return;
            }
            Device.BeginInvokeOnMainThread(OnLongPressed);
        }
        #endregion

        #region Private methods
        private void DeInitializeTimer(ref Timer timer)
        {
            Debug.WriteLine("Dispose timer...");
            lock (syncObject)
            {
                if (timer == null)
                {
                    return;
                }
                timer.Change(Timeout.Infinite, Timeout.Infinite);
                timer.Dispose();
                timer = null;
                Debug.WriteLine("Timer disposed...");
            }
        }

        private void InitializeStartTimer()
        {
            Debug.WriteLine("Initialize start timer...");
            lock (syncObject)
            {
                startTimer = new Timer(Timer_Elapsed, null, DurationStartLongPress, Timeout.Infinite);
            }
        }

        private void InitializeNextTimer()
        {
            Debug.WriteLine("Initialize next timer...");
            lock (syncObject)
            {
                if (startTimer != null)
                    DeInitializeTimer(ref startTimer);
                nextTimer = new Timer(Timer_Elapsed, null, DurationNextLongPress, DurationNextLongPress);
            }
        }
        #endregion
    }

Problem scenerio: We have 2 buttons with arrow up and down to increase and decrease value. Also we have limits of value min and max. Buttons have a white color.

  • user touch up button
  • pressed event is call, timer is initialize
  • I increase the value while is less than maksimum (executed command). If value have a maksimum I set IsEnabled to false
  • Release event is not call (even if user release button) , instead I call manually PropagateUpReleased in renderer
  • button on android is light gray
  • touch to down button
  • now value is less than max, I set up button IsEnabled to true, background of button is dark gray (the same like we touch button)

android

xamarin.forms

imagebutton

0 Answers

Your Answer

Accepted video resources