About dark mode

The Android client AndroidQ has started to support the dark mode, and the experience is also very good, so some many large apps will also adapt to this. There are two methods of adaptation:

1 Custom method: Add a set of night files, and personalize drawable, colors, style, etc. according to the UI design.

  Advantages: can achieve the desired effect according to needs

 Disadvantages: It may be a little more complicated. For old projects, especially color naming is not standardized or there are too many components, it is very troublesome. Even worse, rely on components provided by third-party vendors.

2.  自动适配 Force Dark。<item name="android:forceDarkAllowed" tools:targetApi="q">true </item> 

  Advantages: simple, the effect is quite good.

  Disadvantages: Not conducive to personalized adaptation.

 

1. Customized way:

1. Add a new set of files corresponding to related resource files, see the picture below:

For example, colors.xml of values ​​and colors.xml of values-night are kept consistent, but the same name corresponds to different color values ​​in these two resources. The same is true for other drawable styles. It’s just that the theme of AppTheme needs to be changed to:

<style name="AppCompatTheme" parent="Theme.AppCompat.DayNight">

2. The dark mode switch of the monitoring system:

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    int mSysThemeConfig = newConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK;
    switch (mSysThemeConfig) {
        // 亮色主题
        case Configuration.UI_MODE_NIGHT_NO:
            AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
            recreate();
            break;
        // 深色主题
        case Configuration.UI_MODE_NIGHT_YES:
            AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
            recreate();
            break;
    }

}

Note: Be sure to configure properties for Activity in the configuration file: android:configChanges="uiMode"

At this time, when you switch the system dark mode switch of the APP, the APP will recreate() on this page, and then according to the mode set in your code to match whether to load the resource file corresponding to night or the resource file in normal mode, so as to achieve the dark The purpose of adaptation.  

Be careful: 1. The naming of colors can be directly linked to the color. For example: <color name="color_55000000">#55000000</color>. For the dark mode, multiple names that point to one color can be named separately, and then point to it together, such as :

When multiple people adapt together, in order to avoid possible conflicts, special adaptations can be written separately in their own personalized area.

2. Be sure to pay attention to the colors and image resources dynamically used in the code, and don't forget to adapt.

3. Components in the project. If the color, resource file, etc. in the component are named with a prefix or something, it will not conflict with the main project. At this time, you only need to adapt the colors.xml and style and night corresponding to the drawable under night in the main project. But if the naming is inconsistent, there will be a conflict of adaptation, and the conflict of the component or the main project needs to be modified at this time. Of course, you can also get a set of night files in the component like the main project. How to change the conflict or how to change it (when the resource of the component is named the same as the resource of the main project, the main project will be used when packaging and merging resources. quasi)

  4. For the components of third-party manufacturers (generally not allowed to modify), if the color naming of its own and the color naming of the main project conflict, it will naturally cause some dark and light colors in the components, which is very bad. Need to coordinate with a third party to make changes. We don't adapt the components of general third-party vendors, but it may require dynamic adaptation for the case where the Activity in the main project inherits the on-field components.

It can also be like this: add an xml to the values ​​of the main project, and define style and color in it. At this time, he can use a color name of the main project that has been adapted. As long as the name of a certain color or style you want to adapt to build is the same as the color name and style in this new file, the adaptation is also carried out. As shown below:

2. Automatic adaptation to Force Dark

1. The Theme in style is modified to: parent="Theme.AppCompat.Light.NoActionBar"

2.<item name="android:forceDarkAllowed" tools:targetApi="q">true </item>

Then it's ok. When the mode switch is switched, the system automatically adapts and the effect is good.

This adapts to both native and webview pages. This is very important.

The above content is basically satisfied. The Android client is adapted to the dark mode. However, there may be many other requirements during development, and these requirements will lead to it. I ran into two problems

1. The web page is configured with the attribute prefers-color-scheme, and the  @media corresponding css style is matched after judgment, as shown in the figure below, in order to achieve the dark adaptation of the Android web page. (Ios can be, but many Android phones can’t adapt to it)

body {
  color: #333; /* 在 light mode 时,页面中的文字颜色 */
}
@media screen and (prefers-color-scheme: dark) {
  body {
    color: #fff; /* 如果系统切换到 dark mode 时,页面中的文字颜色改变 */
  }
}

 However, this attribute requires the Chromum version of the kernel browser to be >=81, and many mobile phones are currently lower than this version, which makes this impossible.

So I found the following method:

1. On the client side, dynamically inject css styles according to the logic of the dark switch, you can refer to https://blog.csdn.net/anhenzhufeng/article/details/78931586?utm_medium=distribute.pc_relevant.none-task-blog-baidujs- 3     this article.  

Disadvantages: 1. First of all, you need to have a certain foundation of html, because you need to adapt to special places 2. In addition, the controls on the webpage are still fragmented, which makes it particularly troublesome to deal with

2. Pass the mobile phone mode status to the web page through Js interaction for processing

3. Using our second method, only to adapt to WebviewActivity, it is enough to adapt the style to this Activity separately. Other native interfaces can be adapted in a custom way (I use this)

2. Requirements: The client has a switch to manually control the dark mode in a second or third level interface. Whether the mobile phone displays the dark mode is restricted by the dark switch of the mobile phone system and this switch, and the interface must stay on The current interface is not allowed to jump to the home page (a similar primary interface such as MainActiivty).

If it is allowed to jump to the homepage, it is easy, because the task stack is emptied, and every interface reloaded will be the same as the homepage (this is the case for WeChat, no matter which interface you change the mode, he will jump to the homepage , And flashed for a while). If it is not allowed, then when you dynamically force the current interface to be set to a certain mode, the loaded interface in the task stack will not change. How to solve this demand?

Very troublesome, can be achieved, but the customer experience is not very good. I will only talk about ideas below

1. Create a global cache, and store the current mode state of the interface in the cache every time an interface is loaded in BaseActivity

2. When the mode is switched on a certain interface and the state of the APP needs to be changed, the current interface can be changed directly. For other activities that have been loaded into the stack, the mode in the cache is obtained in onResume and compared with the mode that should be currently displayed. If they are the same, there is no need to modify them, otherwise they will be set dynamically according to the logic.

AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);//Set the light color dynamically
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);//Set the dark color dynamically

And re-modify the state of this interface in the cache, when destroying, remove the storage of this interface

3. Because it is related to the transformation of old projects, there will be such a problem: setContentView() is placed before super.onCreate(), (because it may involve logical processing) when the mode state is modified, recreate( ) Was not rendered as it should be afterwards. In response to this situation, my treatment is to reload once for this situation in onRestoreInstanceState.

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    if (IMApp.getInstance().isChangeConfigMode) {
        String flag = MeUtils.getString(SystemParamManager.getSystemParam(SystemParam.BIG_TYPE_CUSTOMER_PARAM,       SystemParam.SMALL_TYPE_ME_SETTING_DARK_SWITCH));
        IMApp.getInstance().isChangeConfigMode = false;
        if (flag.equals("1") && !isOncreateFirst) {
            Intent intent = getIntent();
            thisActivity.finish();
            overridePendingTransition(0, 0);
            startActivity(intent);
        }
    } else {
        IMApp.getInstance().isChangeConfigMode = false;
    }
}

These are all handled uniformly in Base, as long as the conditions are set.

 

Summary: When adapting to complex and old projects for many years, we may encounter various problems. This requires us to constantly try and optimize.

have not decide:

Huawei P30 mate30Pro These are currently new mobile phones, they will only be controlled by the system. The dark effect has nothing to do with your customization. This can't be done.

Install the APP for the first time from the Splash interface according to: system is black + own switch is off = I force the APP to be set to bright color, when entering MainActivty, the first loaded Fragment inside will have rendering problems, some lines or icons It appears white and cannot be rendered. But other Fragments are fine, and other Activities are fine. Exit and re-enter, there is no problem, and there will be no problem in the future, I don't understand this.

 

Guess you like

Origin blog.csdn.net/lk2021991/article/details/107517455