1 year ago
#289110
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