Screen flickers between black and white before freezing on startup after idling - xamarin.forms

I have an issue with my Xamarin Forms Android app where after idling (a number of hours), when the app resumes there will be a blank screen and then it rapidly flickers black and white for a few seconds and then goes blank and freezes up. I don't think it's getting as far as the PCL, and I get no crash logs for it. This happens on debug and release builds and on a number of real devices, including Android 13.
The only remedy is to close the app and reopen and then it works without an issue.
It may coincide with the device theme changing from light to dark and vice versa and a long idle period. If the device theme is changed on demand and the app closed and reopened, it doesn't suffer from the flicker.
Epilepsy warning
I have a video of it: https://drive.google.com/file/d/1baXvGLYpDoM9DUo5Y9L03HovCNfDOKSV/view?usp=share_link
I am really struggling to find where the offending code is, and I can't debug it because it doesn't happen for hours or days.
As for the app, there are two activities:
Splash activity
[Activity(MainLauncher = true, NoHistory = true)]
public class SplashActivity : AppCompatActivity
{
protected override void OnCreate(Bundle savedInstanceState)
{
try
{
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
}
catch (Exception ex)
{
//Attempted error handling
}
}
protected override void OnStart()
{
try
{
base.OnStart();
StartActivity(new Intent(Application.Context, typeof(MainActivity)).PutExtras(Intent));
}
catch (Exception ex)
{
//Attempted error handling
}
finally
{
Finish();
}
}
public override void OnBackPressed() { }
}
And
Main activity
[Activity(Icon = "#mipmap/ic_launcher", Theme = "#style/MainTheme", MainLauncher = false, LaunchMode = LaunchMode.SingleTask, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize, ResizeableActivity = false, NoHistory = false, Exported = true)]
//auth0 intent filter
public class MainActivity : Xamarin.Forms.Platform.Android.FormsAppCompatActivity, IOnSuccessListener
{
INotificationActionService _notificationActionService;
IDeviceInstallationService _deviceInstallationService;
INotificationActionService NotificationActionService => _notificationActionService ??= ServiceContainer.Resolve<INotificationActionService>();
IDeviceInstallationService DeviceInstallationService => _deviceInstallationService ??= ServiceContainer.Resolve<IDeviceInstallationService>();
protected override void OnCreate(Bundle savedInstanceState)
{
try
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(savedInstanceState);
Bootstrap.Begin(() => new DeviceInstallationService());
if (DeviceInstallationService.NotificationsSupported)
{
FirebaseMessaging.Instance.GetToken().AddOnSuccessListener(this, this);
}
Rg.Plugins.Popup.Popup.Init(this);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
CrossCurrentActivity.Current.Init(this, savedInstanceState);
Forms.Init(this, savedInstanceState);
InitFontScale();
CachedImageRenderer.Init(true);
_ = typeof(SvgCachedImage);
UserDialogs.Init(this);
LoadApplication(new App());
ProcessNotificationActions(Intent);
}
catch (Exception ex)
{
//Attempted error handling
}
}
public override void OnBackPressed() => Rg.Plugins.Popup.Popup.SendBackPressed(base.OnBackPressed);
public void OnSuccess(Java.Lang.Object result) => DeviceInstallationService.Token = result.ToString();
private void InitFontScale()
{
var configuration = Resources.Configuration;
configuration.FontScale = Math.Min(1f, configuration.FontScale);
//0.85 small, 1 standard, 1.15 big,1.3 more bigger ,1.45 super big
var metrics = new DisplayMetrics();
#pragma warning disable CS0618 // Type or member is obsolete
WindowManager.DefaultDisplay.GetMetrics(metrics);
#pragma warning restore CS0618 // Type or member is obsolete
metrics.ScaledDensity = configuration.FontScale * metrics.Density;
BaseContext.ApplicationContext.CreateConfigurationContext(configuration);
BaseContext.Resources.DisplayMetrics.SetTo(metrics);
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Permission[] grantResults)
{
Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
protected override void OnResume()
{
try
{
var culture = new CultureInfo("en-GB");
CultureInfo.DefaultThreadCurrentCulture = culture;
Thread.CurrentThread.CurrentCulture = culture;
InitFontScale();
base.OnResume();
}
catch (Exception ex)
{
//Attempted error handling
}
}
protected override void OnNewIntent(Intent intent)
{
try
{
base.OnNewIntent(intent);
Auth0.OidcClient.ActivityMediator.Instance.Send(intent.DataString);
ProcessNotificationActions(intent);
}
catch (Exception ex)
{
//Attempted error handling
}
}
private void ProcessNotificationActions(Intent intent)
{
try
{
if (intent?.HasExtra("action") == true)
{
var bundle = intent.Extras;
var dict = bundle.KeySet().ToDictionary(key => key, key => bundle.Get(key).ToString());
var action = intent.GetStringExtra("action");
if (!string.IsNullOrEmpty(action))
{
NotificationActionService.TriggerAction(action, dict);
}
}
}
catch (Exception ex)
{
//Attempted error handling
}
}
}
And
some styles
values styles.xml
<?xml version="1.0" encoding="utf-8" ?>
<resources>
<style name="MainTheme" parent="MainTheme.Base">
<item name="colorAccent">#3E94FF</item>
<item name="android:datePickerDialogTheme">#style/CustomDatePickerDialog</item>
</style>
<style name="SplashTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowBackground">#drawable/splash</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowFullscreen">true</item>
<item name="android:windowContentOverlay">#null</item>
<item name="android:windowActionBar">false</item>
<item name="android:windowIsTranslucent">true</item>
</style>
<style name="CustomDatePickerDialog" parent="ThemeOverlay.AppCompat.Dialog">
<!--header background-->
<item name="colorAccent">#3E94FF</item>
<!--selected day-->
<item name="android:colorControlActivated">#3E94FF</item>
<!--cancel&ok-->
<item name="android:textColor">#000000</item>
</style>
</resources>
values-night styles.xml
<?xml version="1.0" encoding="utf-8" ?>
<resources>
<style name="MainTheme" parent="MainTheme.Base">
<item name="colorAccent">#3E94FF</item>
<item name="android:datePickerDialogTheme">#style/CustomDatePickerDialog</item>
</style>
<style name="SplashTheme" parent="Theme.AppCompat.NoActionBar">
<item name="android:windowBackground">#drawable/splash</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowFullscreen">true</item>
<item name="android:windowContentOverlay">#null</item>
<item name="android:windowActionBar">false</item>
<item name="android:windowIsTranslucent">true</item>
</style>
<style name="CustomDatePickerDialog" parent="ThemeOverlay.AppCompat.Dialog">
<!--selected day-->
<item name="android:colorControlActivated">#3E94FF</item>
<!--cancel&ok-->
<item name="android:textColor">#ffffff</item>
<!--body background-->
<item name="android:windowBackground">#2F343C</item>
<!--days of the month-->
<item name="android:textColorPrimary">#9BA3B1</item>
<!--days of the week-->
<item name="android:textColorSecondary">#ffffff</item>
</style>
</resources>
The application tag in the manifest has the splash theme as the style
android:theme="#style/SplashTheme"
Any help with pinpointing the cause would be very much appreciated.
Thank you.
I have tried combining it into one activity to see if it was the transition from the splash to the main activity.
I have also changed it to the splash activity explicitly starting the main activity and finishing itself, but it made no difference.
As I thought it may be the main activity not getting closed properly, I have also used a timer to finish the activity after 5 minutes in the background, but it still occurred.

