PopWindow在Android 2.3.3 或以下的系统的一个bug 及其解决办法

2024-06-15 15:32

本文主要是介绍PopWindow在Android 2.3.3 或以下的系统的一个bug 及其解决办法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

今日终于修复了一个非常严重的bug:
这个bug非常奇怪,我在Anroid.4.0.4或以上测试都正常,但是后来廉温说他在他的手机按一下右下角的"设置"按钮(Button),居然出现了崩溃现象(理论上会在设置按钮上弹出一popuwindow);
廉温手机系统2.3.X ;然后我用平板(系统也是2.3.x)测试下,果然出现错误;
由于平板基本报废,无法USB连接地电脑跟踪测试;一开始我没放在心上,因为几台4.0.4or以上系统都测试能正常。。
于是开了模拟器(系统2.3.3)测试,结果还是崩溃,看log日志 ,报了一个NullPointExcetion,这。。实在太费解了!
问题入口:
......
protected PopupWindow window;
......
this.window = new PopupWindow(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT);
....
这里我实例化一个 PopupWindow ,当时我没有注意,以为传入2个 MeasureSpec (  Width/Height )也就是窗体layout_height 和layout_weight ; 可以是   FILL_PARENT or  WRAP_CONTENT or 具体的高和宽!
悲剧的是,看回文档,居然是:

public PopupWindow (int width, int height)
Added in  API level 1

Create a new empty, non focusable popup window. The dimension of the window must be passed to this constructor.

The popup does not provide any background. This should be handled by the content view.

Parameters
width the popup's width
height the popup's height 

这实际上要是指定了content view 的高、宽 而不是MeasureSpec (FILL_PARENT or WRAP_CONTENT 。。)
那就奇怪了,由于 ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT 这两个常量是负数
窗体的高宽是负数,按道理是不会显示窗体的啊!而且4.0.4系统还是会个跟2.3.3报同一个错误啊! 
但为啥在系统是4.0.4的时候还是正常显示,而2.3.3却错误?
于是我翻看了源码,跟踪记录如下:
Step 1: 
249
     public PopupWindow(int widthint height) {
250
         this(nullwidthheight);     
251
     } 
        

Step    2:
 
265
     public PopupWindow(View contentViewint widthint height) {
266
         this(contentViewwidthheightfalse);  // ->
contentView = null
267
     }
   
Step 3:
   
281
     public PopupWindow(View contentViewint widthint heightboolean focusable) {
282
         if (contentView != null) {
283
             mContext = contentView.getContext();
284
             mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
285
         }
286
         setContentView(contentView);     // -> 在这里报了个NullPointExcetion ,再跟踪
287
         setWidth(width);
288
         setHeight(height);
289
         setFocusable(focusable);
290
     }


Step 4 :
2.3.3
系统下
 
   
376
     public void setContentView(View contentView) {
377
         if (isShowing()) {
378
             return;
379
         }
380
 
381
         mContentView = contentView;
382
 
383
         if (mContext == null) {
384
             mContext = mContentView.getContext();
385
         }
386
 
387
         if (mWindowManager == null) {
388
             mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
389
         }
390
     }
 
同是
Step 4 :
4.0.4 系统下
390
     public void setContentView(View contentView) {
391
         if (isShowing()) {
392
             return;
393
         }
394
 
395
         mContentView = contentView;
396
 
397
         if (mContext == null && mContentView != null) {
398
             mContext = mContentView.getContext();
399
         }
400
 
401
         if (mWindowManager == null && mContentView != null) {
402
             mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
403
         }
404
     }
果然~出现了非常神奇的一幕~ 原来在2.3.3的时候忘记检查
mContentView 是否为空,因为mContextView 这个对象可以在实例化一个PopupWindow 后再通过SetContextView(View view)传入
也就是说,这是算是一个系统级的小bug~ 所以在2.3.3 或以前的版本时 就会崩溃,在4.0.4 以后的都不会崩溃;这不能完全怪谷歌,谁让我没有认真看下文档呢?
这也是我第一次发现谷歌的代码漏洞XD

