[[416377]] This article is reprinted from the WeChat public account "Android Development Programming", the author is Android Development Programming. Please contact the Android Development Programming public account for reprinting this article. Preface Immersive means providing users with a completely immersive experience, making them feel like they are in a virtual world; This experience is widely used in various games. After opening most games, the screen will be completely occupied by the game, allowing players to immerse themselves in it, and the immersive effect will be better in terms of experience. Many people have written articles on the principles of immersion online, but none of them are very clear and confusing; Today we will thoroughly summarize the implementation and principles of immersion; 1. Immersive Concept and Why Use Immersive 1. Immersive concept- Before Android 4.4, the status bar was always black. In 4.4, the windowTranslucentStatus feature was introduced, which began to introduce the concept of "immersive status bar". Google mentioned "Translucent system UI styling" in the API description page of Android 4.4, which means transparent system UI style.
- The "immersive status bar" should be more accurately called the "transparent bar", which is a new design specification defined in 4.4;
- Simply put, when the software is opened, the notification bar and the top color of the software are integrated, which makes the software more consistent with the system itself. At the same time, the color of the notification bar is no longer just white or black.
- Immersive means that the phone screen is displayed in full screen without any controls built into the phone;
2. Why use immersive- If there is no immersive status bar in the app, the status bar will be black, and the black (white) bar below is very different from the main interface of the app. This sacrifices visual height to a certain extent, and the interface area becomes smaller. The most important thing is the user's vision and experience;
- To put it bluntly, if the user experience is good and the experience is enjoyable, the retention rate will be high, so the leader will definitely ask us to develop an immersive theme style;
2. Immersive Principles and Compatibility From Android 4.4 to now (Android 7.1), immersion can be roughly divided into three stages: - Android4.4 (API 19) - Android 5.0 (API 21): Immersion can be achieved at this stage, but the performance is not very good. The implementation method is: set the status bar to transparent and full-screen mode through FLAG_TRANSLUCENT_STATUS, and then add a View of the same size as the StatusBar and set the background of the View to the color we want to achieve immersion;
- Android 5.0 (API 21) and above: In Android 5.0, an important attribute and method android:statusBarColor (the corresponding method is setStatusBarColor) was added, through which we can easily achieve immersion. In other words, starting from Android 5.0, the system truly supports immersion;
- Android 6.0 (API 23) and above: In fact, the implementation of Android 6.0 and above is the same as Android 5.0 +. Why is it classified as a separate and important stage? Because starting from Android 6.0 (API 23), we can change the drawing mode of the status bar to display white or light black content and icons (except Meizu phones, Meizu has made source code changes, which can be implemented below 6.0);
1. Android4.4(API 19)-Android 5.0(API 21) Android added an important attribute in 4.4: FLAG_TRANSLUCENT_STATUS- /**
- * Window flag: request a translucent status bar with minimal system-provided
- * background protection.
- *
- * <p>This flag can be controlled in your theme through the
- * {@link android.R.attr#windowTranslucentStatus} attribute; this attribute
- * is automatically set for you in the standard translucent decor themes
- * such as
- * {@link android.R.style#Theme_Holo_NoActionBar_TranslucentDecor},
- * {@link android.R.style#Theme_Holo_Light_NoActionBar_TranslucentDecor},
- * {@link android.R.style#Theme_DeviceDefault_NoActionBar_TranslucentDecor}, and
- * {@link android.R.style#Theme_DeviceDefault_Light_NoActionBar_TranslucentDecor}.</p>
- *
- * <p> When this flag is enabled for a window, it automatically sets
- * the system UI visibility flags {@link View #SYSTEM_UI_FLAG_LAYOUT_STABLE} and
- * {@link View #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}.</p>
- */
- public static final int FLAG_TRANSLUCENT_STATUS = 0x04000000;
Set the status bar to transparent and change to full screen mode. When this property is valid, the system UI visibility flags SYSTEM_UI_FLAG_LAYOUT_STABLE and SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN are automatically set. Set the status bar to transparent and full-screen mode through FLAG_TRANSLUCENT_STATUS, then add a View of the same size as the StatusBar and set the background of the View to the color we want to achieve immersion. ①, Set FLAG_TRANSLUCENT_STATUS, which can be set in the code as follows: - activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
Or you can set the property windowTranslucentStatus in the theme, as follows: ②. If necessary, set a placeholder View of the same size as the StatusBar. If not set, the content View will be pushed up to the height of the StatusBar. To extend the image to the status bar, just set FLAG_TRANSLUCENT_STATUS The code to add a placeholder View is as follows: - //Get decorView
- ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
- int count = decorView.getChildCount();
- //Determine whether statusBarView has been added
- if ( count > 0 && decorView.getChildAt( count - 1) instanceof StatusBarView) {
- decorView.getChildAt( count - 1).setBackgroundColor(calculateStatusColor(color, statusBarAlpha));
- } else {
- //Create a new view with the same height and width as the status bar
- StatusBarView statusView = createStatusBarView(activity, color, statusBarAlpha);
- decorView.addView(statusView);
- }
- ViewGroup rootView = (ViewGroup) ((ViewGroup) activity.findViewById(android.R.id.content)).getChildAt(0);
- //rootview will not leave status bar space for the status bar
- ViewCompat.setFitsSystemWindows(rootView, true );
- rootView.setClipToPadding( true );
- private static StatusBarView createStatusBarView(Activity activity, int color, int alpha) {
- // Draw a rectangle as high as the status bar
- StatusBarView statusBarView = new StatusBarView(activity);
- LinearLayout.LayoutParams params =
- new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity));
- statusBarView.setLayoutParams(params);
- statusBarView.setBackgroundColor(calculateStatusColor(color, alpha));
- return statusBarView;
- }
2. Android 5.0 (API 21) and above Android 5.0 is a milestone version. Google added a relatively important method setStatusBarColor (corresponding attribute: android:statusBarColor). Through this method, you can easily implement an immersive status bar. The method is as follows: - /**
- * Sets the color of the status bar to {@code color}.
- *
- * For this to take effect,
- * the window must be drawing the system bar backgrounds with
- * {@link android. view .WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} and
- * {@link android. view .WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS} must not be set .
- *
- * If {@code color} is not opaque, consider setting
- * {@link android. view . View #SYSTEM_UI_FLAG_LAYOUT_STABLE} and
- * {@link android. view . View #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}.
- * <p>
- * The transitionName for the view background will be "android:status:background" .
- * </p>
- */
- public abstract void setStatusBarColor(@ColorInt int color);
However, for this method to work, it must be used in conjunction with a Flag. FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS must be set, and FLAG_TRANSLUCENT_STATUS cannot be set (this is only used in Android 4.4). Setting FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS indicates that Window is responsible for the background drawing of the system bar, drawing the system bar (status bar and navigation bar) with a transparent background, and then filling the corresponding area with the colors of getStatusBarColor() and getNavigationBarColor(). The implementation code is as follows: - getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
- //Note to clear the FLAG_TRANSLUCENT_STATUS flag
- getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
- getWindow().setStatusBarColor(getResources().getColor(android.R.color.holo_red_light));
You can also use it directly in Theme, add the following theme in the vlues-v21 folder: - <style name = "MDTheme" parent= "Theme.Design.Light.NoActionBar" >
- <item name = "android:windowTranslucentStatus" > false </item>
- <item name = "android:windowDrawsSystemBarBackgrounds" > true </item>
- <item name = "android:statusBarColor" >@android:color/holo_red_light</item>
- </style>
If you want the image to extend to the status bar, just set windowTranslucentStatus, set statusBarColor to transparent, and set the properties of DecorView: - getWindow().getDecorView().setSystemUiVisibility( View .SYSTEM_UI_FLAG_FULLSCREEN |
- View .SYSTEM_UI_FLAG_LAYOUT_STABLE);
3. Android 6.0 + In fact, the implementation method of Android 6.0 and above is the same as that of Android 5.0 +. Why is it classified as a separate important stage? Because starting from Android 6.0 (API 23), we can change the drawing mode of the status bar to display white or light black content and icons; When using immersive mode on Android 6.0 or above, you will encounter a problem. The color of the text and icons on the status bar of the Android system is white. When the color of the status bar is close to light color, the content on the status bar cannot be seen clearly. Android 6.0 adds a new attribute to solve this problem. The attribute is SYSTEM_UI_FLAG_LIGHT_STATUS_BAR, which can set the status bar text color and icon to light black. - /**
- * Flag for {@link #setSystemUiVisibility( int )}: Requests the status bar to draw in a mode that
- * is compatible with light status bar backgrounds.
- *
- * <p> For this to take effect, the window must request
- * {@link android. view .WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
- * FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
- * {@link android. view .WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
- * FLAG_TRANSLUCENT_STATUS}.
- *
- * @see android.R.attr#windowLightStatusBar
- */
- public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
However, for this property to take effect, the FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS flag must be set first and the FLAG_TRANSLUCENT_STATUS flag must be cleared at the same time. (1) The status bar font is white - getWindow().getDecorView().setSystemUiVisibility( View .SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); //The font is white by default
- getWindow().setStatusBarColor(android.R.color.transparent);//Transparent background
(2) Status bar font is black - getWindow().getDecorView().setSystemUiVisibility( View .SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN| View .SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);//Black font
- getWindow().setStatusBarColor(android.R.color.transparent);//Transparent background
3. Analysis of Difficulties in Actual Immersive Development 1. Summary of flags commonly used in immersion ①. View.SYSTEM_UI_FLAG_FULLSCREEN: The Activity is displayed in full screen, and the status bar is hidden and covered ②.View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN: The Activity is displayed in full screen, but the status bar will not be hidden and covered, and the status bar is still visible. ③. View.SYSTEM_UI_FLAG_LAYOUT_STABLE SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN and SYSTEM_UI_FLAG_LAYOUT_STABLE are used. Note that the two flags must be used together, which means that the main content of the application will occupy the space of the system status bar. ④. View.SYSTEM_UI_FLAG_HIDE_NAVIGATION: Hide the virtual buttons (navigation bar). Some mobile phones use virtual buttons instead of physical buttons. ⑤. View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION: The effect of hiding the navigation bar is the same as View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN ⑥. Some mobile phones display in full screen by default. Sometimes you need to force it not to display in full screen. Use the following flag Not full screen - getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
Full Screen Display - getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
2. Status bar font color adaptation- /***
- * Status bar font adaptation solution
- * @param activity
- * @param dark
- */
- public static void darkMode(Activity activity, boolean dark) {
- try {
- if (isFlyme4Later()) {
- //Meizu
- darkModeForFlyme4(activity.getWindow(), dark);
- } else if (isMIUI6Later()) {
- //Millet
- darkModeForMIUI6(activity.getWindow(), dark);
- } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- //Other general solutions
- darkModeForM(activity.getWindow(), dark);
- }
- } catch (Exception e) {
- }
- }
- /***
- * Status bar font adaptation solution
- * @param activity
- * @param dark
- */
- public static void darkMode(Activity activity, boolean dark) {
- try {
- if (isFlyme4Later()) {
- //Meizu
- darkModeForFlyme4(activity.getWindow(), dark);
- } else if (isMIUI6Later()) {
- //Millet
- darkModeForMIUI6(activity.getWindow(), dark);
- } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- //Other general solutions
- darkModeForM(activity.getWindow(), dark);
- }
- } catch (Exception e) {
- }
- }
- /**
- * Determine whether it is Flyme4 or above
- */
- public static boolean isFlyme4Later() {
- return Build.FINGERPRINT. contains ( "Flyme_OS_4" )
- || Build.VERSION.INCREMENTAL. contains ( "Flyme_OS_4" )
- || Pattern.compile( "Flyme OS [4|5]" , Pattern.CASE_INSENSITIVE).matcher(Build.DISPLAY).find();
- }
- /**
- * Determine whether it is MIUI6 or above
- */
- @SuppressLint( "PrivateApi" )
- public static boolean isMIUI6Later() {
- try {
- Class<?> clz = Class.forName( "android.os.SystemProperties" );
- Method mtd = clz.getMethod( "get" , String.class);
- String val = (String) mtd.invoke( null , "ro.miui.ui.version.name" );
- assert val != null ;
- val = val.replaceAll( "[vV]" , "" );
- int version = Integer .parseInt(val);
- return version >= 6;
- } catch (Exception e) {
- return false ;
- }
- }
- /**
- * Android 6.0 set font color
- */
- @RequiresApi(Build.VERSION_CODES.M)
- private static void darkModeForM(Window window, boolean dark) {
- window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
- window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
- window.setStatusBarColor(Color.TRANSPARENT);
- int systemUiVisibility = window.getDecorView().getSystemUiVisibility();
- if (dark) {
- systemUiVisibility |= View .SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
- } else {
- systemUiVisibility &= ~ View .SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
- }
- window.getDecorView().setSystemUiVisibility(systemUiVisibility);
- }
3. Understanding and usage of fitsSystemWindows- When implementing the immersive status bar, we will use the attribute android:fitsSystemWindows="true";
- After setting a transparent status bar (StatusBar) or navigation bar (NavigationBar), the content of the activity will extend to the corresponding area, causing the area to overlap. This has a particularly great impact on the situation where the content contains interactive controls. To solve this problem, the fitsSystemWindows attribute appears. We can add this attribute to any view. All padding attributes of the view with this attribute set will be invalid, and the system will add paddingTop and paddingBottom to the view according to the situation (when setting a transparent status bar, the system will add a paddingTop value equal to the status bar height to the view, and when setting a transparent navigation bar, the system will add a paddingBottom value equal to the navigation bar height to the view);
- By default, when multiple views set this property, only the outermost view will take effect; we can also override some methods of the custom view to determine our own processing and whether the child view has the opportunity to truncate and respond to fitsSystemWindows. For example, DrawerLayout, CoordinatorLayout, and CollapsingToolbarLayout use custom fitsSystemWindow (no wonder setting this property for drawerLayout is inconsistent with our understanding of the behavior)
- There are two effects to be achieved: the background image fills the entire screen, and the status bar and actionBar have the same color.
We just need to extend the content to the status bar and navigation bar, and then set the image background for the root layout. If you need the content not to appear in the status bar and navigation bar area, add android:fitsSystemWindows="true" - /**
- * Get the status bar height
- */
- public static int getStatusBarHeight(Context context) {
- int result = 24;
- int resId = context.getResources().getIdentifier( "status_bar_height" , "dimen" , "android" );
- if (resId > 0) {
- result = context.getResources().getDimensionPixelSize(resId);
- } else {
- result = ( int ) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
- result, Resources.getSystem().getDisplayMetrics());
- }
- return result;
- }
4. Immersive Wheel Solution In fact, there are many mature immersive solutions on the Internet, and there is no need for us to encapsulate them. The main thing is to understand the knowledge points so that we can troubleshoot problems when we encounter them. Online wheel StatusBarUtil It has the following functions: 1. Set the status bar color- StatusBarUtil.setColor(Activity activity, int color)
Set the status bar to be semi-transparent 2. StatusBarUtil.setTranslucent(Activity activity, int statusBarAlpha) Set the status bar to be fully transparent - StatusBarUtil.setTransparent(Activity activity)
3. Set the status bar color for the interface containing DrawerLayout (you can also set it to semi-transparent or fully transparent)- StatusBarUtil.setColorForDrawerLayout(Activity activity, DrawerLayout drawerLayout, int color)
4. Set the status bar to be transparent for the interface that uses ImageView as the header- StatusBarUtil.setTranslucentForImageView(Activity activity, int statusBarAlpha, View needOffsetView)
5. Use in Fragment 6. By passing in the statusBarAlpha parameter, you can change the transparency value of the status bar. The default value is 112. Summarize: I hope this summary of knowledge points can help those who have not used the immersive status bar. If you have used the immersive status bar, you can have a deeper understanding of the principles of each version. |