Well to start with Android 12 and above doesn't support a separate SplashScreen Activity, so you would need to get rid of that. See https://developer.android.com/develop/ui/views/launch/splash-screen for the full details.
If you want to see how it should be done in Xamarin.Android take a look at https://github.com/gmck/XamarinBasicSplashScreen. Works from API 21 - 33.

Related

Run a background process to change backgroundimage of another page using timer in Xamarin.forms

Hi StackOverflow Team,
I am trying to run a background process in my App. This background process should update just Background image on one of the pages in the App every 15 seconds. So far, I tried to create a timer in the App OnStart() method and update the backgroundimage of the page in the BeginInvokeOnMainThread() method but with no success. Can anyone help me with this?
My Code -
{
private static Stopwatch stopWatch = new Stopwatch();
private const int defaultTimespan = 20;
private readonly HomePage homePage;
public App()
{
InitializeComponent();
try
{
MainPage = new MainPage();
homePage = new HomePage();
}
catch(Exception ex)
{
string str = ex.Message;
}
}
protected override void OnStart()
{
if (!stopWatch.IsRunning)
{
stopWatch.Start();
}
Device.StartTimer(new TimeSpan(0, 0, 10), () =>
{
// Logic for logging out if the device is inactive for a period of time.
if (stopWatch.IsRunning && stopWatch.Elapsed.Seconds >= defaultTimespan)
{
//prepare to perform your data pull here as we have hit the 1 minute mark
// Perform your long running operations here.
Device.BeginInvokeOnMainThread(() =>
{
// If you need to do anything with your UI, you need to wrap it in this.
// homePage.BackgroundImageSource = "goldengate.jpg";
homePage.ChangeBackgroundImage();
});
stopWatch.Restart();
}
// Always return true as to keep our device timer running.
return true;
});
}
protected override void OnSleep()
{
//stopWatch.Reset();
}
protected override void OnResume()
{
//stopWatch.Start();
}
//void ChangeHomePageImage()
//{
// Navigation.PushAsync(new HomePage(appBackground));
// Navigation.RemovePage(this);
//}
}
MainPage -
<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:local="clr-namespace:Excercise.Views"
x:Class="Excercise.MainPage" IsPresented="False">
<MasterDetailPage.Master>
<local:MenuPage x:Name="menuPage"></local:MenuPage>
</MasterDetailPage.Master>
<MasterDetailPage.Detail>
<NavigationPage>
<x:Arguments>
<local:HomePage x:Name="homePage"></local:HomePage>
</x:Arguments>
</NavigationPage>
</MasterDetailPage.Detail>
</MasterDetailPage>
HomePage -
public partial class HomePage : ContentPage
{
private SQLiteAsyncConnection _connection;
public HomePage()
{
InitializeComponent();
// BindingContext = new HomePageViewModel();
_connection = DependencyService.Get<ISQLiteDb>().GetConnection();
loadData("");
}
public HomePage(string BackgroundimgPath)
{
InitializeComponent();
// BindingContext = new HomePageViewModel();
_connection = DependencyService.Get<ISQLiteDb>().GetConnection();
loadData(BackgroundimgPath);
}
public HomePage(string City, string LocationKey, string StateID)
{
InitializeComponent();
_connection = DependencyService.Get<ISQLiteDb>().GetConnection();
// BindingContext = new HomePageViewModel();
try
{
// Method Calls
}
catch (Exception)
{
DisplayAlert("Error", "There was an error loading this page.", "OK");
}
}
protected override void OnAppearing()
{
this.Title = App.AppTitle;
this.firstStacklayout.Margin = new Thickness(0, (Application.Current.MainPage.Height * 0.25), 0, 0);
base.OnAppearing();
}
you are creating an instance of HomePage and trying to update it, but it is NOT the same instance that is being displayed in your MasterDetail
try something like this
var md = (MasterDetailPage)MainPage;
var nav = (NavigationPage)md.DetailPage;
var home = (HomePage)nav.CurrentPage;
home.ChangeBackgroundImage();
alternately, you could use MessagingCenter to send a message to HomePage requesting that it udpate

Is it possible to use AppThemeBinding in Android Custom Styles?

I'm trying to implement Darkmode for Android by using the new AppThemeBinding. It works fine for Android and iOS but i do not have a clue on how to implement it for custom renderers or custom styles.
For example i got a custom Stepper renderer which looks something like this:
protected override void OnElementChanged(ElementChangedEventArgs<Stepper> e)
{
base.OnElementChanged(e);
if (Control != null)
{
Android.Widget.Button buttonDown = (Android.Widget.Button)Control.GetChildAt(0);
Android.Widget.Button buttonUp = (Android.Widget.Button)Control.GetChildAt(1);
if(e.NewElement != null)
{
//Button Down
buttonDown.SetBackgroundResource(Resource.Drawable.button_bg_left);
buttonDown.LayoutParameters = new LinearLayout.LayoutParams(DpToPixel(50), DpToPixel(33));
buttonDown.SetPadding(0,0,0,0);
buttonDown.SetTextColor(Android.Graphics.Color.ParseColor("#007bff"));
//Button Up
buttonUp.SetBackgroundResource(Resource.Drawable.button_bg_right);
buttonUp.LayoutParameters = new LinearLayout.LayoutParams(DpToPixel(50), DpToPixel(33));
buttonUp.SetPadding(0, 0, 0, 0);
buttonUp.SetTextColor(Android.Graphics.Color.ParseColor("#007bff"));
}
}
}
I'm setting a background resource which is a .xml file and looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#FFFFFF"/>
<stroke android:width="1dp" android:color="#007bff" />
<corners
android:topLeftRadius="5dp"
android:bottomLeftRadius="5dp"/>
</shape>
Since the AppThemeBinding is a Markup Extension and works inside .xaml files, i have no clue how i could implement color changes for my android specific renderers?
How could i go about changing the color of my custom shape for Light/Darkmode?
You can Detect the current system theme in the renderer and then set the corresponding color:
class MyStepperRenderer : StepperRenderer
{
public MyStepperRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Stepper> e)
{
base.OnElementChanged(e);
OSAppTheme currentTheme = Xamarin.Forms.Application.Current.RequestedTheme;
if (currentTheme == OSAppTheme.Light)
{
//
}
else
{
//
}
}
}

