android获取状态栏高度

公司项目中使用了popWindow,并且需求指明了popWindow必须是和Activity类似的全屏模式,并且从页面底部弹出!

当popWindow所有设计完毕后,从底部弹出popWindow,发现设置在popWindow的上的titlebar一部分被压入状态栏的底部了,也就是说全屏是全屏了,但是超过了应有的部分!

解决方案:

为了达到良好的兼容性,我们可以如下变现代码

 
/**

 * 用于获取状态栏的高度。

 * 

 * @return 返回状态栏高度的像素值。

 */

private int getStatusBarHeight() {

        int statusBarHeight = 0;

        try {

            Class<?> c = Class.forName("com.android.internal.R$dimen");

            Object o = c.newInstance();

            Field field = c.getField("status_bar_height");

            int x = (Integer) field.get(o);

            statusBarHeight = getResources().getDimensionPixelSize(x);

        } catch (Exception e) {

            e.printStackTrace();

            Rect frame = new Rect();

            getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);

            statusBarHeight = frame.top;

        }

        return statusBarHeight;

}

还可以使用Resource对象获取(推荐这种方式)

    private int getStatusBarHeight() {

            int result = 0;

            int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");

            if (resourceId > 0) {

                result = res.getDimensionPixelSize(resourceId);

            }

            return result;

        }

-----------------------------------2015-01-29 更新--------------------------------------

公司有测试人员发现,FlymeOS4.x/Android4.4.4出现 了问题,让人一头雾水,因此,这里把问题再次改正一下,目前Android4.4.4的系统不多,只检测到魅族的FlymeOS4.x有问题,所以对FlymeOS着重处理一下。

手写判断是否是Flyme OsS 4.x.x

 private boolean isFlymeOs4x()

{

    String sysVersion = android.os.Build.VERSION.RELEASE;

    if("4.4.4".equals(sysVersion))

    {

            String sysIncrement = android.os.Build.VERSION.INCREMENTAL;

            String displayId = android.os.Build.DISPLAY;

            if(!TextUtils.isEmpty(sysIncrement))

            {

                return sysIncrement.contains("Flyme_OS_4");

            }

            else 

            {

                return displayId.contains("Flyme OS 4");

            }

        }

        return false;

}

然后PopWindow改为

int statusBarHeight = getStatusBarHeight();

if(isFlymeOs4x())

{

    searchFlightListWindow.setHeight(screenMetrics.heightPixels-statusBarHeight*2);

    //至于这里为什么乘以2,我只能说,除了鬼鬼们,只有魅族自己知道,我是发现获得的StatusBarHeight偏小,所以乘以2,实践检验是正确的,但也很无语

    searchFlightListWindow.showAtLocation(findViewById(R.id.main), Gravity.BOTTOM, 0, 0);

}else{

    searchFlightListWindow.setHeight(screenMetrics.heightPixels-statusBarHeight);

    searchFlightListWindow.showAtLocation(findViewById(R.id.main), Gravity.BOTTOM, 0, 0);

}      

----------------------------

View contentView = getWindow().getDecorView().findViewById(android.R.id.content);

View contentView = getWindow().getDecorView().getChildAt(0);

View titleView = findViewById(Window.ID_ANDROID_CONTENT);

