美文网首页
StatusBarUtils实现沉浸式状态栏适配(第一种实现方式

StatusBarUtils实现沉浸式状态栏适配(第一种实现方式

作者: kksoCoud | 来源:发表于2018-11-15 19:57 被阅读145次

    现在沉浸式状态栏基本都成为产品主流样式了。但对于google官方提供的API对于状态栏的颜色设置是4.4版本才推出,所以我们也只能适配4.4及以上版本。但在4.4到5.0的时候只能通过设置状态栏透明,然后手动添加伪状态栏来进行修改状态栏颜色,对于5.0以上可以通过修改状态栏颜色即可。我们都知道,对于Activity我们通过setContentView方法添加的我们需要显示的xlm布局文件,其实是添加在decoview下面的content(其实是一个FrameLayout)里面。对于4.4~5.0之间的版本我们创建的伪状态栏就添加在decoview里面。先看看效果:


    statusbarutils01.png
    statusbarutils02.png

    看效果还行,并且以适配Drawlayout,Fragment对状态栏的修改。
    如果对于文字描叙不太清楚,可看看下面实现方式布局图:


    实现方式.png

    废话不多,开撸、开撸。

    public class StatusBarUtil {
    
        private static final int FAKE_STATUS_BAR_VIEW_ID = R.id.status_bar_util_fake_status_bar_view;
    
        public static void setStatusBarColorRes(Activity activity, @ColorRes int color){
            setStatusBarColor(activity, activity.getResources().getColor(color));
        }
    
        public static void setStatusBarColor(Activity activity, @ColorInt int color) {
            DrawerLayout drawerLayout = findDrawerLayout(activity);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
                activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
                if (drawerLayout == null) {
                    if (activity.getWindow().getStatusBarColor() == Color.TRANSPARENT) {
                        setContentLayoutParamsOfTop(activity, getStatusBarHeight(activity));
                    }
                    activity.getWindow().setStatusBarColor(color);
                } else {
                    activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
                    setDrawLayouterStatusBarColor(activity, drawerLayout, color);
                }
            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
                if (drawerLayout == null) {
                    ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
                    View fakeStatusBarView = decorView.findViewById(FAKE_STATUS_BAR_VIEW_ID);
                    if (fakeStatusBarView != null) {
                        if (fakeStatusBarView.getVisibility() == View.GONE) {
                            fakeStatusBarView.setVisibility(View.VISIBLE);
                        }
                        fakeStatusBarView.setBackgroundColor(color);
                    } else {
                        decorView.addView(createStatusBarView(activity, color));
                    }
                    setContentLayoutParamsOfTop(activity, getStatusBarHeight(activity));
                    setRootView(activity);
                } else {
                    setDrawLayouterStatusBarColor(activity, drawerLayout, color);
                }
            }
        }
    
        public static void setStatusBarTraslucent(Activity activity) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                setTransparentForWindow(activity);
                setContentLayoutParamsOfTop(activity, 0);
                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
                    clearPreviousSetting(activity);
                }
                DrawerLayout drawerLayout = findDrawerLayout(activity);
                if (drawerLayout != null) {
                    setDrawerLayoutProperty(drawerLayout);
                }
            }
        }
    
        private static void setDrawLayouterStatusBarColor(Activity activity, DrawerLayout drawerLayout, @ColorInt int color) {
            ViewGroup contentLayout = (ViewGroup) drawerLayout.getChildAt(0);
            View fakeStatusBarView = contentLayout.findViewById(FAKE_STATUS_BAR_VIEW_ID);
            if (fakeStatusBarView != null) {
                if (fakeStatusBarView.getVisibility() == View.GONE) {
                    fakeStatusBarView.setVisibility(View.VISIBLE);
                }
                fakeStatusBarView.setBackgroundColor(color);
            } else {
                drawerLayout.removeView(contentLayout);
                LinearLayout linearLayout = new LinearLayout(activity);
                linearLayout.setLayoutParams(new DrawerLayout.LayoutParams(DrawerLayout.LayoutParams.MATCH_PARENT, DrawerLayout.LayoutParams.MATCH_PARENT));
                linearLayout.setOrientation(LinearLayout.VERTICAL);
                linearLayout.addView(createStatusBarView(activity, color));
                linearLayout.addView(contentLayout);
                drawerLayout.addView(linearLayout, 0);
            }
            setDrawerLayoutProperty(drawerLayout);
        }
    
        private static void clearPreviousSetting(Activity activity) {
            ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
            View fakeStatusBarView = decorView.findViewById(FAKE_STATUS_BAR_VIEW_ID);
            if (fakeStatusBarView != null) {
                decorView.removeView(fakeStatusBarView);
            }
        }
    
        private static void setContentLayoutParamsOfTop(Activity activity, int top) {
            ViewGroup rootView = (ViewGroup) ((ViewGroup) activity.findViewById(android.R.id.content)).getChildAt(0);
            rootView.setPadding(0, top, 0, 0);
        }
    
        private static void setTransparentForWindow(Activity activity) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
                activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
                activity.getWindow()
                        .getDecorView()
                        .setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                activity.getWindow()
                        .setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            }
        }
    
        private static DrawerLayout findDrawerLayout(Activity activity) {
            ViewGroup rootView = (ViewGroup) ((ViewGroup) activity.getWindow().getDecorView().findViewById(android.R.id.content)).getChildAt(0);
            if (rootView instanceof DrawerLayout) {
                return (DrawerLayout) rootView;
            }
            return null;
        }
    
        private static void setDrawerLayoutProperty(DrawerLayout drawerLayout) {
            ViewGroup drawer = (ViewGroup) drawerLayout.getChildAt(1);
            drawerLayout.setFitsSystemWindows(false);
            drawer.setFitsSystemWindows(false);
        }
    
        @TargetApi(Build.VERSION_CODES.M)
        public static void setLightMode(Activity activity) {
            setMIUIStatusBarDarkIcon(activity, true);
            setMeizuStatusBarDarkIcon(activity, true);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
            }
        }
    
        @TargetApi(Build.VERSION_CODES.M)
        public static void setDarkMode(Activity activity) {
            setMIUIStatusBarDarkIcon(activity, false);
            setMeizuStatusBarDarkIcon(activity, false);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
            }
        }
    
        private static void setRootView(Activity activity) {
            ViewGroup parent = activity.findViewById(android.R.id.content);
            for (int i = 0; i < parent.getChildCount(); i++) {
                View childView = parent.getChildAt(i);
                if (childView instanceof ViewGroup) {
                    childView.setFitsSystemWindows(true);
                    ((ViewGroup) childView).setClipToPadding(true);
                }
            }
        }
    
        private static View createStatusBarView(Activity activity, @ColorInt int color) {
            View statusBarView = new View(activity);
            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity));
            statusBarView.setLayoutParams(params);
            statusBarView.setBackgroundColor(color);
            statusBarView.setId(FAKE_STATUS_BAR_VIEW_ID);
            return statusBarView;
        }
    
        private static int getStatusBarHeight(Context context) {
            // 获得状态栏高度
            int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
            return context.getResources().getDimensionPixelSize(resourceId);
        }
    
        /**
         * 修改 MIUI V6  以上状态栏颜色
         */
        private static void setMIUIStatusBarDarkIcon(@NonNull Activity activity, boolean darkIcon) {
            Class<? extends Window> clazz = activity.getWindow().getClass();
            try {
                Class<?> layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
                Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
                int darkModeFlag = field.getInt(layoutParams);
                Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
                extraFlagField.invoke(activity.getWindow(), darkIcon ? darkModeFlag : 0, darkModeFlag);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 修改魅族状态栏字体颜色 Flyme 4.0
         */
        private static void setMeizuStatusBarDarkIcon(@NonNull Activity activity, boolean darkIcon) {
            try {
                WindowManager.LayoutParams lp = activity.getWindow().getAttributes();
                Field darkFlag = WindowManager.LayoutParams.class.getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON");
                Field meizuFlags = WindowManager.LayoutParams.class.getDeclaredField("meizuFlags");
                darkFlag.setAccessible(true);
                meizuFlags.setAccessible(true);
                int bit = darkFlag.getInt(null);
                int value = meizuFlags.getInt(lp);
                if (darkIcon) {
                    value |= bit;
                } else {
                    value &= ~bit;
                }
                meizuFlags.setInt(lp, value);
                activity.getWindow().setAttributes(lp);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    

    为了在Fragment切换时修改同一Activity的状态栏,所以我们得给伪状态栏设置id(及在values目录下新建一资源文件ids)

    <item name="status_bar_util_fake_status_bar_view" type="id" />
    

    相关文章

      网友评论

          本文标题:StatusBarUtils实现沉浸式状态栏适配(第一种实现方式

          本文链接:https://www.haomeiwen.com/subject/pwkufqtx.html