Ahora que ya se ha hecho realidad el esperado modo oscuro en Android, gracias a la versión Android Q, en versiones anteriores de Android ya se vio un intento pero por ejemplo en Android P, solo se activaba cuando el dispositivo entraba en ahorro de batería.
Añadir soporte a tema oscuro
Para integrar modo oscuro en la aplicación lo puedes realizar con AppCompat o bien MaterialComponents ambas maneras se hace de la misma forma, heredar el tema principal de DayNight
<style name="AppTheme" parent="Theme.AppCompat.DayNight">
Usar tema oscuro de MaterialComponents
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight">
Permiten diferentes variaciones, en apunte me centrare con el nuevo estilo MaterialComponents
Theme.MaterialComponents.DayNight
Theme.MaterialComponents.DayNight.NoActionBar
Theme.MaterialComponents.DayNight.DarkActionBar
Tema y estilos
Debemos usar los estilos adecuadamente para que cuando se cambie a tema oscuro los elementos cambien de color, por ejemplo: la barra de acción de la app, el color del texto, los iconos…
Para que el modo oscuro afecte a la barra de la aplicación, en AppBarLayout debemos definir
android:theme="?attr/actionBarTheme"
y el Toolbar definir
app:popupTheme="?attr/actionBarPopupTheme"
Todo junto así
<com.google.android.material.appbar.AppBarLayout
...
android:theme="?attr/actionBarTheme">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
...
app:popupTheme="?attr/actionBarPopupTheme"/>
Para elementos de texto
El color del texto ?android:attr/textColorPrimary
en el tema claro el texto será casi negro y en el tema oscuro será casi blanco, manteniendo estados de estilo inhabilitado.
Por defecto se establecen el color del texto, pero si queremos forzar en un elemento
android:textColor="?android:attr/textColorPrimary"
El color del texto secundario ?android:attr/textColorSecondary en el tema claro y oscuro se mostrará con un gris oscuro, manteniendo estados de estilo inhabilitado.
android:textColor="?android:attr/textColorSecondary"
Para elementos gráficos
El color de los iconos, aplicar el tinte en ?attr/colorControlNormal de esa forma se mantendrá la alteración del color en el estado inhabilitado
<vector
...
android:tint="?attr/colorControlNormal">
Personalización del Modo Oscuro
Si queremos una mayor personalización del tema claro y oscuro, podemos especificar por separado sus estilos
Definir el tema claro en values/styles.xml
<style name="Theme.YourApp.Light" parent="Theme.MaterialComponents.Light">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<!-- your light theme attributes -->
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/primaryColor</item>
<item name="colorPrimaryDark">@color/primaryDarkColor</item>
<item name="colorAccent">@color/secondaryColor</item>
</style>
Definir el tema oscuro en values/styles.xml
<style name="Theme.YourApp.Dark" parent="Theme.MaterialComponents">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<!-- your dark theme attributes -->
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/primaryColor</item>
<item name="colorPrimaryDark">@color/primaryDarkColor</item>
<item name="colorAccent">@color/secondaryColor</item>
</style>
Definir el tema oscuro en values-night/styles.xml
Para que se cargue un tema o otro dependiendo del modo oscuro, lo deberemos hacer con el sufijo -night en values-night/styles.xml definir que Theme.YourApp.DayNight herede del tema oscuro
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Theme.YourApp.DayNight" parent="Theme.YourApp.Dark" />
</resources>
Y en values/styles.xml definir que Theme.YourApp.DayNight herede del tema claro
<style name="Theme.YourApp.DayNight" parent="Theme.YourApp.Light" />
Luego en AndroidManifest.xml en las actividades que queremos implementar el modo oscuro definir el tema:
... android:theme="@style/Theme.YourApp.DayNight" ...
Visualización
<style name="AppTheme.Light" parent="Theme.MaterialComponents.Light.Bridge">
<style name="AppTheme.Dark" parent="Theme.MaterialComponents.Bridge">
<style name="AppTheme.Light" parent="Theme.MaterialComponents.Light.DarkActionBar.Bridge">
Estilizar el ActionBar
El ActionBar de las aplicaciones puede ser de color opaco con la fuente de color blanco que normalmente se atribuye a DarkActionBar o bien que sea con fondo claro y letras negras.
El atributo de tema actionBarTheme es donde se especifica el estilo de la ActionBar
Propiedad actionBarPopupTheme es donde se especifica el estilo del menú contextual de la ActionBar
Barra superior oscura
<item name="actionBarTheme">@style/ThemeOverlay.MaterialComponents.Dark.ActionBar</item>
<item name="actionBarPopupTheme">@style/ThemeOverlay.MaterialComponents.Dark</item>
Barra superior clara
<item name="actionBarTheme">@style/ThemeOverlay.MaterialComponents.Light</item>
<item name="actionBarPopupTheme">@style/ThemeOverlay.MaterialComponents.Light</item>
Establecer un color a la barra superior
Para especificar un color se hace en elemento Toolbar y con la propiedad android:background:
<androidx.appcompat.widget.Toolbar
...
android:background="?attr/colorPrimary"
.../>
Ejemplo de tema personalizado
El tema personalizado heredera los colores de DarkActionBar, modificando el color de la ActionBar a Azul y el menú en oscuro para el tema claro, en el tema oscuro el color de la ActionBar será rojo
Los colores usados se obtienen de Lista de Colores Material Design
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.MaterialComponents.Light.Bridge">
<!-- Customize your theme here. -->
</style>
<style name="AppTheme.Light" parent="Theme.MaterialComponents.Light.DarkActionBar.Bridge">
<!-- your light theme attributes -->
<item name="colorPrimary">@color/primaryColor</item>
<item name="colorPrimaryDark">@color/primaryDarkColor</item>
<item name="colorAccent">@color/secondaryColor</item>
<item name="android:statusBarColor">@color/primaryColor</item>
<item name="actionBarTheme">@style/ThemeOverlay.MaterialComponents.Dark.ActionBar</item>
<item name="actionBarPopupTheme">@style/ThemeOverlay.MaterialComponents.Dark</item>
</style>
<style name="AppTheme.Dark" parent="Theme.MaterialComponents.Bridge">
<!-- your dark theme attributes -->
<item name="colorPrimary">@color/md_red_500</item>
<item name="colorPrimaryDark">@color/md_red_700</item>
<item name="colorAccent">@color/md_yellow_500</item>
<item name="android:statusBarColor">?attr/colorPrimary</item>
<item name="android:navigationBarColor">?attr/colorPrimarySurface</item>
</style>
<style name="AppTheme.DayNight" parent="AppTheme.Light" />
<style name="AppTheme.DayNight.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
</resources>
Establecer el tema mediante código
Mediante código Kotlin podemos establecer como actuará el modo oscuro, podemos forzar que la aplicación se muestre con tema oscuro, claro, o dependiendo del sistema, se hace con la función appCompatDelegate.setDefaultNightMode(<valor_modo>)
- AppCompatDelegate.MODE_NIGHT_NO para establecer el tema claro
- AppCompatDelegate.MODE_NIGHT_YES para establecer el tema oscuro
- AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM para establcer el tema predeterminado del sistema Android Q y en Android P cuando se activa el modo ahorro de batería
Lo ideal en la clase MyApplication que hereda de Application en init esteblecer
class MyApplication : Application() {
...
override fun onCreate() {
super.onCreate()
AppCompatDelegate.setDefaultNightMode(
AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
)
}
..
}
//AndroidManifest.xml, esteblecer <application
android:name=".MyApplication"
Obtener el estado de Modo Oscuro
Si queremos saber como está establecido el modo oscuro
fun isDarkTheme(activity: Activity): Boolean {
return activity.resources.configuration.uiMode and
Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES
}
El siguiente enlace puedes obtener el ejemplo usado TestNavigationNavWithDarkTheme
Recursos adicionales
- Lista de Colores Material Design
- Dark Theme & Gesture Navigation (Google I/O’19)
- DayNight — Adding a dark theme to your app
- Official docs on Dark Theme
- Material design guidelines for Dark Theme implementation
- How to Design a Dark Theme Using Material (Google I/O’19)
- Best Practices for Themes and Styles (Android Dev Summit ‘18)
Hola, hice el modo oscuro utilizando el appCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO), ya que no deseo mayor personalización. Utilizando un botón switch para encender y apagar el modo oscuro, y quisiera saber cómo puedo guardar esta línea de código en SharedPreferences.
Gracias
Me gustaMe gusta