Android狀態欄顏色怎麼修改?

Android狀態欄顏色怎麼修改?默認情況下,狀態欄的顏色是黑色的。同時狀態欄顏色也可以半透明或是指定任意一種顏色。實現圖分別如下

黑色:

自主設定顏色

半透明

一:如何為狀態欄設置顏色?

在實現上主要分兩種,5.0以上機型、4.4-5.0版本機型。

4.4-5.0還沒有API可以直接修改狀態欄顏色,所以必須先將狀態欄設置為透明,然後在佈局中添加一個背景為期望色值的View來作為狀態欄的填充。

static void setStatusBarColor(Activity activity, int statusColor) {
    Window window = activity.getWindow();
    //設置Window為全透明
    window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

    ViewGroup mContentView = (ViewGroup) window.findViewById(Window.ID_ANDROID_CONTENT);
    //獲取父佈局
    View mContentChild = mContentView.getChildAt(0);
    //獲取狀態欄高度
    int statusBarHeight = getStatusBarHeight(activity);

    //如果已經存在假狀態欄則移除,防止重復添加
    removeFakeStatusBarViewIfExist(activity);
    //添加一個View來作為狀態欄的填充
    addFakeStatusBarView(activity, statusColor, statusBarHeight);
    //設置子控件到狀態欄的間距
    addMarginTopToContentChild(mContentChild, statusBarHeight);
    //不預留系統欄位置
    if (mContentChild != null) {
        ViewCompat.setFitsSystemWindows(mContentChild, false);
    }
    //如果在Activity中使用瞭ActionBar則需要再將佈局與狀態欄的高度跳高一個ActionBar的高度,否則內容會被ActionBar遮擋
    int action_bar_id = activity.getResources().getIdentifier("action_bar", "id", activity.getPackageName());
    View view = activity.findViewById(action_bar_id);
    if (view != null) {
       TypedValue typedValue = new TypedValue();
        if (activity.getTheme().resolveAttribute(R.attr.actionBarSize, typedValue, true)) {
            int actionBarHeight = TypedValue.complexToDimensionPixelSize(typedValue.data, activity.getResources().getDisplayMetrics());
            setContentTopPadding(activity, actionBarHeight);
        }
    }
}
private static void removeFakeStatusBarViewIfExist(Activity activity) {
    Window window = activity.getWindow();
    ViewGroup mDecorView = (ViewGroup) window.getDecorView();

    View fakeView = mDecorView.findViewWithTag(TAG_FAKE_STATUS_BAR_VIEW);
    if (fakeView != null) {
        mDecorView.removeView(fakeView);
    }
}

private static View addFakeStatusBarView(Activity activity, int statusBarColor, int statusBarHeight) {
    Window window = activity.getWindow();
    ViewGroup mDecorView = (ViewGroup) window.getDecorView();

    View mStatusBarView = new View(activity);
    FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight);
    layoutParams.gravity = Gravity.TOP;
    mStatusBarView.setLayoutParams(layoutParams);
    mStatusBarView.setBackgroundColor(statusBarColor);
    mStatusBarView.setTag(TAG_FAKE_STATUS_BAR_VIEW);

    mDecorView.addView(mStatusBarView);
    return mStatusBarView;
}

private static void addMarginTopToContentChild(View mContentChild, int statusBarHeight) {
    if (mContentChild == null) {
        return;
    }
    if (!TAG_MARGIN_ADDED.equals(mContentChild.getTag())) {
        FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mContentChild.getLayoutParams();
        lp.topMargin += statusBarHeight;
        mContentChild.setLayoutParams(lp);
        mContentChild.setTag(TAG_MARGIN_ADDED);
    }
}

static void setContentTopPadding(Activity activity, int padding) {
     ViewGroup mContentView = (ViewGroup) activity.getWindow().findViewById(Window.ID_ANDROID_CONTENT);
     mContentView.setPadding(0, padding, 0, 0);
}

在5.0以上機型,Google提供瞭方法用於設置顏色,所以實現方法並不相同

