状态栏、导航栏、PopupWindow的使用

目录:
1、状态栏、标题栏、导航栏简介
2、PopupWindow的基本使用
image.png

1. 状态栏、标题栏、导航栏简介

绝对高度 = 高度 + 状态栏高度 + 导航栏高度
RealHeight = Height + StatusBarHeight + NavigationBarHeight

1.1 获取屏幕绝对高度:RealHeight

    public static int getScreenRealHeight(Context context) {
        WindowManager windowManager = (WindowManager) (context.getApplicationContext().getSystemService(Context.WINDOW_SERVICE));
        Display defaultDisplay = windowManager.getDefaultDisplay();
        Point point = new Point();
        defaultDisplay.getRealSize(point);
        return point.y;
    }

1.2 获取屏幕高度:Height

    /**
     * 方法一:
     */
    public static int getScreenHeight(Context context) {
        DisplayMetrics dm = context.getResources().getDisplayMetrics();
        return dm.heightPixels;
    }
    /**
     * 方法二:
     */
    public static int getScreenHeight(Context context) {
        WindowManager windowManager = (WindowManager) (context.getApplicationContext().getSystemService(Context.WINDOW_SERVICE));
        Display defaultDisplay = windowManager.getDefaultDisplay();
        Point point = new Point();
        defaultDisplay.getSize(point);
        return point.y;
    }

1.3 获取状态栏高度:StatusBarHeight

    /**
     * 利用反射获取状态栏高度
     */
    public static int getStatusBarHeight(Context context) {
        int result = 0;
        //获取状态栏高度的资源id
        int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            result = context.getResources().getDimensionPixelSize(resourceId);
        }
        return result;
    }

1.4 获取导航栏高度:NavigationbarHeight

    /**
     * 获取虚拟操作拦(home等)高度
     */
    public static int getNavigationBarHeight(Activity activity) {
        if (!isNavigationBarShow(activity))
            return 0;
        int height = 0;
        Resources resources = activity.getResources();
        //获取NavigationBar的高度
        int resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android");
        if (resourceId > 0)
            height = resources.getDimensionPixelSize(resourceId);
//        LogUtil.i("NavigationBar的高度:" + height);
        return height;
    }


    /**
     * 虚拟操作拦(home等)是否显示
     */
    public static boolean isNavigationBarShow(Activity activity) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            Display display = activity.getWindowManager().getDefaultDisplay();
            Point size = new Point();
            Point realSize = new Point();
            display.getSize(size);
            display.getRealSize(realSize);
            return realSize.y != size.y;
        } else {
            boolean menu = ViewConfiguration.get(activity).hasPermanentMenuKey();
            boolean back = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK);
            if (menu || back) {
                return false;
            } else {
                return true;
            }
        }
    }

2. PopupWindow的基本使用注意事项

  • 避免麻烦,将锚点设置为一条线,或一个点
场景一:无半透明背景,在锚点顶部弹出
无半透明背景,在锚点顶部弹出
public void showAsDropUp(View parent){
        int windowPos[] = calculatePopWindowPos(parent, fl_content);
        int xOff = 0;// 可以自己调整偏移
        windowPos[0] -= xOff;
        this.showAtLocation(parent, Gravity.TOP | Gravity.START,20, windowPos[1]);
    }

    /**
     * 计算出来的位置,y方向就在anchorView的上面和下面对齐显示,x方向就是与屏幕右边对齐显示
     * 如果anchorView的位置有变化,就可以适当自己额外加入偏移来修正
     * @param anchorView 呼出window的view
     * @param contentView  window的内容布局
     * @return window显示的左上角的xOff,yOff坐标
     */
    private static int[] calculatePopWindowPos(final View anchorView, final View contentView) {
        final int windowPos[] = new int[2];
        final int anchorLoc[] = new int[2];
        anchorView.getLocationOnScreen(anchorLoc);
        final int anchorHeight = anchorView.getHeight();
        // 获取屏幕的高宽
        final int screenHeight = ScreenUtils.getScreenHeight(anchorView.getContext());
        final int screenWidth = ScreenUtils.getScreenWidth(anchorView.getContext());
        contentView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
        // 计算contentView的高宽
        final int windowHeight = contentView.getMeasuredHeight();
        final int windowWidth = contentView.getMeasuredWidth();
        // 判断需要向上弹出还是向下弹出显示
        final boolean isNeedShowUp = (screenHeight - anchorLoc[1] - anchorHeight < windowHeight);
        if (isNeedShowUp) {
            windowPos[0] = screenWidth - windowWidth;
            windowPos[1] = anchorLoc[1] - windowHeight;
        } else {
            windowPos[0] = screenWidth - windowWidth;
            windowPos[1] = anchorLoc[1] + anchorHeight;
        }
        return windowPos;
    }
场景二:有半透明背景,在锚点底部弹出,背景占满余下屏幕

假设出现窗口没准确出现在锚点下方,或者半透明背景没占满余下屏幕的情况,看看高度取值是否准确。


有半透明背景,在锚点底部弹出,背景占满余下屏幕
  • 锚点下方显示窗口,且占满余下屏幕,背景半透明
@Override
    public void showAsDropDown(View anchor) {
        try {
            final int anchorLoc[] = new int[2];
            anchor.getLocationOnScreen(anchorLoc); 
            // shFull = sh + statusBar + navigationBar
            int shFull = StatusBar.getScreenRealHeight(mContext);// 2340
            int sh = StatusBar.getScreenHeight(mContext);// 2130
            int statusBar = StatusBar.getStatusBarHeight(mContext);//80
            int navigationBar = ScreenUtils.getNavigationBarHeight(mActivity);//130
            
            int h = shFull - anchorLoc[1]; // 取(真实高度 - 锚点y轴)
            setHeight(h); // 重新设置PopupWindow高度
            super.showAsDropDown(anchor);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

你可能感兴趣的:(状态栏、导航栏、PopupWindow的使用)