CustomPicker Ok and Cancel buttons' color

I have this custompicker class in android project:
public class CustomPickerRenderer : PickerRenderer
{
private Context context;
private IElementController ElementController => Element as IElementController;
private AlertDialog _dialog;
public CustomPickerRenderer(Context context) : base(context)
{
this.context = context;
}
protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
{
base.OnElementChanged(e);
if (Control == null || e.NewElement == null) return;
Control.Click += Control_Click1;
}
protected override void Dispose(bool disposing)
{
Control.Click -= Control_Click1;
base.Dispose(disposing);
}
private void Control_Click1(object sender, EventArgs e)
{
Picker model = Element;
var picker = new NumberPicker(Context);
if (model.Items != null && model.Items.Any())
{
picker.MaxValue = model.Items.Count - 1;
picker.MinValue = 0;
picker.SetDisplayedValues(model.Items.ToArray());
picker.WrapSelectorWheel = false;
picker.DescendantFocusability = DescendantFocusability.BlockDescendants;
picker.Value = model.SelectedIndex;
}
var layout = new LinearLayout(Context) { Orientation = Orientation.Vertical };
layout.AddView(picker);
ElementController.SetValueFromRenderer(VisualElement.IsFocusedProperty, true);
var builder = new AlertDialog.Builder(Context);
builder.SetView(layout);
builder.SetTitle(model.Title ?? "");
//change the text or color here
builder.SetNegativeButton(Html.FromHtml("<font color='#039BE5'>Cancel</font>"), (s, a) =>
{
ElementController.SetValueFromRenderer(VisualElement.IsFocusedProperty, false);
// It is possible for the Content of the Page to be changed when Focus is changed.
// In this case, we'll lose our Control.
Control?.ClearFocus();
_dialog = null;
});
//change the text or color here
builder.SetPositiveButton(Html.FromHtml("<font color='#039BE5'>OK</font>"), (s, a) =>
{
ElementController.SetValueFromRenderer(Picker.SelectedIndexProperty, picker.Value);
// It is possible for the Content of the Page to be changed on SelectedIndexChanged.
// In this case, the Element & Control will no longer exist.
if (Element != null)
{
if (model.Items.Count > 0 && Element.SelectedIndex >= 0)
Control.Text = model.Items[Element.SelectedIndex];
ElementController.SetValueFromRenderer(VisualElement.IsFocusedProperty, false);
// It is also possible for the Content of the Page to be changed when Focus is changed.
// In this case, we'll lose our Control.
Control?.ClearFocus();
}
_dialog = null;
});
_dialog = builder.Create();
_dialog.DismissEvent += (ssender, args) =>
{
ElementController?.SetValueFromRenderer(VisualElement.IsFocusedProperty, false);
};
_dialog.Show();
}
}
I tried running my project on my phone Xiaomi POCOPHONE F1 (Android 9) and 2 emulators (Android 8.1) and the colors of cancel and ok buttons are designed Perfectly. But when I tried running the project on Huawei PLE-701L and SAMSUNG SM-T365 (Android 5.1) the color of the buttons didn't changed.
Any suggestions?
Get the button object through the API of dialog and set the text color of the button. This method can be personalized. One point needs to be noted: it must be called after show
in your custom renderer,below _dialog.Show();
....
_dialog.Show();
Button btnOk = _dialog.GetButton((int)DialogInterface.ButtonPositive);
btnOk .SetTextColor(Color.Red);
Button btnCancel= _dialog.GetButton((int)DialogInterface.ButtonNegative);
btnCancel.SetTextColor(Color.Red);
add this style in style.xml
<style name="SpinnerDialog" parent="Theme.AppCompat.Light.Dialog">
<item name="android:popupBackground">#ff00ff</item>
<item name="colorPrimary">#ff00ff</item>
<item name="colorPrimaryDark">#ffff00</item>
<item name="colorAccent">#ff0000</item>
</style>
you can change allthe color including buttons.
and you can also use
<style name="AlertDialogCustom" parent="android:Theme.Material.Light.Dialog.Alert">
<item name="android:colorPrimary">#1e87f0</item>
<item name="android:colorAccent">#1e87f0</item>
</style>
<style name="AppCompatDialogStyle" parent="Theme.AppCompat.Light.Dialog">
<item name="colorAccent">#1e87f0</item>
</style>
The Question is answered here: Picker button's color not changing on android 5.1
I added the styles code in the correct answer in the link, and it worked!