static void setStatusBarColor(Activity activity, int statusColor) {
    Window window = activity.getWindow();
    //取消狀態欄透明
    window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
    //添加Flag把狀態欄設為可繪制模式
    window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
    //設置狀態欄顏色
    window.setStatusBarColor(statusColor);
    //設置系統狀態欄處於可見狀態
    window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
    //讓view不根據系統窗口來調整自己的佈局
    ViewGroup mContentView = (ViewGroup) window.findViewById(Window.ID_ANDROID_CONTENT);
    View mChildView = mContentView.getChildAt(0);
    if (mChildView != null) {
        ViewCompat.setFitsSystemWindows(mChildView, false);
        ViewCompat.requestApplyInsets(mChildView);
    }
}

二:開源SystemTintBarManager,可以提供統一的4.4以上機型的狀態欄顏色設置。原理與上面介紹的相似。

/**
 * Class to manage status and navigation bar tint effects when using KitKat
 * translucent system UI modes.
 */
public class SystemBarTintManager {

    /**
     * The default system bar tint color value.
     */
    public static final int DEFAULT_TINT_COLOR = 0x99000000;
    private static String sNavBarOverride;

    static {
        // Android allows a system property to override the presence of the navigation bar.
        // Used by the emulator.
        // See https://github.com/android/platform_frameworks_base/blob/master/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java#L1076
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            try {
                Class c = Class.forName("android.os.SystemProperties");
                Method m = c.getDeclaredMethod("get", String.class);
                m.setAccessible(true);
                sNavBarOverride = (String) m.invoke(null, "qemu.hw.mainkeys");
            } catch (Throwable e) {
                sNavBarOverride = null;
            }
        }
    }

    private final SystemBarConfig mConfig;
    private boolean mStatusBarAvailable;
    private boolean mNavBarAvailable;
    private boolean mNavBarTintEnabled;
    private View mStatusBarTintView;
    private View mNavBarTintView;

    /**
     * Constructor. Call this in the host activity onCreate method after its
     * content view has been set. You should always create new instances when
     * the host activity is recreated.
     *
     * @param activity The host activity.
     */
    @TargetApi(19)
    public SystemBarTintManager(Activity activity) {

        Window win = activity.getWindow();
        ViewGroup decorViewGroup = (ViewGroup) win.getDecorView();

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            // check theme attrs
            int[] attrs = {android.R.attr.windowTranslucentStatus,
                    android.R.attr.windowTranslucentNavigation};
            TypedArray a = activity.obtainStyledAttributes(attrs);
            try {
                mStatusBarAvailable = a.getBoolean(0, false);
                mNavBarAvailable = a.getBoolean(1, false);
            } finally {
                a.recycle();
            }

            // check window flags
            WindowManager.LayoutParams winParams = win.getAttributes();
            int bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
            if ((winParams.flags & bits) != 0) {
                mStatusBarAvailable = true;
            }
            bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
            if ((winParams.flags & bits) != 0) {
                mNavBarAvailable = true;
            }
        }

        mConfig = new SystemBarConfig(activity, mStatusBarAvailable, mNavBarAvailable);
        // device might not have virtual navigation keys
        if (!mConfig.hasNavigtionBar()) {
            mNavBarAvailable = false;
        }

        if (mStatusBarAvailable) {
            setupStatusBarView(activity, decorViewGroup);
        }
        if (mNavBarAvailable) {
            setupNavBarView(activity, decorViewGroup);
        }

    }

    @TargetApi(19)
    public SystemBarTintManager(Activity activity, ViewGroup decorViewGroup) {

        Window win = activity.getWindow();

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            // check theme attrs
            int[] attrs = {android.R.attr.windowTranslucentStatus,
                    android.R.attr.windowTranslucentNavigation};
            TypedArray a = activity.obtainStyledAttributes(attrs);
            try {
                mStatusBarAvailable = a.getBoolean(0, false);
                mNavBarAvailable = a.getBoolean(1, false);
            } finally {
                a.recycle();
            }

            // check window flags
            WindowManager.LayoutParams winParams = win.getAttributes();
            int bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
            if ((winParams.flags & bits) != 0) {
                mStatusBarAvailable = true;
            }
            bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
            if ((winParams.flags & bits) != 0) {
                mNavBarAvailable = true;
            }

        }

        if (mStatusBarAvailable && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            win.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            win.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
            win.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            win.setStatusBarColor(Color.TRANSPARENT);
        }

        mConfig = new SystemBarConfig(activity, mStatusBarAvailable, mNavBarAvailable);

        if (decorViewGroup == null) {
            return;
        }

        // device might not have virtual navigation keys
        if (!mConfig.hasNavigtionBar()) {
            mNavBarAvailable = false;
        }

        if (mStatusBarAvailable) {
            setupStatusBarView(activity, decorViewGroup);
        }
        if (mNavBarAvailable) {
            setupNavBarView(activity, decorViewGroup);
        }

    }


    /**
     * Enable tinting of the system status bar.
     * 

* If the platform is running Jelly Bean or earlier, or translucent system * UI modes have not been enabled in either the theme or via window flags, * then this method does nothing. * * @param enabled True to enable tinting, false to disable it (default). */ public void setStatusBarTintEnabled(boolean enabled) { boolean mStatusBarTintEnabled = enabled; if (mStatusBarAvailable && mStatusBarTintView != null) { mStatusBarTintView.setVisibility(enabled ? View.VISIBLE : View.GONE); } } /** * Enable tinting of the system navigation bar. *

* If the platform does not have soft navigation keys, is running Jelly Bean * or earlier, or translucent system UI modes have not been enabled in either * the theme or via window flags, then this method does nothing. * * @param enabled True to enable tinting, false to disable it (default). */ // public void setNavigationBarTintEnabled(boolean enabled) { // mNavBarTintEnabled = enabled; // if (mNavBarAvailable) { // mNavBarTintView.setVisibility(enabled ? View.VISIBLE : View.GONE); // } // } /** * Apply the specified color tint to all system UI bars. * * @param color The color of the background tint. */ public void setTintColor(int color) { setStatusBarTintColor(color); setNavigationBarTintColor(color); } /** * Apply the specified drawable or color resource to all system UI bars. * * @param res The identifier of the resource. */ public void setTintResource(int res) { setStatusBarTintResource(res); setNavigationBarTintResource(res); } /** * Apply the specified drawable to all system UI bars. * * @param drawable The drawable to use as the background, or null to remove it. */ // public void setTintDrawable(Drawable drawable) { // setStatusBarTintDrawable(drawable); // setNavigationBarTintDrawable(drawable); // } /** * Apply the specified alpha to all system UI bars. * * @param alpha The alpha to use */ // public void setTintAlpha(float alpha) { // setStatusBarAlpha(alpha); // setNavigationBarAlpha(alpha); // } /** * Apply the specified color tint to the system status bar. * * @param color The color of the background tint. */ public void setStatusBarTintColor(int color) { if (mStatusBarAvailable) { mStatusBarTintView.setBackgroundColor(color); } } /** * Apply the specified drawable or color resource to the system status bar. * * @param res The identifier of the resource. */ public void setStatusBarTintResource(int res) { if (mStatusBarAvailable) { mStatusBarTintView.setBackgroundResource(res); } } /** * Apply the specified drawable to the system status bar. *

