Luis
Luis

Reputation: 33

In Xamarin, how can I change the background color of a button for just 1 second and return it again to its original color?

I'm developing a little app in Xamarin and I want to change the background color of a button just for 1 second when the user presses it. The code I'm trying to use is the following:

var auxColor = btnCancel.BackgroundColor;    // saving the original color (btnCancel is the button name)
btnCancel.BackgroundColor = Color.Red;       // changing the color to red
Task.Delay(1000).Wait();                     // waiting 1 second            
btnCancel.BackgroundColor = auxColor;        // restoring the original color

But what I get is the following sequence:

1- Saving the original color
2- WAITING 1 SECOND
3 Changing the color to red
4 Immediately restoring the color

Does anybody know how to solve this problem?

Upvotes: 3

Views: 156

Answers (2)

Felix Too
Felix Too

Reputation: 11941

You can use the Device.StartTimer in the following manner.

In your button click event:

private void OnButtonClicked(object sender, EventArgs e)
{                    
    var auxColor = btnCancel.BackgroundColor;    // saving the original color 
    btnCancel.BackgroundColor = Color.Red; 

    Device.StartTimer(TimeSpan.FromSeconds(1), () =>
    {
        btnCancel.BackgroundColor = auxColor;             
        return false;
    });
}

To interact with UI elements you can use BeginInvokeOnMainThread like:

Device.StartTimer (new TimeSpan (0, 0, 1), () =>
{
    // do something every 1 second
    Device.BeginInvokeOnMainThread (() => 
    {
      // interact with UI elements
    });
    return true; // runs again, or false to stop
});

See Device.StartTimer docs.

Upvotes: 3

Fruchtzwerg
Fruchtzwerg

Reputation: 11399

Looks like you are calling the steatements in a method executed by the main thread, which is also responsible for rendering. This means your statement

Task.Delay(1000).Wait();                     // waiting 1 second   

blocks rendering, so your change will not be visible.

There are different possible approaches to solve your problem, simplest approach would be using an async method, to allow the UI thread to continue in background:

private async void blink()
{
    var auxColor = btnCancel.BackgroundColor;    // saving the original color (btnCancel is the button name)
    btnCancel.BackgroundColor = Color.Red;       // changing the color to red
    await Task.Delay(1000)                       // waiting 1 second            
    btnCancel.BackgroundColor = auxColor;        // restoring the original color
}

Another possible solution would be to setting the original color after the delay was finished using the original (UI) thread context again:

var auxColor = btnCancel.BackgroundColor;        // saving the original color (btnCancel is the button name)
btnCancel.BackgroundColor = Color.Red;           // changing the color to red
Task.Delay(1000).ContinueWith((T) =>             // waiting 1 second  
    {
        btnCancel.BackgroundColor = auxColor;    // restoring the original color
    }, TaskScheduler.FromCurrentSynchronizationContext());

Upvotes: 2

Related Questions