-------------------------2015-05-05更新,沉浸式状态栏---------------------------------

 public class SystemBarTintManager {

    /**

     * The default system bar tint color value.

     */

    public static final int DEFAULT_TINT_COLOR = 0x99000000;

 

    private final SystemBarConfig mConfig;

    private boolean mStatusBarAvailable;

    private boolean mNavBarAvailable;

    private boolean mStatusBarTintEnabled;

    private boolean mNavBarTintEnabled;

    private View mStatusBarTintView;

    private View mNavBarTintView;

    private static boolean sIsMiuiV6;

    private static String sNavBarOverride = null;

 

    static {

        Method methodGetter = null;

        try {

            Class<?> sysClass = Class.forName("android.os.SystemProperties");

            methodGetter = sysClass.getDeclaredMethod("get", String.class);

            sIsMiuiV6 = "V6".equals((String) methodGetter.invoke(sysClass, "ro.miui.ui.version.name"));

        } catch (Exception e) {

            e.printStackTrace();

        }finally{

            if(methodGetter!=null)

            {

                try {

                    sNavBarOverride = (String) methodGetter.invoke(null, "qemu.hw.mainkeys");

                } catch (Exception e) {

                    e.printStackTrace();

                    sNavBarOverride = null;

                }

            }

        }

    }

    /**

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

        }

 

    }

 

    /**

     * Enable tinting of the system status bar.

     *

     * @param enabled True to enable tinting, false to disable it (default).

     */

    public void setStatusBarTintEnabled(boolean enabled) {

        mStatusBarTintEnabled = enabled;

        if (mStatusBarAvailable) {

            mStatusBarTintView.setVisibility(enabled ? View.VISIBLE : View.GONE);

        }

    }

 

    /**

     * set status bar darkmode

     * @param darkmode

     * @param activity

     */

    public void setStatusBarDarkMode(boolean darkmode, Activity activity) {

        if (sIsMiuiV6) {

            Class<? extends Window> clazz = activity.getWindow().getClass();

            try {

            int darkModeFlag = 0;

            Class<?> layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");

            Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");

            darkModeFlag = field.getInt(layoutParams);

            Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);

            extraFlagField.invoke(activity.getWindow(), darkmode ? darkModeFlag : 0, darkModeFlag);

            } catch (Exception e) {

                e.printStackTrace();

            }

        }

    }

 

    /**

     * Enable tinting of the system navigation bar.

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

     *

     * @param drawable 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.

     *

     * @param 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 = context.getResources().getDimensionPixelSize(tv.resourceId);

            }

            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;

        }

 

        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;

            }

        }

         

        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 !hasPermanentMenuKey(context);

            }

        }

         

        private boolean hasPermanentMenuKey(Context cxt) {

            try {

                WindowManager wm = (WindowManager) cxt.getSystemService(Context.WINDOW_SERVICE);

             

                ViewConfiguration config = ViewConfiguration.get(cxt);

                Field menuKeyField = ViewConfiguration.class

                        .getDeclaredField("sHasPermanentMenuKey");

                if (menuKeyField != null) {

                    menuKeyField.setAccessible(true);

                    return menuKeyField.getBoolean(config);

                }

            } catch (Exception e) {

                e.printStackTrace();

            }

             

            return false;

        }

 

    }

 

}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Android小菜鸡

自定义广告图片轮播View——CarouselView

  因为一个广告机的需求,需要做一个广告轮播的效果,不需要什么特别的动画,正常的轮播就可以了。笔者看了网上很多文章,要么不好用,要么就是效果太多,太复杂,用不上...

1502
来自专栏项勇

笔记21 | 学习整理开源APP(BaseAnimation)程序源码“中的通讯录效果(二)

1357
来自专栏向治洪

高仿今日头条(1)

本片博客主要实现今日头条的主题框架。后面我会慢慢完善,欢迎大家持续关注 git下载地址:https://github.com/xiangzhihong/topN...

3657
来自专栏向治洪

Android侧滑删除另一种实现,SwipeListView补充

前不久在在做聊天删除功能的时候使用SwipeListView进行侧滑删除有一点小问题,因为SwipeListView嵌套在Fragment内的时候,会报一个转换...

1979
来自专栏懒人开发

鸿洋AutoLayout代码分析(四):剩下的类

也和前面的AutoXXXLayout类似, 都只是通过 关联和依赖 AutoLayoutHelper , Override对应的 onMeasure(in...

1162
来自专栏增长技术

App Intro相关

##How to use Add this to your build.gradle:

762
来自专栏编程之路

羊皮书APP(Android版)开发系列(十)Android开发常用工具类

1161
来自专栏蜉蝣禅修之道

android获取textview展开渲染后的高度

1774
来自专栏向治洪

Android侧滑删除另一种实现,SwipeListView补充

前不久在在做聊天删除功能的时候使用SwipeListView进行侧滑删除有一点小问题,因为SwipeListView嵌套在Fragment内的时候,会报一个转换...

3345
来自专栏向治洪

RecyclerView 实现横向滚动效果

我相信很久以前,大家在谈横向图片轮播是时候,优先会选择具有HorizontalScrollView效果和ViewPager来做,不过自从Google大会之后,系...

4026

扫码关注云+社区

领取腾讯云代金券