Android技术

PopUpWindow在Android7.0及以上位置和阴影显示

2018-08-01  本文已影响306人  阡陌昏晨

1、PopupWindow的位置显示问题

项目时发现Popupwindow在7.0及以上的设备上显示位置异常,6.0上及以下却没有问题:
解决方式:调用Popupwindow的showasdrop方法 代码如下

  /**
 * 适配7.0系统显示弹窗问题
  * @param window
 * @param parent
 * @param offsetY
  */
  public static voidadapterApiV24ForShowAsDropDown(PopupWindow window, View parent, int     offsetY) {

 if (null == window) {
      return;
  }

  if (null == parent) {

  return;

  }

  if(Build.VERSION.SDK_INT >= 24){

  Rect visibleFrame = new Rect();

  parent.getGlobalVisibleRect(visibleFrame);

 int height =parent.getResources().getDisplayMetrics().heightPixels - visibleFrame.bottom 
 +Math.abs(offsetY);

  window.setHeight(height);

 }

window.showAsDropDown(parent, 0, offsetY);

   }

代码难点解析
parent.getGlobalVisibleRect(visibleFrame);这里主要是获取传入的view 在屏幕上的位置
visibleFrame.bottom就是获取该view在屏幕的y的高度

Math.abs(offsetY) 这个是popupWindow显示的位置y轴的偏移量

int height = parent.getResources().getDisplayMetrics().heightPixels - visibleFrame.bottom + Math.abs(offsetY);这里是算出屏幕分辨率的高度-该view在屏幕上的高度+Y轴偏移量

window.setHeight(height);这里就是给popupWindow重新设置一下高度 一定要设置 否则就不起作用

window.showAsDropDown(parent, 0, offsetY);
这一句就很简单了 你懂得 不懂的就去百度一下showAsDropDown跟showAtLocation的区别

2、PopupWindow的阴影覆盖问题

android7.0以上的小米手机和华为手机下面状态栏隐藏的时候会出现阴影没有覆盖到最底部的情况(前提是popupWindow往下面弹出) 看图说话 小米全面屏出现的问题

device-2018-08-01-115629.png

解决办法 直接上代码

/**
 * 通过判断是否有导航栏 适配7.0以上系统显示弹窗问题
 * 主要是解决阴影没有遮住下面的TabHost的问题
 *
 * @param window
 * @param parent
 * @param offsetY
 */
public static void adapterApiV24ForShowAsDropDown(PopupWindow window, View parent, int   offsetY) {
if (null == window) {
    return;
}
if (null == parent) {
    return;
}
if (Build.VERSION.SDK_INT >= 24) {
    Rect visibleFrame = new Rect();
    parent.getGlobalVisibleRect(visibleFrame);
    int height;
    /**
     * 判断是否有导航栏
     */
    if (BarUtils.isShowNavBar(window.getContentView().getContext())) {
        height = parent.getResources().getDisplayMetrics().heightPixels - visibleFrame.bottom + Math.abs(offsetY);
    } else {
        /**
         * 获取物理真实高度 才能在android 7.0以上遮住下面的TabHost
         */
        height = WindowDispaly.getRealHeight() - visibleFrame.bottom + Math.abs(offsetY);
    }
    window.setHeight(height);
}
window.showAsDropDown(parent, 0, offsetY);
}

判断是否有导航栏的方法 BarUtils类 (该方法可以基本适配所有机型 判断是否显示了导航栏 后续有文章专门说明我的思路)

/**
 * 判断是否显示了导航栏
 * (说明这里的context 一定要是activity的context 否则类型转换失败)
 *
 * @param context
 * @return
 */
public static boolean isShowNavBar(Context context) {
if (null == context) {
    return false;
}
/**
 * 获取应用区域高度
 */
Rect outRect1 = new Rect();
try {
    ((Activity) context).getWindow().getDecorView().getWindowVisibleDisplayFrame(outRect1);
} catch (ClassCastException e) {
    e.printStackTrace();
    return false;
}
int activityHeight = outRect1.height();
/**
 * 获取状态栏高度
 */
int statuBarHeight = WindowDispaly.getStatusBarHeight();
/**
 * 屏幕物理高度 减去 状态栏高度
 */
int remainHeight = WindowDispaly.getRealHeight() - statuBarHeight;
/**
 * 剩余高度跟应用区域高度相等 说明导航栏没有显示 否则相反
 */
if (activityHeight == remainHeight) {
    return false;
} else {
    return true;
}

}

获取真实屏幕高度比如我的手机是小米6X 设置中显示 分辨率是2160X1080 2160就是真实屏幕高度(包括了状态栏高度) WindowDispaly类中的代码如下

/**
 * 获取真实屏幕高度
 *
 * @return
 */
public static int getRealHeight() {
if (null == wm) {
    wm = (WindowManager) BaseApplication.getContext().getSystemService(Context.WINDOW_SERVICE);
}
Point point = new Point();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
    wm.getDefaultDisplay().getRealSize(point);
} else {
    wm.getDefaultDisplay().getSize(point);
}
return point.y;
}

/**
 * 获取状态栏高度
 *
 * @return
 */
public static int getStatusBarHeight() {
    int result = 0;
    int resourceId = BaseApplication.getContext().getResources().getIdentifier("status_bar_height", "dimen", "android");
    if (resourceId > 0) {
        result = BaseApplication.getContext().getResources().getDimensionPixelSize(resourceId);
    }
    return result;
}

修改后运行效果如下图

device-2018-08-01-141758.png

3、PopupWindow的阴影没有覆盖状态栏的问题

目前测试机型也是小米6x 效果如下图

17.png

解决办法 增加一行代码就搞定

popupWindow.setClippingEnabled(false) 

原理我也没仔细研究了 给个我觉得还靠谱的博客文章
PopupWindow全屏显示

修改后的效果如下图

07.png

对PopupWindow的总结

1、对showAsDropDown跟showAtLocation方法需要熟悉以便控制PopupWindow显示的位置

2、状态栏和导航栏对PopupWindow的高度影响需要考虑

3、PopupWindow在android7.0以上有很多的适配bug(谷歌工程师的锅),所以看以后如果用到PopupWindow可以考虑用Activity替代

嘿嘿 第一次写简书文章排版不是很好看各位请见谅,如果遇到以上适配问题或者判断导航栏方法是否可见 有bug都希望各位留言 一起努力解决问题 ZFFQ(K5EV_FFXA711(G1_9K.gif
上一篇下一篇

猜你喜欢

热点阅读