* The drawable to use as the background, or null to remove it. */ @SuppressWarnings("deprecation") // public void setStatusBarTintDrawable(Drawable drawable) { // if (mStatusBarAvailable) { // mStatusBarTintView.setBackgroundDrawable(drawable); // } // } /** * Apply the specified alpha to the system status bar. * * @param alpha The alpha to use */ @TargetApi(11) // public void setStatusBarAlpha(float alpha) { // if (mStatusBarAvailable && Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { // mStatusBarTintView.setAlpha(alpha); // } // } /** * Apply the specified color tint to the system navigation bar. * * @param color The color of the background tint. */ public void setNavigationBarTintColor(int color) { if (mNavBarAvailable) { mNavBarTintView.setBackgroundColor(color); } } /** * Apply the specified drawable or color resource to the system navigation bar. * * @param res The identifier of the resource. */ public void setNavigationBarTintResource(int res) { if (mNavBarAvailable) { mNavBarTintView.setBackgroundResource(res); } } /** * Apply the specified drawable to the system navigation bar. *

* drawable The drawable to use as the background, or null to remove it. */ @SuppressWarnings("deprecation") // public void setNavigationBarTintDrawable(Drawable drawable) { // if (mNavBarAvailable) { // mNavBarTintView.setBackgroundDrawable(drawable); // } // } /** * Apply the specified alpha to the system navigation bar. * * @param alpha The alpha to use */ @TargetApi(11) // public void setNavigationBarAlpha(float alpha) { // if (mNavBarAvailable && Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { // mNavBarTintView.setAlpha(alpha); // } // } /** * Get the system bar configuration. * * @return The system bar configuration for the current device configuration. */ public SystemBarConfig getConfig() { return mConfig; } /** * Is tinting enabled for the system status bar? * * @return True if enabled, False otherwise. */ // public boolean isStatusBarTintEnabled() { // return mStatusBarTintEnabled; // } /** * Is tinting enabled for the system navigation bar? * * @return True if enabled, False otherwise. */ // public boolean isNavBarTintEnabled() { // return mNavBarTintEnabled; // } private void setupStatusBarView(Context context, ViewGroup decorViewGroup) { mStatusBarTintView = new View(context); LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, mConfig.getStatusBarHeight()); params.gravity = Gravity.TOP; if (mNavBarAvailable && !mConfig.isNavigationAtBottom()) { params.rightMargin = mConfig.getNavigationBarWidth(); } mStatusBarTintView.setLayoutParams(params); mStatusBarTintView.setBackgroundColor(DEFAULT_TINT_COLOR); mStatusBarTintView.setVisibility(View.GONE); decorViewGroup.addView(mStatusBarTintView); } private void setupNavBarView(Context context, ViewGroup decorViewGroup) { mNavBarTintView = new View(context); LayoutParams params; if (mConfig.isNavigationAtBottom()) { params = new LayoutParams(LayoutParams.MATCH_PARENT, mConfig.getNavigationBarHeight()); params.gravity = Gravity.BOTTOM; } else { params = new LayoutParams(mConfig.getNavigationBarWidth(), LayoutParams.MATCH_PARENT); params.gravity = Gravity.RIGHT; } mNavBarTintView.setLayoutParams(params); mNavBarTintView.setBackgroundColor(DEFAULT_TINT_COLOR); mNavBarTintView.setVisibility(View.GONE); decorViewGroup.addView(mNavBarTintView); } /** * Class which describes system bar sizing and other characteristics for the current * device configuration. */ public static class SystemBarConfig { private static final String STATUS_BAR_HEIGHT_RES_NAME = "status_bar_height"; private static final String NAV_BAR_HEIGHT_RES_NAME = "navigation_bar_height"; private static final String NAV_BAR_HEIGHT_LANDSCAPE_RES_NAME = "navigation_bar_height_landscape"; private static final String NAV_BAR_WIDTH_RES_NAME = "navigation_bar_width"; private static final String SHOW_NAV_BAR_RES_NAME = "config_showNavigationBar"; private final boolean mTranslucentStatusBar; private final boolean mTranslucentNavBar; private final int mStatusBarHeight; private final int mActionBarHeight; private final boolean mHasNavigationBar; private final int mNavigationBarHeight; private final int mNavigationBarWidth; private final boolean mInPortrait; private final float mSmallestWidthDp; private SystemBarConfig(Activity activity, boolean translucentStatusBar, boolean traslucentNavBar) { Resources res = activity.getResources(); mInPortrait = (res.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT); mSmallestWidthDp = getSmallestWidthDp(activity); mStatusBarHeight = getInternalDimensionSize(res, STATUS_BAR_HEIGHT_RES_NAME); mActionBarHeight = getActionBarHeight(activity); mNavigationBarHeight = getNavigationBarHeight(activity); mNavigationBarWidth = getNavigationBarWidth(activity); mHasNavigationBar = (mNavigationBarHeight > 0); mTranslucentStatusBar = translucentStatusBar; mTranslucentNavBar = traslucentNavBar; } @TargetApi(14) private int getActionBarHeight(Context context) { int result = 0; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { TypedValue tv = new TypedValue(); context.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true); result = TypedValue.complexToDimensionPixelSize(tv.data, context.getResources().getDisplayMetrics()); } return result; } @TargetApi(14) private int getNavigationBarHeight(Context context) { Resources res = context.getResources(); int result = 0; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { if (hasNavBar(context)) { String key; if (mInPortrait) { key = NAV_BAR_HEIGHT_RES_NAME; } else { key = NAV_BAR_HEIGHT_LANDSCAPE_RES_NAME; } return getInternalDimensionSize(res, key); } } return result; } @TargetApi(14) private int getNavigationBarWidth(Context context) { Resources res = context.getResources(); int result = 0; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { if (hasNavBar(context)) { return getInternalDimensionSize(res, NAV_BAR_WIDTH_RES_NAME); } } return result; } @TargetApi(14) private boolean hasNavBar(Context context) { Resources res = context.getResources(); int resourceId = res.getIdentifier(SHOW_NAV_BAR_RES_NAME, "bool", "android"); if (resourceId != 0) { boolean hasNav = res.getBoolean(resourceId); // check override flag (see static block) if ("1".equals(sNavBarOverride)) { hasNav = false; } else if ("0".equals(sNavBarOverride)) { hasNav = true; } return hasNav; } else { // fallback return !ViewConfiguration.get(context).hasPermanentMenuKey(); } } private int getInternalDimensionSize(Resources res, String key) { int result = 0; int resourceId = res.getIdentifier(key, "dimen", "android"); if (resourceId > 0) { result = res.getDimensionPixelSize(resourceId); } return result; } @SuppressLint("NewApi") private float getSmallestWidthDp(Activity activity) { DisplayMetrics metrics = new DisplayMetrics(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { activity.getWindowManager().getDefaultDisplay().getRealMetrics(metrics); } else { // TODO this is not correct, but we don't really care pre-kitkat activity.getWindowManager().getDefaultDisplay().getMetrics(metrics); } float widthDp = metrics.widthPixels / metrics.density; float heightDp = metrics.heightPixels / metrics.density; return Math.min(widthDp, heightDp); } /** * Should a navigation bar appear at the bottom of the screen in the current * device configuration? A navigation bar may appear on the right side of * the screen in certain configurations. * * @return True if navigation should appear at the bottom of the screen, False otherwise. */ public boolean isNavigationAtBottom() { return (mSmallestWidthDp >= 600 || mInPortrait); } /** * Get the height of the system status bar. * * @return The height of the status bar (in pixels). */ public int getStatusBarHeight() { return mStatusBarHeight; } /** * Get the height of the action bar. * * @return The height of the action bar (in pixels). */ // public int getActionBarHeight() { // return mActionBarHeight; // } /** * Does this device have a system navigation bar? * * @return True if this device uses soft key navigation, False otherwise. */ public boolean hasNavigtionBar() { return mHasNavigationBar; } /** * Get the height of the system navigation bar. * * @return The height of the navigation bar (in pixels). If the device does not have * soft navigation keys, this will always return 0. */ public int getNavigationBarHeight() { return mNavigationBarHeight; } /** * Get the width of the system navigation bar when it is placed vertically on the screen. * * @return The width of the navigation bar (in pixels). If the device does not have * soft navigation keys, this will always return 0. */ public int getNavigationBarWidth() { return mNavigationBarWidth; } /** * Get the layout inset for any system UI that appears at the top of the screen. * * @param withActionBar True to include the height of the action bar, False otherwise. * @return The layout inset (in pixels). */ // public int getPixelInsetTop(boolean withActionBar) { // return (mTranslucentStatusBar ? mStatusBarHeight : 0) + (withActionBar ? mActionBarHeight : 0); // } /** * Get the layout inset for any system UI that appears at the bottom of the screen. * * @return The layout inset (in pixels). */ // public int getPixelInsetBottom() { // if (mTranslucentNavBar && isNavigationAtBottom()) { // return mNavigationBarHeight; // } else { // return 0; // } // } /** * Get the layout inset for any system UI that appears at the right of the screen. * * @return The layout inset (in pixels). */ // public int getPixelInsetRight() { // if (mTranslucentNavBar && !isNavigationAtBottom()) { // return mNavigationBarWidth; // } else { // return 0; // } // } } }

You May Also Like