Costas
Costas

Reputation: 587

Change colorAccent according to theme for Android

In a MAUI project I want to adopt a different colorAccent value according to the theme of the application.

I tried to adopt this solution https://learn.microsoft.com/en-us/answers/questions/241870/how-to-customize-coloraccent-when-changing-the-the, from the Xamarin.Forms era, with a small modification of the code in the MainActivity.cs:

public override void OnConfigurationChanged(Configuration newConfig)
{
    base.OnConfigurationChanged(newConfig);

    if (Microsoft.Maui.Controls.Application.Current.RequestedTheme == AppTheme.Dark)
    {
        this.SetTheme(Resource.Style.DarkTheme);
    }
    else
    {
        this.SetTheme(Resource.Style.MainTheme);
    }
}

I also have set android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize" property in the activity tag of AndroidManfest.xml, but the problem is that the execution of the code never enters the body of OnConfigurationChanged.

Is there another approach that works for MAUI?

Upvotes: 0

Views: 209

Answers (1)

Liyun Zhang - MSFT
Liyun Zhang - MSFT

Reputation: 14469

but the problem is that the execution of the code never enters the body of OnConfigurationChanged.

The OnConfigurationChanged will be triggered when the system theme changed not the app's theme chanaged.

You can refer to the official document: User expectations of Runtime changes.

And if you want do something when change Application.Current.UserAppTheme. You can use Application.Current.RequestedThemeChanged.

I used it in the MainActivity:

 protected override void OnCreate(Bundle? savedInstanceState)
 {
     base.OnCreate(savedInstanceState);
     App.Current.RequestedThemeChanged += (s, e) =>
     {
        if (Microsoft.Maui.Controls.Application.Current.RequestedTheme == AppTheme.Dark)
        {
        this.SetTheme(Resource.Style.DarkTheme);
        }
    else
        {
        this.SetTheme(Resource.Style.MainTheme);
        }
     };
 }

Edit:

You need to recreate the activity if you want to change its theme at runtime. And call the SetTheme() in the Activity's OnCreate method.

  1. Delclare the custom color and custom style:

In the Platforms\Andorid\Resources\values\colors.xml:

<resources>
    <color name="colorPrimary">#512BD4</color>
    <color name="colorPrimaryDark">#2B0B98</color>
    <color name="colorAccent">#2B0B98</color>
    <color name="colorAccentDark">#FF0000</color>
</resources>

In the Platforms\Andorid\Resources\values\styles.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
      <style name="DarkTheme" parent="Theme.MaterialComponents.DayNight">
            <item name="colorPrimary">@color/colorAccentDark</item>
            <item name="colorPrimaryDark">@color/colorAccentDark</item>
            <item name="colorAccent">@color/colorAccentDark</item>
            <item name="android:actionMenuTextColor">@color/colorActionMenuTextColor</item>
            <item name="appBarLayoutStyle">@style/ThemeOverlay.AppCompat.Dark.ActionBar</item>
            <item name="bottomNavigationViewStyle">@style/Widget.Design.BottomNavigationView</item>
            <item name="materialButtonStyle">@style/MauiMaterialButton</item>
            <item name="checkboxStyle">@style/MauiCheckBox</item>
            <item name="android:textAllCaps">false</item>
            <item name="alertDialogTheme">@style/MauiAlertDialogTheme</item>
      </style>
     
</resources>

In the MainActivity:

[Activity(Theme = "@style/Maui.MainTheme.NoActionBar", MainLauncher = true, LaunchMode = LaunchMode.SingleTop, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)]
 public class MainActivity : MauiAppCompatActivity
 {
     static bool IsDarkTheme = false;
     protected override void OnCreate(Bundle? savedInstanceState)
     {
         App.Current.RequestedThemeChanged += (s, e) =>
         {
             if(Microsoft.Maui.Controls.Application.Current.UserAppTheme == AppTheme.Dark)
                 IsDarkTheme = true;
             else
                 IsDarkTheme = false;
         };
         if (IsDarkTheme)
             SetTheme(Resource.Style.DarkTheme);
         else
             SetTheme(Resource.Style.MainTheme);

         base.OnCreate(savedInstanceState);
     }   
 }

I used the static bool variable. You can use the preference to store the value instead.

Finally, recreate the activity when you change the theme:

            Application.Current.UserAppTheme = AppTheme.Dark;
#if ANDROID
            Platform.CurrentActivity.Recreate();
#endif

In my test, the default theme [Activity(Theme = "@style/Maui.SplashTheme" will make the this.SetTheme(Resource.Style.DarkTheme); not work. If you change the SplashTheme to other theme, such as MainTheme, Maui.MainTheme.NoActionBar and so on, the accent color will also change. But this will break the splash screen.

Upvotes: 1

Related Questions