Xamarin Forms Lifecycle

As App.cs is provided from Xamarin Forms I do bootstrap some of the stuff like AutoMapper there. However sometimes when the app is long in the background then the App's constructor fires again when going back from background.
This makes a bit exception since initial stuff being done twice or more.
Is that normal behaviour of XamarinForms lifecycle?
public App()
{
//Its called multiple times since app is running and going back from the background
InitializeComponent();
Bootstrap(new AppContainer(),
new TranslationBootstrap(),
new MapperBootstrap(), );
Navigate();
}
EDIT:
This happens on Android
MainActivity.cs
protected override void OnCreate(Bundle bundle)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(bundle);
Rg.Plugins.Popup.Popup.Init(this, bundle);
CrossCurrentActivity.Current.Init(this, bundle);
RequestedOrientation = ScreenOrientation.Portrait;
AppDomain.CurrentDomain.UnhandledException += CurrentDomainOnUnhandledException;
TaskScheduler.UnobservedTaskException += TaskSchedulerOnUnobservedTaskException;
global::Xamarin.Forms.Forms.Init(this, bundle);
UserDialogs.Init(() => this);
InteractiveAlerts.Init(() => this);
LoadApplication(new App());
}
private static async void TaskSchedulerOnUnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs unobservedTaskExceptionEventArgs)
{
var newExc = new Exception("TaskSchedulerOnUnobservedTaskException", unobservedTaskExceptionEventArgs.Exception);
await LogUnhandledException(sender, newExc);
}
private static async void CurrentDomainOnUnhandledException(object sender, UnhandledExceptionEventArgs unhandledExceptionEventArgs)
{
var newExc = new Exception("CurrentDomainOnUnhandledException", unhandledExceptionEventArgs.ExceptionObject as Exception);
await LogUnhandledException(sender, newExc);
}
internal static async Task LogUnhandledException(object sender, Exception exception)
{
var logger = DependencyService.Get<ILogger>();
await logger.LogAsync(sender, exception.Source, exception.Message, LogType.Fatal);
}
protected override void OnResume()
{
base.OnResume();
if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.WriteExternalStorage) != Permission.Granted)
{
ActivityCompat.RequestPermissions(this,
new[] { Manifest.Permission.WriteExternalStorage, Manifest.Permission.ReadExternalStorage }, 101);
}
}

