美文网首页
Android 状态栏的沉浸式实现

Android 状态栏的沉浸式实现

作者: 84ed7ae0e2ba | 来源:发表于2016-03-23 18:46 被阅读285次

    1 sdk>19

    2 思路,window的设置透明的,然后在decorView加上一个和状态栏的一样的高的view就可以了,颜色,设置颜色。

    3 解决了 从全屏幕到不是全屏幕的会反生页面会卡一下的效果,思路:在给contentview默认加一个padding的值大小等于状态栏的高度

    4 后来遇到了将一张图片设为状态栏背景色

    本地图片:借用
    publicclassSystemBarTintManager {

    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;

    }

    }

    }

    /**

    * The default system bar tint color value.

    */

    publicstaticfinalintDEFAULT_TINT_COLOR =0x99000000;

    privatestaticString sNavBarOverride;

    privatefinalSystemBarConfig mConfig;

    privatebooleanmStatusBarAvailable;

    privatebooleanmNavBarAvailable;

    privatebooleanmStatusBarTintEnabled;

    privatebooleanmNavBarTintEnabled;

    privateView mStatusBarTintView;

    privateView 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)

    publicSystemBarTintManager(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();

    intbits = 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 =newSystemBarConfig(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);

    }

    }

    /**

    * 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).

    */

    publicvoidsetStatusBarTintEnabled(booleanenabled) {

    mStatusBarTintEnabled = enabled;

    if(mStatusBarAvailable) {

    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).

    */

    publicvoidsetNavigationBarTintEnabled(booleanenabled) {

    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.

    */

    publicvoidsetTintColor(intcolor) {

    setStatusBarTintColor(color);

    setNavigationBarTintColor(color);

    }

    /**

    * Apply the specified drawable or color resource to all system UI bars.

    *

    * @param res The identifier of the resource.

    */

    publicvoidsetTintResource(intres) {

    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.

    */

    publicvoidsetTintDrawable(Drawable drawable) {

    setStatusBarTintDrawable(drawable);

    setNavigationBarTintDrawable(drawable);

    }

    /**

    * Apply the specified alpha to all system UI bars.

    *

    * @param alpha The alpha to use

    */

    publicvoidsetTintAlpha(floatalpha) {

    setStatusBarAlpha(alpha);

    setNavigationBarAlpha(alpha);

    }

    /**

    * Apply the specified color tint to the system status bar.

    *

    * @param color The color of the background tint.

    */

    publicvoidsetStatusBarTintColor(intcolor) {

    if(mStatusBarAvailable) {

    mStatusBarTintView.setBackgroundColor(color);

    }

    }

    /**

    * Apply the specified drawable or color resource to the system status bar.

    *

    * @param res The identifier of the resource.

    */

    publicvoidsetStatusBarTintResource(intres) {

    if(mStatusBarAvailable) {

    mStatusBarTintView.setBackgroundResource(res);

    }

    }

    /**

    * Apply the specified drawable to the system status bar.

    *

    * @param drawable The drawable to use as the background, or null to remove it.

    */

    @SuppressWarnings("deprecation")

    publicvoidsetStatusBarTintDrawable(Drawable drawable) {

    if(mStatusBarAvailable) {

    mStatusBarTintView.setBackgroundDrawable(drawable);

    }

    }

    /**

    * Apply the specified alpha to the system status bar.

    *

    * @param alpha The alpha to use

    */

    @TargetApi(11)

    publicvoidsetStatusBarAlpha(floatalpha) {

    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.

    */

    publicvoidsetNavigationBarTintColor(intcolor) {

    if(mNavBarAvailable) {

    mNavBarTintView.setBackgroundColor(color);

    }

    }

    /**

    * Apply the specified drawable or color resource to the system navigation bar.

    *

    * @param res The identifier of the resource.

    */

    publicvoidsetNavigationBarTintResource(intres) {

    if(mNavBarAvailable) {

    mNavBarTintView.setBackgroundResource(res);

    }

    }

    /**

    * Apply the specified drawable to the system navigation bar.

    *

    * @param drawable The drawable to use as the background, or null to remove it.

    */

    @SuppressWarnings("deprecation")

    publicvoidsetNavigationBarTintDrawable(Drawable drawable) {

    if(mNavBarAvailable) {

    mNavBarTintView.setBackgroundDrawable(drawable);

    }

    }

    /**

    * Apply the specified alpha to the system navigation bar.

    *

    * @param alpha The alpha to use

    */

    @TargetApi(11)

    publicvoidsetNavigationBarAlpha(floatalpha) {

    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.

    */

    publicSystemBarConfig getConfig() {

    returnmConfig;

    }

    /**

    * Is tinting enabled for the system status bar?

    *

    * @return True if enabled, False otherwise.

    */

    publicbooleanisStatusBarTintEnabled() {

    returnmStatusBarTintEnabled;

    }

    /**

    * Is tinting enabled for the system navigation bar?

    *

    * @return True if enabled, False otherwise.

    */

    publicbooleanisNavBarTintEnabled() {

    returnmNavBarTintEnabled;

    }

    privatevoidsetupStatusBarView(Context context, ViewGroup decorViewGroup) {

    mStatusBarTintView =newView(context);

    LayoutParams params =newLayoutParams(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);

    }

    privatevoidsetupNavBarView(Context context, ViewGroup decorViewGroup) {

    mNavBarTintView =newView(context);

    LayoutParams params;

    if(mConfig.isNavigationAtBottom()) {

    params =newLayoutParams(LayoutParams.MATCH_PARENT, mConfig.getNavigationBarHeight());

    params.gravity = Gravity.BOTTOM;

    }else{

    params =newLayoutParams(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.

    *

    */

    publicstaticclassSystemBarConfig {

    privatestaticfinalString STATUS_BAR_HEIGHT_RES_NAME ="status_bar_height";

    privatestaticfinalString NAV_BAR_HEIGHT_RES_NAME ="navigation_bar_height";

    privatestaticfinalString NAV_BAR_HEIGHT_LANDSCAPE_RES_NAME ="navigation_bar_height_landscape";

    privatestaticfinalString NAV_BAR_WIDTH_RES_NAME ="navigation_bar_width";

    privatestaticfinalString SHOW_NAV_BAR_RES_NAME ="config_showNavigationBar";

    privatefinalbooleanmTranslucentStatusBar;

    privatefinalbooleanmTranslucentNavBar;

    privatefinalintmStatusBarHeight;

    privatefinalintmActionBarHeight;

    privatefinalbooleanmHasNavigationBar;

    privatefinalintmNavigationBarHeight;

    privatefinalintmNavigationBarWidth;

    privatefinalbooleanmInPortrait;

    privatefinalfloatmSmallestWidthDp;

    privateSystemBarConfig(Activity activity,booleantranslucentStatusBar,booleantraslucentNavBar) {

    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)

    privateintgetActionBarHeight(Context context) {

    intresult =0;

    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {

    TypedValue tv =newTypedValue();

    context.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv,true);

    result = TypedValue.complexToDimensionPixelSize(tv.data, context.getResources().getDisplayMetrics());

    }

    returnresult;

    }

    @TargetApi(14)

    privateintgetNavigationBarHeight(Context context) {

    Resources res = context.getResources();

    intresult =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;

    }

    returngetInternalDimensionSize(res, key);

    }

    }

    returnresult;

    }

    @TargetApi(14)

    privateintgetNavigationBarWidth(Context context) {

    Resources res = context.getResources();

    intresult =0;

    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {

    if(hasNavBar(context)) {

    returngetInternalDimensionSize(res, NAV_BAR_WIDTH_RES_NAME);

    }

    }

    returnresult;

    }

    @TargetApi(14)

    privatebooleanhasNavBar(Context context) {

    Resources res = context.getResources();

    intresourceId = res.getIdentifier(SHOW_NAV_BAR_RES_NAME,"bool","android");

    if(resourceId !=0) {

    booleanhasNav = res.getBoolean(resourceId);

    // check override flag (see static block)

    if("1".equals(sNavBarOverride)) {

    hasNav =false;

    }elseif("0".equals(sNavBarOverride)) {

    hasNav =true;

    }

    returnhasNav;

    }else{// fallback

    return!ViewConfiguration.get(context).hasPermanentMenuKey();

    }

    }

    privateintgetInternalDimensionSize(Resources res, String key) {

    intresult =0;

    intresourceId = res.getIdentifier(key,"dimen","android");

    if(resourceId >0) {

    result = res.getDimensionPixelSize(resourceId);

    }

    returnresult;

    }

    @SuppressLint("NewApi")

    privatefloatgetSmallestWidthDp(Activity activity) {

    DisplayMetrics metrics =newDisplayMetrics();

    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);

    }

    floatwidthDp = metrics.widthPixels / metrics.density;

    floatheightDp = metrics.heightPixels / metrics.density;

    returnMath.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.

    */

    publicbooleanisNavigationAtBottom() {

    return(mSmallestWidthDp >=600|| mInPortrait);

    }

    /**

    * Get the height of the system status bar.

    *

    * @return The height of the status bar (in pixels).

    */

    publicintgetStatusBarHeight() {

    returnmStatusBarHeight;

    }

    /**

    * Get the height of the action bar.

    *

    * @return The height of the action bar (in pixels).

    */

    publicintgetActionBarHeight() {

    returnmActionBarHeight;

    }

    /**

    * Does this device have a system navigation bar?

    *

    * @return True if this device uses soft key navigation, False otherwise.

    */

    publicbooleanhasNavigtionBar() {

    returnmHasNavigationBar;

    }

    /**

    * 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.

    */

    publicintgetNavigationBarHeight() {

    returnmNavigationBarHeight;

    }

    /**

    * 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.

    */

    publicintgetNavigationBarWidth() {

    returnmNavigationBarWidth;

    }

    /**

    * 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).

    */

    publicintgetPixelInsetTop(booleanwithActionBar) {

    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).

    */

    publicintgetPixelInsetBottom() {

    if(mTranslucentNavBar && isNavigationAtBottom()) {

    returnmNavigationBarHeight;

    }else{

    return0;

    }

    }

    /**

    * Get the layout inset for any system UI that appears at the right of the screen.

    *

    * @return The layout inset (in pixels).

    */

    publicintgetPixelInsetRight() {

    if(mTranslucentNavBar && !isNavigationAtBottom()) {

    returnmNavigationBarWidth;

    }else{

    return0;

    }

    }

    }

    }

    相关文章

      网友评论

          本文标题:Android 状态栏的沉浸式实现

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