Reputation: 33
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
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
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