Índice
1. Para alternar entre o modo branco e noturno, destrua e reinicie a Atividade para resolver:
2. Copie o seguinte método de classe de ferramentas e use-o diretamente:
5. Precauções para mudar o modo noturno branco:
1. Para alternar entre o modo branco e noturno, destrua e reinicie a Atividade para resolver:
Quando o modo noturno branco for ativado, a atividade será destruída e recarregada. O Google espera que recarregar a atividade possa atualizar a interface do usuário da página, mas meu aplicativo não está adaptado para o modo escuro, então a experiência do usuário é muito ruim. A solução é :
Adicione ou anexe o atributo android:configChanges="uiMode" a Activiyty em AndroidManifest.xml :
Detalhes do parâmetro configChanges:
2. Adaptação ao modo escuro
1. Adicione dependências:
api 'com.android.support:appcompat-v7:24.1.1' 或者更高版本
或使用androidx的依赖都可以
2. Copie o seguinte método de classe de ferramentas e use-o diretamente:
/**
* 暗黑模式适配工具类
*/
public class DarkModeUtils {
public static final String KEY_MODE = "white_night_mode_sp";
/**
* 在 Application 的 onCreate() 方法中调用
*/
public static void init(Application application) {
int nightMode = getNightModel(application);
AppCompatDelegate.setDefaultNightMode(nightMode);
}
/**
* 应用夜间模式
*/
public static void applyNightMode(Context context) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
setNightModel(context, AppCompatDelegate.MODE_NIGHT_YES);
}
/**
* 应用日间模式
*/
public static void applyDayMode(Context context) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
setNightModel(context, AppCompatDelegate.MODE_NIGHT_NO);
}
/**
* 跟随系统主题时需要动态切换
*/
public static void applySystemMode(Context context) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
setNightModel(context, AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
}
/**
* 判断App当前是否处于暗黑模式状态
*/
public static boolean isDarkMode(Context context) {
int nightMode = getNightModel(context);
if (nightMode == AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM) {
int applicationUiMode = context.getResources().getConfiguration().uiMode;
int systemMode = applicationUiMode & Configuration.UI_MODE_NIGHT_MASK;
return systemMode == Configuration.UI_MODE_NIGHT_YES;
} else {
return nightMode == AppCompatDelegate.MODE_NIGHT_YES;
}
}
private static int getNightModel(Context context) {
SharedPreferences sp = context.getSharedPreferences(KEY_MODE, Context.MODE_PRIVATE);
return sp.getInt(KEY_MODE, AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
}
public static void setNightModel(Context context, int nightMode) {
SharedPreferences sp = context.getSharedPreferences(KEY_MODE, Context.MODE_PRIVATE);
sp.edit().putInt(KEY_MODE, nightMode).apply();
}
}
3. Adaptação de recursos:
Crie uma pasta de modo escuro para fotos e cores, e o sistema usará automaticamente os recursos dessa pasta ao alternar para o modo escuro:
4. Callback de adaptação:
Se o atributo android:configChanges="uiMode" for adicionado ou adicionado , o onConfigurationChanged() da Activity será chamado de volta depois que o modo for trocado . Recomenda-se reescrever este método em BaseActivity e fazer as adaptações correspondentes nele.
Você pode chamar o método DarkModeUtils.isDarkMode(this) na classe de ferramenta acima para determinar se está no modo escuro. Você também pode chamar o método na classe de ferramenta para alternar o modo noturno branco do aplicativo. As observações são as seguintes:
5. Precauções para mudar o modo noturno branco:
(1) Chame DarkModeUtils.init(this) no método onCreate() de Application para inicializar a classe de ferramenta;
(2) Chame o método DarkModeUtils.applySystemMode(this) para alternar entre os modos branco e noturno do sistema adaptativo;
(3) Se a dependência de androidx for usada, ela pode ser chamada diretamente.
(4) Se você usar dependências de suporte, precisará chamar manualmente o método recreate() da Activity para reconstruir a página ou fazer diferentes adaptações para todas as Views na página.
Exemplo de chamada direta do método recreate() para reconstruir a página:
Exemplo de configuração do modo branco e noturno para cada Visualização na página:
(5) Veja o código fonte abaixo para razões específicas:
versão androidx:
/**
* Sets the default night mode. This is the default value used for all components, but can
* be overridden locally via {@link #setLocalNightMode(int)}.
*
* <p>This is the primary method to control the DayNight functionality, since it allows
* the delegates to avoid unnecessary recreations when possible.</p>
*
* <p>If this method is called after any host components with attached
* {@link AppCompatDelegate}s have been 'started', a {@code uiMode} configuration change
* will occur in each. This may result in those components being recreated, depending
* on their manifest configuration.</p>
*
* <p>Defaults to {@link #MODE_NIGHT_FOLLOW_SYSTEM}.</p>
*
* @see #setLocalNightMode(int)
* @see #getDefaultNightMode()
*/
public static void setDefaultNightMode(@NightMode int mode) {
switch (mode) {
case MODE_NIGHT_NO:
case MODE_NIGHT_YES:
case MODE_NIGHT_FOLLOW_SYSTEM:
case MODE_NIGHT_AUTO_TIME:
case MODE_NIGHT_AUTO_BATTERY:
if (sDefaultNightMode != mode) {
sDefaultNightMode = mode;
applyDayNightToActiveDelegates();
}
break;
default:
Log.d(TAG, "setDefaultNightMode() called with an unknown mode");
break;
}
}
versão de suporte:
public static void setDefaultNightMode(int mode) {
switch(mode) {
case -1:
case 0:
case 1:
case 2:
sDefaultNightMode = mode;
break;
default:
Log.d("AppCompatDelegate", "setDefaultNightMode() called with an unknown mode");
}
}
Após a comparação, pode-se descobrir que, depois que o androidx mudou para o modo escuro, ele chamou ativamente o método applyDayNightToActiveDelegates() para reconstruir a atividade. Mas não há suporte, apenas atribuição. Portanto, o uso da versão de suporte precisa chamar o método recreate() da Activity a ser reconstruída.