美文网首页Android使用场景
Android状态栏-字体颜色改变

Android状态栏-字体颜色改变

作者: mrFessible | 来源:发表于2018-01-13 09:49 被阅读207次

    识别MIUI和FLyme系统

    目前只看到了小米和魅族公开了各自的实现方法,支持底层Android4.4以上的版本。而Android官方在6.0版本才有了深色状态栏字体API。所以Android4.4以上系统版本可以修改状态栏颜色,但是只有小米的MIUI、魅族的Flyme和Android6.0以上系统可以把状态栏文字和图标换成深色。

    我们首先要了解如何识别手机系统。
    这篇文章告诉我们如何判断手机系统

    整理出判断MIUI,FLyme系统的方法为

    public class OSUtils {
        public static final String ROM_MIUI = "MIUI";
        public static final String ROM_FLYME = "FLYME";
        private static final String KEY_VERSION_MIUI = "ro.miui.ui.version.name";
    
        private static String sName;
        private static String sVersion;
    
        public static boolean isMiui() {
            return check(ROM_MIUI);
        }
    
        public static boolean isFlyme() {
            return check(ROM_FLYME);
        }
    
        public static boolean check(String rom) {
            if (sName != null) {
                return sName.equals(rom);
            }
            if (!TextUtils.isEmpty(sVersion = getProp(KEY_VERSION_MIUI))) {
                sName = ROM_MIUI;
            } else {
                sVersion = Build.DISPLAY;
                if (sVersion.toUpperCase().contains(ROM_FLYME)) {
                    sName = ROM_FLYME;
                } else {
                    sVersion = Build.UNKNOWN;
                    sName = Build.MANUFACTURER.toUpperCase();
                }
            }
            return sName.equals(rom);
        }
    
        public static String getProp(String name) {
            String line = null;
            BufferedReader input = null;
            try {
                Process p = Runtime.getRuntime().exec("getprop " + name);
                input = new BufferedReader(new InputStreamReader(p.getInputStream()), 1024);
                line = input.readLine();
                input.close();
            } catch (IOException ex) {
                Log.e(TAG, "Unable to read prop " + name, ex);
                return null;
            } finally {
                if (input != null) {
                    try {
                        input.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            return line;
        }
    }
    

    设置状态栏透明

    综合上一篇文章,我们知道Android4.4.+ ,API 19 以上可以设置状态栏透明,且 4.4 和 5.0 方式不同

      /**
         * 设置状态栏透明
         */
        private void setTranslucentStatus() {
    
            // 5.0以上系统状态栏透明
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                Window window = getWindow();
                //清除透明状态栏
                window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
                window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                        | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
                //设置状态栏颜色必须添加
                window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
                window.setStatusBarColor(Color.TRANSPARENT);//设置透明
            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { //19
                getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            }
        }
    

    我们设置的主题为NoActionBar,除此之外没添加别的元素。
    这里我给button添加了颜色,可以看到button顶到了状态栏。


    image

    添加状态栏高度

      public int getStatusBarHeight() {
            int statusBarHeight = 0;
            int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
            if (resourceId > 0) {
                statusBarHeight = getResources().getDimensionPixelSize(resourceId);
            }
            return statusBarHeight;
        }
    

    魅族字体设置方式

     public void setFlymeUI(boolean dark) {
            try {
                Window window = getWindow();
                WindowManager.LayoutParams lp = window.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 (dark) {
                    value |= bit;
                } else {
                    value &= ~bit;
                }
                meizuFlags.setInt(lp, value);
                window.setAttributes(lp);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    

    小米字体设置方式

    public void setMiuiUI(boolean dark) {
            try {
                Window window = getWindow();
                Class clazz = getWindow().getClass();
                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);
                if (dark) {    //黑色字体
                    extraFlagField.invoke(window, darkModeFlag, darkModeFlag);
                } else {       
                    extraFlagField.invoke(window, 0, darkModeFlag);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    

    Android 6.0 以上设置方式

     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                        getWindow().getDecorView().setSystemUiVisibility(
                                View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                                        | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
    
                    }
    

    实现方式

    这里介绍实现方式的一种,通过自定义基类的Activity,让所有要实现的Activity继承它。

    我们的基类布局设置的方式为:状态栏+内容实现布局。
    因此在实现过程中我们要将子类布局添加到我们的内容实现布局中,还要将状态栏设置为透明。

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
        <View
            android:id="@+id/view_status_bar_place"
            android:layout_width="match_parent"
            android:layout_height="25dp"/>
    
        <FrameLayout
            android:id="@+id/frame_layout_content_place"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    </LinearLayout>
    

    总的实现方法为,下面是全部代码(要耐心看)

    import android.graphics.Color;
    import android.os.Build;
    import android.os.Bundle;
    import android.support.annotation.LayoutRes;
    import android.support.annotation.Nullable;
    import android.support.v7.app.AppCompatActivity;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.view.Window;
    import android.view.WindowManager;
    import android.widget.FrameLayout;
    
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    
    /**
     * Created by rhm on 2018/1/12.
     */
    
    public class CompactActivity extends AppCompatActivity {
        private FrameLayout mFrameLayoutContent;
        private View mViewStatusBarPlace;
        private final static int MIUI = 0;
        private final static int FLYME = 1;
        private final static int COMMON = 2;
    
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            super.setContentView(R.layout.activity_status_bar);
            mViewStatusBarPlace = findViewById(R.id.view_status_bar_place);
            mFrameLayoutContent = (FrameLayout) findViewById(R.id.frame_layout_content_place);
    
            ViewGroup.LayoutParams params = mViewStatusBarPlace.getLayoutParams();
            params.height = getStatusBarHeight();
            mViewStatusBarPlace.setLayoutParams(params);
        }
    
    //将子类布局添加到FrameLayout中
        @Override
        public void setContentView(@LayoutRes int layoutResID) {
            View contentView = LayoutInflater.from(this).inflate(layoutResID, null);
            mFrameLayoutContent.addView(contentView);
        }
    
    
        /**
         * 设置沉浸式状态栏
         *
         * @param fontIconDark 状态栏字体和图标颜色是否为深色
         */
        protected void setImmersiveStatusBar(boolean fontIconDark) {
            setTranslucentStatus();
            if (fontIconDark) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    setStatusBarFontIconDark(COMMON);
                } else if (OSUtils.isMiui()) {
                    setStatusBarFontIconDark(MIUI);
                } else if (OSUtils.isFlyme()) {
                    setStatusBarFontIconDark(FLYME);
                } else {//其他情况下我们将状态栏设置为灰色,就不会看不见字体
                    setStatusBarPlaceColor(Color.LTGRAY);//灰色
                }
            }
        }
    
        /**
         * 设置文字颜色
         */
        public void setStatusBarFontIconDark(int type) {
            switch (type) {
                case MIUI:
                    setMiuiUI(true);
                    break;
                case COMMON:
                    setCommonUI();
                    break;
                case FLYME:
                    setFlymeUI(true);
                    break;
            }
        }
    
        public void setCommonUI() {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                getWindow().getDecorView().setSystemUiVisibility(
                        View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                                | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
    
            }
        }
    
        public void setFlymeUI(boolean dark) {
            try {
                Window window = getWindow();
                WindowManager.LayoutParams lp = window.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 (dark) {
                    value |= bit;
                } else {
                    value &= ~bit;
                }
                meizuFlags.setInt(lp, value);
                window.setAttributes(lp);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        public void setMiuiUI(boolean dark) {
            try {
                Window window = getWindow();
                Class clazz = getWindow().getClass();
                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);
                if (dark) {    //状态栏亮色且黑色字体
                    extraFlagField.invoke(window, darkModeFlag, darkModeFlag);
                } else {
                    extraFlagField.invoke(window, 0, darkModeFlag);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        public void setStatusBarPlaceColor(int statusColor) {
            if (mViewStatusBarPlace != null) {
                mViewStatusBarPlace.setBackgroundColor(statusColor);
            }
        }
    
        /**
         * 设置状态栏透明
         */
        private void setTranslucentStatus() {
    
            // 5.0以上系统状态栏透明
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                Window window = getWindow();
                //清除透明状态栏
                window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
                window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                        | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
                //设置状态栏颜色必须添加
                window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
                window.setStatusBarColor(Color.TRANSPARENT);//设置透明
            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { //19
                getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            }
        }
    
        //设置状态栏高度
        public int getStatusBarHeight() {
            int statusBarHeight = 0;
            int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
            if (resourceId > 0) {
                statusBarHeight = getResources().getDimensionPixelSize(resourceId);
            }
            return statusBarHeight;
        }
    }
    
    

    状态栏默认为主题颜色。可以根据需要设置状态栏的颜色,字体是否显示为黑色。
    实现代码为:

    public class MainActivity extends CompactActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            setImmersiveStatusBar(true);
            }
            }
    
    image

    下一篇,我会介绍另一种实现方式。

    参考文章
    https://www.jianshu.com/p/a44c119d6ef7
    http://yifeng.studio/2017/02/19/android-statusbar/

    相关文章

      网友评论

        本文标题:Android状态栏-字体颜色改变

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