解决2.3.3或以下的办法就是用
1、可以用PopupWindow(Context context)这个构造方法实例化
2、mPopupWindow.setContentView(View view) 传入content view
3、mPopupWindow.setWidth(WindowManager.LayoutParams.WRAP_CONTENT);
mPopupWindow.setHeight(WindowManager.LayoutParams.WRAP_CONTENT);
这里的setWidth() setHeight() 才是是改变PopupWindow 的Width/Height MeasureSpec

转载请说明出处,鼓励原创!

这篇关于PopWindow在Android 2.3.3 或以下的系统的一个bug 及其解决办法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1063851

相关文章

javacv依赖太大导致jar包也大的解决办法

《javacv依赖太大导致jar包也大的解决办法》随着项目的复杂度和依赖关系的增加,打包后的JAR包可能会变得很大,:本文主要介绍javacv依赖太大导致jar包也大的解决办法,文中通过代码介绍的... 目录前言1.检查依赖2.更改依赖3.检查副依赖总结 前言最近在写项目时,用到了Javacv里的获取视频

JWT + 拦截器实现无状态登录系统

《JWT+拦截器实现无状态登录系统》JWT(JSONWebToken)提供了一种无状态的解决方案:用户登录后,服务器返回一个Token,后续请求携带该Token即可完成身份验证,无需服务器存储会话... 目录✅ 引言 一、JWT 是什么? 二、技术选型 三、项目结构 四、核心代码实现4.1 添加依赖(pom

基于Python实现自动化邮件发送系统的完整指南

《基于Python实现自动化邮件发送系统的完整指南》在现代软件开发和自动化流程中,邮件通知是一个常见且实用的功能,无论是用于发送报告、告警信息还是用户提醒,通过Python实现自动化的邮件发送功能都能... 目录一、前言:二、项目概述三、配置文件 `.env` 解析四、代码结构解析1. 导入模块2. 加载环

Android协程高级用法大全

《Android协程高级用法大全》这篇文章给大家介绍Android协程高级用法大全,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友跟随小编一起学习吧... 目录1️⃣ 协程作用域(CoroutineScope)与生命周期绑定Activity/Fragment 中手

linux系统上安装JDK8全过程

《linux系统上安装JDK8全过程》文章介绍安装JDK的必要性及Linux下JDK8的安装步骤,包括卸载旧版本、下载解压、配置环境变量等,强调开发需JDK,运行可选JRE,现JDK已集成JRE... 目录为什么要安装jdk?1.查看linux系统是否有自带的jdk:2.下载jdk压缩包2.解压3.配置环境

Linux查询服务器系统版本号的多种方法

《Linux查询服务器系统版本号的多种方法》在Linux系统管理和维护工作中,了解当前操作系统的版本信息是最基础也是最重要的操作之一,系统版本不仅关系到软件兼容性、安全更新策略,还直接影响到故障排查和... 目录一、引言:系统版本查询的重要性二、基础命令解析:cat /etc/Centos-release详

Android 缓存日志Logcat导出与分析最佳实践

《Android缓存日志Logcat导出与分析最佳实践》本文全面介绍AndroidLogcat缓存日志的导出与分析方法,涵盖按进程、缓冲区类型及日志级别过滤,自动化工具使用,常见问题解决方案和最佳实... 目录android 缓存日志(Logcat)导出与分析全攻略为什么要导出缓存日志?按需过滤导出1. 按

更改linux系统的默认Python版本方式

《更改linux系统的默认Python版本方式》通过删除原Python软链接并创建指向python3.6的新链接,可切换系统默认Python版本,需注意版本冲突、环境混乱及维护问题,建议使用pyenv... 目录更改系统的默认python版本软链接软链接的特点创建软链接的命令使用场景注意事项总结更改系统的默

在Linux系统上连接GitHub的方法步骤(适用2025年)

《在Linux系统上连接GitHub的方法步骤(适用2025年)》在2025年,使用Linux系统连接GitHub的推荐方式是通过SSH(SecureShell)协议进行身份验证,这种方式不仅安全,还... 目录步骤一:检查并安装 Git步骤二:生成 SSH 密钥步骤三:将 SSH 公钥添加到 github

Android Paging 分页加载库使用实践

《AndroidPaging分页加载库使用实践》AndroidPaging库是Jetpack组件的一部分,它提供了一套完整的解决方案来处理大型数据集的分页加载,本文将深入探讨Paging库... 目录前言一、Paging 库概述二、Paging 3 核心组件1. PagingSource2. Pager3.