Xamarin.Forms - Change StatusBar Color

I search but I can't find if it's possible to change the StatusBar color for each platform, from my portable code? (for Android, iOS & WinPhone 8.1)
public App()
{
// Change the StatusBar color
MainPage = new MainPageUser();
}
I believe you would be better off writing a little bit of platform-specific code:
For Android:
On your MainActivity.cs on the Droid project, right after
LoadApplication(new App());
of the overriden OnCreate method, add:
Window.SetStatusBarColor(Android.Graphics.Color.Argb(255, 0, 0, 0));
Like so:
protected override void OnCreate(Bundle bundle)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(bundle);
global::Xamarin.Forms.Forms.Init(this, bundle);
LoadApplication(new App());
Window.SetStatusBarColor(Android.Graphics.Color.Argb(255, 0, 0, 0)); //here
}
I'm coming back to this answer years later to fix it because my answer had been wrong even though it had been accepted as the correct answer. I have now fixed it.
I had misread the question to want to change the navigation bar or that it worked differently in Android at that time.
I think at least this is a much better answer and should be better help to change the color of the navigationbar in Android and iOS.
Add this code to your Xamarin.Forms project
public interface IStatusBarPlatformSpecific
{
void SetStatusBarColor(Color color);
}
add this class to your Android project
[assembly: Dependency(typeof(MyDemo.Droid.CustomRenderers.Statusbar))]
namespace MyDemo.Droid.CustomRenderers
{
public class Statusbar : IStatusBarPlatformSpecific
{
public Statusbar()
{
}
public void SetStatusBarColor(Color color)
{
// The SetStatusBarcolor is new since API 21
if (Build.VERSION.SdkInt >= BuildVersionCodes.Lollipop)
{
var androidColor = color.AddLuminosity(-0.1).ToAndroid();
//Just use the plugin
CrossCurrentActivity.Current.Activity.Window.SetStatusBarColor(androidColor);
}
else
{
// Here you will just have to set your
// color in styles.xml file as shown below.
}
}
}
}
Add this CurrentActivityPlugin to your projects
Now you can change the color in your Forms project like this
var statusbar = DependencyService.Get<IStatusBarPlatformSpecific>();
statusbar.SetStatusBarColor(Color.Green);
Note the else statement above. If you are using an older buildversion than 21 you will need to hard-code your color to the styles.xml in your Android project like this
<?xml version="1.0" encoding="utf-8" ?>
<resources>
<style name="MainTheme.Base" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="android:statusBarColor">#544054</item>
</style>
</resources>
For iOS its similar
add this to your Info.plist (more docs here)
<key>UIStatusBarStyle</key>
<string>UIStatusBarStyleLightContent</string>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
and add this code to your SetStatusBarColor ethod in the iOS version of the StatusBar class
UIView statusBar = UIApplication.SharedApplication.ValueForKey(
new NSString("statusBar")) as UIView;
if (statusBar != null && statusBar.RespondsToSelector(
new ObjCRuntime.Selector("setBackgroundColor:")))
{
// change to your desired color
statusBar.BackgroundColor = Color.FromHex("#7f6550").ToUIColor();
}
I wrote a more detailed blog post on how to set the color of the statusbar from Xamarin.Forms if somebody is interested. It does only talk about Android and iOS but should give you an idea what to do with other platforms.
Another option for Android: change the color in the file \Resources\values\styles.xml (Android project).
<item name="colorPrimaryDark">#00FF00</item>
Using this approach you can change it on every page.
Application.Current.MainPage.SetValue(NavigationPage.BarBackgroundColorProperty, Color.Black);
Maybe I'm not understanding the question, but I hope this helps.
After searching around quite a bit trying to find out how to change the iPhoneX status bar color (the bit behind the notch), I found out that it automatically sets itself based on the BackroundColorproperty of the root ContentPage.
So in Xaml it's as easy as this:
<ContentPage.BackgroundColor>
<OnPlatform x:TypeArguments="Color"
iOS="Navy"
Android="Yellow"
/>
</ContentPage.BackgroundColor>
I'm basically using the approach described in one of the answers here: https://stackoverflow.com/a/46199029/960691, but modifying it a little by giving you a code snippet that I've focused for your individual question (at least I think!)
On the latest versions of Xamarin you no longer need sketchy plugins and can instead do the following on Android:
var androidColor = color.ToAndroid();
Xamarin.Essentials.Platform.CurrentActivity.Window.SetStatusBarColor(androidColor);
So a complete dependency example in Android:
using System;
using Android.OS;
using WikiSpiv.Droid.Extras;
using WikiSpiv.Extras;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: Dependency(typeof(Statusbar))]
namespace WikiSpiv.Droid.Extras
{
public class Statusbar : IStatusBarPlatformSpecific
{
public Statusbar()
{
}
public void SetStatusBarColor(Color color)
{
if (Build.VERSION.SdkInt >= BuildVersionCodes.Lollipop)
{
var androidColor = color.ToAndroid();
Xamarin.Essentials.Platform.CurrentActivity.Window.SetStatusBarColor(androidColor);
}
}
}
}
In Forms:
using System;
using Xamarin.Forms;
namespace WikiSpiv.Extras
{
public interface IStatusBarPlatformSpecific
{
public void SetStatusBarColor(Color color);
}
}
And it can be called like this:
var statusbar = DependencyService.Get<IStatusBarPlatformSpecific>();
statusbar.SetStatusBarColor(Color.Green);
Step 1. Add interface in shared class
public interface IStatusBarColor
{
void changestatuscolor(string color);
}
Step 2. on main activity inject dependency and implement the interface
[assembly: Dependency(typeof(ETCrewReport.Droid.MainActivity))]
public class MainActivity : FormsAppCompatActivity, IStatusBarColor
{
......
...
public static Context context;
protected override void OnCreate(Bundle bundle)
{
}
public void changestatuscolor(string color)
{
try
{
if (Build.VERSION.SdkInt >= BuildVersionCodes.Lollipop)
{
var c = MainActivity.context as FormsAppCompatActivity;
c?.RunOnUiThread(() => c.Window.SetStatusBarColor(Android.Graphics.Color.ParseColor(color)));
}
}
catch (Exception ex)
{
}
}
Step 3. get the dependency in the required xaml.cs file on OnAppearing method
protected async override void OnAppearing()
{
try
{
DependencyService.Get<IStatusBarColor>().changestatuscolor(Color.Black.ToHex());
}
catch (Exception ex)
{
throw;
}
}
in your android
MainActivity.cs
after the
LoadApplication(new App());
add this line
Window.SetStatusBarColor(Android.Graphics.Color.Argb(255, 62, 102,
226));
the color code is Argb format (Alpha,Red,Green,Blue)
You can change your intensity with the alpha percentage from 0-255
below mentioned may help you with opacity of your alpha color
for black with 50% alpha use
Window.SetStatusBarColor(Android.Graphics.Color.Argb(80, 0, 0, 0));
100% - FF
95% - F2
90% - E6
85% - D9
80% - CC
75% - BF
70% - B3
65% - A6
60% - 99
55% - 8C
50% - 80
45% - 73
40% - 66
35% - 59
30% - 4D
25% - 40
20% - 33
15% - 26
10% - 1A
5% - 0D
0% - 00
For android:
protected override void OnCreate(Bundle savedInstanceState)
{
AppCompatDelegate.DefaultNightMode = AppCompatDelegate.ModeNightNo;
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
this.SetStatusBarColor(Color.FromHex("#8EC5FC").ToAndroid());
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
LoadApplication(new App());
}
This works for me.
In the App.xaml
<Color x:Key="navBarRed">#AA0000</Color>
<Color x:Key="navBarBlue">#F4721C</Color>
<Color x:Key="navBarColour">#F4721C</Color>
<Style TargetType="NavigationPage">
<Setter Property="BarBackgroundColor" Value="{DynamicResource navBarColour}"/>
</Style>
Then when you want to change the colour:
if (Condition == true)
App.Current.Resources["navBarColour"] = App.Current.Resources["navBarBlue"];
else
App.Current.Resources["navBarColour"] = App.Current.Resources["navBarRed"];

Resources