In Xamarin Forms, we could use DependencyService to call native method. Fortunately, Android document provide the method setLocalNightMode to modify the local DarkMode. We should note that this mehtod can not modify the configure of Settings for the Mobile.
Now we can create a IDarkModeService interface:
public interface IDarkModeService
{
void SetDarkMode(bool value);
}
Then implement its method in Android solution:
public class DarkModeService : IDarkModeService
{
public void SetDarkMode(bool value)
{
if (value)
{
MainActivity.instance.Delegate.SetLocalNightMode(AppCompatDelegate.ModeNightYes);
MainActivity.instance.Recreate();
}
else
{
MainActivity.instance.Delegate.SetLocalNightMode(AppCompatDelegate.ModeNightNo);
MainActivity.instance.Recreate();
}
}
}
Here we need to create a static instance from MainActivity
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
public static MainActivity instance { set; get; }
protected override void OnCreate(Bundle savedInstanceState)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
instance = this;
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
LoadApplication(new App());
}
}
}
And not forgetting to add configure inside styles.xml to make the app support DarkMode:
<style name="MainTheme" parent="Theme.AppCompat.DayNight.NoActionBar"></style>
Last, we could call the dependency method in Xamarin Forms as follows:
private async void ShowDialog_Clicked(object sender, EventArgs e)
{
await DisplayAlert("Alert", "You have been alerted", "OK");
}
private void SetDarkMode_Clicked(object sender, EventArgs e)
{
DependencyService.Get<IDarkModeService>().SetDarkMode(true);
}
private void CancelDarkMode_Clicked(object sender, EventArgs e)
{
DependencyService.Get<IDarkModeService>().SetDarkMode(false);
}
The effect:

==================================Update==================================
If need to custom style of each Theme, you could exchange Theme on runtime.
First, you could store a Theme flag(DarkMode) in Xamrin Forms:
private void SetDarkMode_Clicked(object sender, EventArgs e)
{
Preferences.Set("DarkMode", true);
DependencyService.Get<IDarkModeService>().SetDarkMode(true);
}
private void CancelDarkMode_Clicked(object sender, EventArgs e)
{
Preferences.Set("DarkMode", false);
DependencyService.Get<IDarkModeService>().SetDarkMode(false);
}
Then add each Theme style inside styles.xml:
<?xml version="1.0" encoding="utf-8" ?>
<resources>
<style name="MainTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
</style>
<style name="DayTheme" parent="MainTheme">
</style>
<style name="NightTheme" parent="MainTheme" >
<item name="buttonBarPositiveButtonStyle">@style/positiveBtnStyle</item>
<item name="buttonBarNegativeButtonStyle">@style/negativeBtnstyle</item>
</style>
<!--style of sure button-->
<style name="positiveBtnStyle" parent="Widget.AppCompat.Button.ButtonBar.AlertDialog">
<item name="android:textColor">#0000ff</item>
</style>
<!--style of cancel button-->
<style name="negativeBtnstyle" parent="Widget.AppCompat.Button.ButtonBar.AlertDialog">
<item name="android:textColor">#999999</item>
</style>
</resources>
Last, change the Theme before create view in MainActivity.cs:
public static MainActivity instance { set; get; }
protected override void OnCreate(Bundle savedInstanceState)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
instance = this;
var darkMode = Preferences.Get("DarkMode", false);
if (darkMode)
{
this.SetTheme(Resource.Style.NightTheme);
}
else
{
this.SetTheme(Resource.Style.DayTheme);
}
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
LoadApplication(new App());
}
Now we could see the color style of button will change:
