Android Night Mode Best Practice _android

Source: Internet
Author: User

Because the Android settings do not have the option of night mode, for those who like to play the mobile phone before bedtime, can simply adjust the screen brightness to improve the experience. More and more applications are starting to add nighttime models to their apps, and Google will soon add this feature to the Android system.

The industry on the implementation of night mode, there are two mainstream programs, each has its pros and cons, I am more highly recommended the third option:

1, by switching theme to achieve night mode.
2, through the resource ID mapping way to implement the night mode.
3, by modifying uimode to switch night mode.

It is worth mentioning that the above mentioned several scenarios, are embedded in the apk of resources, such as Sina Weibo, the need to download the implementation of the night mode scheme, there are many online, not discussed here.

Here is a brief description of the implementation of the following scenarios:

One, by switching theme to achieve night mode

First in Attrs.xml, define attributes for content that needs to change with theme

<?xml version= "1.0" encoding= "Utf-8"?>
<resources> <attr name= "TextColor" format= "color|"
  Reference "/> <attr name= mainbackground" format= "color|reference"/>
</resources>

Second, in different theme, set different values for the properties, and define the theme in Styles.xml as follows

<?xml version= "1.0" encoding= "Utf-8"?>
<resources>
  <!--default--> <style
  "Name=" Themedefault "parent=" Theme.AppCompat.Light.DarkActionBar ">
    <item name=" Mainbackground "> #ffffff < /item>
    <item name= "TextColor" > #000000 </item>
  </style>
  <!--night-->
  < Style name= "Themenight" parent= "Theme.AppCompat.Light.DarkActionBar" >
    <item name= "Mainbackground" ># 000000</item>
    <item name= "TextColor" > #ffffff </item>
  </style>
</ Resources>

Use the corresponding value in the layout file to get the values for the different theme by using the Attr/property name.

<linearlayout xmlns:android= "http://schemas.android.com/apk/res/android"
  android= "@+id/main_screen"
  Android:layout_width= "Match_parent"
  android:layout_height= "match_parent"
  android:orientation= "vertical" "
  android:background=" Attr/mainbackground ">
  <button
    android:id=" @+id/button "
    android: Layout_width= "Wrap_content"
    android:layout_height= "wrap_content"
    android:layout_gravity= "center"
    android:text= "Change theme"
    android:onclick= "Changetheme" android:textcolor= "Attr/textcolor"/>
</LinearLayout>

The following Changetheme method is called in the activity, where Isnightmode is a global variable that is used to mark the current night mode, and after the theme is set, You also need to call restartactivity or Setcontentview to refresh the UI again.

public void Changetheme () {
  if (isnightmode) {
    settheme (r.style.themedefault);
    Isnightmode = false;
  } else {
    settheme (r.style.themenight);
    Isnightmode = true;
  }
  Setcontentview (R.layout.activity_main);
}

This completes a simple night-mode implementation, including many apps such as Google's own, that implement the nightly pattern, which should also be the way Android is officially recommended.

But this kind of way has some insufficiency, the large-scale application, needs to change with theme the attribute to be many, all needs to define, a bit troublesome, another disadvantage is to make the new theme effective, the general need restartactivity to switch UI, will cause the interface flicker when the theme is switched.

However, you can also use the following Updatetheme method to update only the parts that need to be updated, to avoid flicker problems, but to write a bunch of updatetheme methods.

private void Updatetheme () {
  Typedvalue typedvalue = new Typedvalue ();
  Resources.theme Theme = Gettheme ();
  Theme.resolveattribute (R.attr.textcolor, Typedvalue, true);
  Findviewbyid (R.id.button). SetBackgroundColor (typedvalue.data);
  Theme.resolveattribute (R.attr.mainbackground, Typedvalue, true);
  Findviewbyid (R.id.main_screen). SetBackgroundColor (Typedvalue.data);
}

Second, the way to implement the night mode through Resource ID mapping

When a resource is acquired through an ID, it is converted to a nightly pattern ID, and then resources are obtained by resource.

public static drawable getdrawable (context context, int id) {return
  context.getresources (). Getdrawable Getresid ( ID);
}

public static int Getresid (int defaultresid) {
  if (!isnightmode ()) {return
    defaultresid;
  }
  if (Sresourcemap = = null) {
    buildresourcemap ();
  }
  int themedresid = Sresourcemap.get (DEFAULTRESID);
  return Themedresid = = 0? Defaultresid:themedresid;
}

This is done by HashMap the resid of daytime mode and the Resid of night mode to one by one.

private static void Buildresourcemap () {
  sresourcemap = new Sparseintarray ();
  Sresourcemap.put (R.drawable.common_background, r.drawable.common_background_night);
  // ...
}

This program is simple and rough, the trouble is the same as the first scenario: each add resources need to establish a mapping relationship, the way to refresh the UI is similar to the first scenario, looks like today's headlines, NetEase news clients and other mainstream news reading applications are implemented in this way night mode.

Third, by modifying uimode to switch night mode

First, the place where the resource is obtained is unified, and the application corresponding resources are used to initialize the Resourcesmanager init method in application's OnCreate.

public static void init (context context) {
  sres = context.getresources ();
}


When you switch nightly mode, updating the configuration of resources by updating Uimode, the system will read the resource under the corresponding night according to its uimode, and add a-night suffix to the resources in the RES for night mode, such as Values-night, Drawable-night.

public static void Updatenightmode (Boolean on) {
  displaymetrics dm = Sres.getdisplaymetrics ();
  Configuration config = sres.getconfiguration ();
  Config.uimode &= ~configuration.ui_mode_night_mask;
  Config.uimode |= on? Configuration.UI_MODE_NIGHT_YES:Configuration.UI_MODE_NIGHT_NO;
  Sres.updateconfiguration (config, DM);

As for the Android resource reading, we can refer to the Lao's blog, "The Android application resource lookup process," and analyze how resources are being accurately found. The advantage of this approach versus the first two is that resource additions are very simple and clear, but updates on the UI are not very smooth.

How did I find the third option?

The search for night in the Android development document is found as follows, and can be achieved by Uimodemanager

Night:night time
Notnight:day time
Added in API level 8.

This can change during the life of your application if night mode are left in Auto mode (default), in which case the mode C Hanges based on the "Time". You can enable or disable this mode using Uimodemanager. Handling Runtime Changes For information about I this affects your application during Runtime.

Unfortunately, it must be in the driving mode to be effective, it is not to open the driving mode and then set it, in fact, is not feasible, driving mode, the system UI changes, this is not desirable.

/**
* Sets the night mode. Changes to the night mode are only effective when
* the "car" or desk mode is enabled on a device.
*
* The mode can be one of:
* {@link #MODE_NIGHT_NO sets the device into Notnight
* mode.
* {@link #MODE_NIGHT_YES}-sets the device into NIGHT MODE.
* {@link #MODE_NIGHT_AUTO}-Automatic night/notnight switching
* Depending on the location and certain other sensors.
*
/public void Setnightmode (int mode)

Starting from the source, Uimodemanagerservice.java's Setnightmode method:

if (isdoingnightmodelocked () && mnightmode!= mode) {
  Settings.Secure.putInt (GetContext (). Getcontentresolver (), Settings.Secure.UI_NIGHT_MODE, MODE);
  Mnightmode = mode;
  updatelocked (0, 0);
}

Boolean isdoingnightmodelocked () {return
  mcarmodeenabled | | mdockstate!= intent.extra_dock_state_undocked;
}

The state of Dockstate and Mcardmode is judged in the isdoingnightmodelocked, and if the condition actually modifies only the Mnightmode value, continue to trace the Updatelocked method. You can see that the configuration Uimode is updated in updateconfigurationlocked.

Let's turn to configuration's Uimode description:

/**
* Bit Mask of the UI mode. Currently there are two fields:
* The
{@link #UI_MODE_TYPE_MASK} bits define the overall UI MODE of
* Devi Ce. They may be one of {@link #UI_MODE_TYPE_UNDEFINED},
* {@link #UI_MODE_TYPE_NORMAL}, {@link #UI_MODE_TYPE_DESK},
* {@link #UI_MODE_TYPE_CAR}, {@link #UI_MODE_TYPE_TELEVISION},
* {@link #UI_MODE_TYPE_APPLIANCE}, or {@link #UI_ Mode_type_watch}.
*
* The
{@link #UI_MODE_NIGHT_MASK} defines whether the screen
* was in a special MODE. They may be one of {@link #UI_MODE_NIGHT_UNDEFINED},
* {@link #UI_MODE_NIGHT_NO} or {@link #UI_MODE_NIGHT_YES}.
   
    */public
int uimode;

   

Uimode for public can be set directly, since the Uimodemanager set Nightmode only changed the configuration Uimode, then we can directly change its uimode it?

In fact, only a small piece of code can be achieved, but if you do not see the implementation of Uimodemanager night mode, do not think that only need to update the configuration uimode on it.

The above is the entire content of this article, I hope to help you learn.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.