PopupWindow定位问题

这篇博客主要讨论了PopupWindow在刘海屏设备上出现的定位问题。在某些设备上,由于刘海屏和全面屏功能的影响,PopupWindow无法正确显示。文章详细分析了问题所在,包括计算过程可能存在的错误,并提出了两种解决方案:使用paddingTop和固定控件高度。作者倾向于paddingBottom方案,但目前因兼容性问题采用paddingTop。计划进一步测试并在后续版本中优化。
摘要由CSDN通过智能技术生成

神马笔记录音功能采用PopupWindow作为容器实现录音编辑器功能,在适配刘海屏时出现了定位问题。

一、目标

在荣耀畅玩7上,显示一切正常,完美定位。
在这里插入图片描述

二、刘海屏问题

完全相同的代码,在红米6Pro上出现了问题。

只有在打开“隐藏屏幕刘海”和采用“经典导航键”时,相当于关闭了所谓“全面屏”功能后,界面显示是正常的。

隐藏屏幕刘海系统导航方式截图
关闭全面屏手势在这里插入图片描述
关闭经典导航键在这里插入图片描述
打开全面屏手势在这里插入图片描述
打开经典导航键在这里插入图片描述

三、问题分析

1. 实现思路

控件采用右下对齐方式,通过设置paddingBottom实现对齐到anchor。

2. 实现代码

int getPaddingBottom(View anchor) {

  int y;

  int bottom;
  View rootView = anchor.getRootView();

  // root view relative to display
  {
    DisplayMetrics dm = this.displayMetrics;
    Display d = context.getWindowManager().getDefaultDisplay();
    d.getMetrics(dm);
    //            d.getRealMetrics(dm); // must consider navigation bar
    int realHeight = dm.heightPixels;

    Rect visibleDisplayFrame = this.bounds;
    rootView.getWindowVisibleDisplayFrame(visibleDisplayFrame);

    y = realHeight - visibleDisplayFrame.bottom;
    bottom = visibleDisplayFrame.bottom;
  }

  // anchor relative to root
  if (rootView instanceof ViewGroup) {
    Rect anchorRect = this.bounds;
    anchorRect.set(0, 0, anchor.getWidth(), anchor.getHeight());

    ((ViewGroup)rootView).offsetDescendantRectToMyCoords(anchor, anchorRect);

    int offset = (bottom - anchorRect.bottom);
    y += offset;
  }

  return y;
}

3. 问题所在

paddingBottom的计算分成2步

  1. 计算根控件的paddingBottom
  2. 计算anchor与根控件的paddingBottom

2个步骤的计算都可能存在问题。

Display提供了2个接口,getMetricsgetRealMetrics,非全面屏必须使用getMetrics接口获取的才是去掉导航条的高度。

其次,anchor与根控件的paddingBottom的计算也可能存在问题。

虽然通过offsetDescendantRectToMyCoords计算出anchor相对于根控件的位置,但根控件的高度是多少,并无法明确确定。

四、解决方案

采用paddingTop的方案。

paddingTop方案能准确计算出相对位置,问题是必须首先明确自身的高度才可能。

采用固定控件高度的方式来实现。

int getPaddingTop(View anchor) {

  int y = 0;

  View rootView = anchor.getRootView();

  // anchor relative to root
  if (rootView instanceof ViewGroup) {
    Rect anchorRect = this.bounds;
    anchorRect.set(0, 0, anchor.getWidth(), anchor.getHeight());

    ((ViewGroup)rootView).offsetDescendantRectToMyCoords(anchor, anchorRect);

    y = anchorRect.bottom;
  }

  if (y > 0) {
    int height = context.getResources().getDimensionPixelSize(R.dimen.tapeActionHeight);
    y -= height;

    y -= this.statusBarHeight;
  }

  y = y < 0? 0: y;
  return y;
}

五、遗留问题

相较于paddingTop方案,更喜欢paddingBottom的方案。

使用paddingBottom可以不用固化控件高度,更加自由一些。

未来再针对刘海屏、水滴屏进行更多测试,希望能改回paddingBottom方案。

六、接下来

继续测试,正确明天7月1日发布2.7.0的正式版本。

七、Finally

尔时世尊。食时。
著衣持钵。入舍卫大城乞食。

于其城中。次第乞已。还至本处。
饭食讫。
收衣钵。
洗足已。
敷座而坐。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值