解决Popwindow宽高的问题。

问题

在使用Popwindow进行自定义的过程中,需要设置popwindow的宽高。但是宽高很多时候容易出问题。比如下面的例子。

布局文件如下

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#77000000"android:orientation="vertical"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"android:background="#fff"><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="44dp"android:layout_margin="12dp"android:background="@drawable/cz_add_rzh_bg"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:drawableStart="@drawable/cz_icon_add_rzh"android:drawablePadding="4dp"android:text="申请注册入驻号"android:textColor="#ff333333"android:textSize="14sp" /></RelativeLayout></LinearLayout><Viewandroid:id="@+id/close_layout"android:layout_width="match_parent"android:layout_height="100dp"/>
</LinearLayout>

使用了传统方法设置宽高
在这里插入图片描述
实际显示效果很差,没有内容只有一个黑色透明背景。
在这里插入图片描述

解决方案

为了解决这个问题,我写了个工具类。原理就是内部创建一个铺面全屏的FrameLayout。在填充布局的时候作为父布局,来自动计算宽高。在通过其内部的LayoutParam来获取宽高,如果宽高是-1的话,(MATCH_PARENT的值)就替换成屏幕的宽高。在编程实践中Popwindow一般会显示在某个控件的下面,这个时候布局中的高度match_parent对应的就不是手机屏幕的高度,而是需要减去上方空间占用的高度。这个时候就可以传入上方控件,可以自动计算被使用的高度。

优化

加入了顶部view的处理

package com.trs.nmip.common.util.web;import android.content.Context;
import android.util.DisplayMetrics;
import android.util.Pair;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.FrameLayout;import androidx.annotation.LayoutRes;/*** @author: zhuguohui* @date: 2025/3/21* @description: 用于获取View大小的工具类*/
public class ViewSizeUtil {private static FrameLayout fullScreenView;private static FrameLayout getFullScreenView(Context ctx) {if (fullScreenView == null) {fullScreenView = new FrameLayout(ctx);fullScreenView.measure(getWidthMeasureSpec(ctx), getHeightMeasureSpec(ctx));fullScreenView.layout(0, 0, getScreenWidth(ctx), getScreenHeight(ctx));}return fullScreenView;}public static class Size {public  int width;public  int height;public Size(int width, int height) {this.width = width;this.height = height;}}/*** 填充布局,获取宽高,用于在没有父view的情况下,计算宽高** @param ctx      上下文* @param layoutId 布局id* @param topView  在其上面的控件,比如popWindow,如果要显示在某个控件下面,并且当前控件的高度需要铺面全屏的话。*                 那么就会减去topView所占用的高度。* @return 一个pair对象,第一个元素是view,第二个是宽高*/public static Pair<View, Size> inflateViewAndGetSize(Context ctx, @LayoutRes int layoutId, View topView, int yOffset) {View view = LayoutInflater.from(ctx).inflate(layoutId, getFullScreenView(ctx), false);ViewGroup.LayoutParams layoutParams = view.getLayoutParams();int width = layoutParams.width;int height = layoutParams.height;if (width == -1) {width = getScreenWidth(ctx);}if (height == -1) {height = getScreenHeight(ctx);//如果是铺满全屏,还要显示在某个控件下面,需要减去这个控件使用的距离if (topView != null) {int[] location = new int[2];topView.getLocationOnScreen(location);int useHeight = location[1] + topView.getHeight();height -= useHeight;}}height += yOffset;return new Pair<>(view, new Size(width, height));}private static int getScreenWidth(Context context) {WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);DisplayMetrics dm = new DisplayMetrics();wm.getDefaultDisplay().getMetrics(dm);return dm.widthPixels;}private static int getScreenHeight(Context context) {DisplayMetrics displayMetrics = new DisplayMetrics();((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getRealMetrics(displayMetrics);int screenHeight = displayMetrics.heightPixels;return screenHeight;}private static int getWidthMeasureSpec(Context ctx) {return View.MeasureSpec.makeMeasureSpec(getScreenWidth(ctx), View.MeasureSpec.AT_MOST);}private static int getHeightMeasureSpec(Context ctx) {return View.MeasureSpec.makeMeasureSpec(getScreenHeight(ctx), View.MeasureSpec.AT_MOST);}}

使用方法如下。

public class ChangeRzhPopWindow extends PopupWindow {public ChangeRzhPopWindow(Context context,View topView) {super(context);Pair<View, ViewSizeUtil.Size> pair = ViewSizeUtil.inflateViewAndGetSize(context, R.layout.change_rzh_pop_window,topView);setContentView(pair.first);setWidth(pair.second.width);setHeight(pair.second.height);setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));setFocusable(true);setOutsideTouchable(true);//因为背景是我们创建的。所以需要我们实现点击背景关闭的功能pair.first.findViewById(R.id.close_layout).setOnClickListener(v-> dismiss());}
}

效果如下

红色的地方就是顶部view

在这里插入图片描述

遇到的问题

在开发中遇到一个通过代码获取的屏幕高度和手机时间高度不一致的情况,通过AI查询得到这样的结果。测试没问题。特此记录一下。

在这里插入图片描述

提取基类

把上面的功能提取一个基类。这样可以方便处理这些问题。这个基类还实现了LifecycleOwner 。更方便使用。

package com.trs.app.gzcz.content_manage.ui.rzh_title_bar.change_rzh_pop_window;import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.util.Pair;
import android.view.View;
import android.widget.PopupWindow;import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.LifecycleRegistry;import com.trs.news.R;
import com.trs.nmip.common.util.web.ViewSizeUtil;/**** @author: zhuguohui* @date: 2025/3/21* @description: 自动处理宽高的PopupWindow* 加入了LifeCycleOwner的功能*/
public class EasySizePopupWindow extends PopupWindow implements LifecycleOwner {LifecycleRegistry registry=new LifecycleRegistry(this);{registry.setCurrentState(Lifecycle.State.INITIALIZED);}protected void setContentView(Context context, @LayoutRes  int layoutId, View topView,int yOffset){Pair<View, ViewSizeUtil.Size> pair = ViewSizeUtil.inflateViewAndGetSize(context, layoutId,topView,yOffset);setContentView(pair.first);setWidth(pair.second.width);setHeight(pair.second.height);setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));setFocusable(true);setOutsideTouchable(true);//因为背景是我们创建的。所以需要我们实现点击背景关闭的功能pair.first.findViewById(R.id.close_layout).setOnClickListener(v-> dismiss());}@Overridepublic void showAsDropDown(View anchor) {super.showAsDropDown(anchor);}@Overridepublic void showAsDropDown(View anchor, int xoff, int yoff) {super.showAsDropDown(anchor, xoff, yoff);}@Overridepublic void showAsDropDown(View anchor, int xoff, int yoff, int gravity) {super.showAsDropDown(anchor, xoff, yoff, gravity);updateLifecycleState();}@Overridepublic void showAtLocation(View parent, int gravity, int x, int y) {super.showAtLocation(parent, gravity, x, y);updateLifecycleState();}@Overridepublic void dismiss() {super.dismiss();updateLifecycleStateToDismiss();}private void updateLifecycleStateToDismiss(){registry.setCurrentState( Lifecycle.State.CREATED);registry.setCurrentState( Lifecycle.State.STARTED);registry.setCurrentState( Lifecycle.State.DESTROYED);}private void updateLifecycleState(){registry.setCurrentState( Lifecycle.State.CREATED);registry.setCurrentState( Lifecycle.State.STARTED);registry.setCurrentState( Lifecycle.State.RESUMED);}@NonNull@Overridepublic Lifecycle getLifecycle() {return registry;}
}

使用

public class ChangeRzhPopWindow extends EasySizePopupWindow {public ChangeRzhPopWindow(Context context, View topView) {super();setContentView(context, R.layout.change_rzh_pop_window, topView);//因为背景是我们创建的。所以需要我们实现点击背景关闭的功能getContentView().findViewById(R.id.close_layout).setOnClickListener(v-> dismiss());}}

关于全屏高度问题

如果当前页面的布局是沉浸式的。那么使用PopupWindowshowAsDropDown会出现位置不对的情况。需要加上偏移量。
就可以完美显示了。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/38195.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Bell-1量子计算机分析:开启量子计算2.0时代的创新引擎

Bell-1量子计算机:开启量子计算2.0时代的创新引擎 一、引言 1.1 研究背景 在当今科技飞速发展的时代,量子计算作为前沿领域,正深刻地改变着科技格局,引领新一轮科技革命与产业变革。自 20 世纪 80 年代量子计算概念被提出以来,历经多年的理论探索与技术攻坚,已取得了众…

什么?中断禁用失效了?

什么&#xff1f;中断禁用失效了&#xff1f; 1. 前言 道友们&#xff0c;在嵌入式的开发中我们不管是RTOS或NO-RTOS的开发&#xff0c;都无法避免“多线程”的应用场景&#xff0c;高优先级的任务或中断打断低优先级的任务或中断&#xff0c;此时为了要保证共享数据的安全性…

单表达式倒计时工具:datetime的极度优雅(Kimi)

一个简单表达式&#xff0c;也可以优雅自成工具。 笔记模板由python脚本于2025-03-22 20:25:49创建&#xff0c;本篇笔记适合任意喜欢学习的coder翻阅。 【学习的细节是欢悦的历程】 博客的核心价值&#xff1a;在于输出思考与经验&#xff0c;而不仅仅是知识的简单复述。 Pyth…

[笔记.AI]多头自注意力机制(Multi-Head Attention)

多头自注意力是深度学习领域&#xff0c;特别是自然语言处理&#xff08;NLP&#xff09;和Transformer模型中的关键概念。其发展源于对序列数据中复杂依赖关系的建模需求&#xff0c;特别是在Transformer架构的背景下。 举例 比喻-读长篇文章 用一个简单的比喻来理解“多头注…

SOFABoot-02-模块化隔离方案

sofaboot 前言 大家好&#xff0c;我是老马。 sofastack 其实出来很久了&#xff0c;第一次应该是在 2022 年左右开始关注&#xff0c;但是一直没有深入研究。 最近想学习一下 SOFA 对于生态的设计和思考。 sofaboot 系列 SOFABoot-00-sofaboot 概览 SOFABoot-01-蚂蚁金…

【实用部署教程】olmOCR智能PDF文本提取系统:从安装到可视化界面实现

文章目录 引言系统要求1. 环境准备&#xff1a;安装Miniconda激活环境 2. 配置pip源加速下载3. 配置学术加速&#xff08;访问国外资源&#xff09;4. 安装系统依赖5. 安装OLMOCR6. 运行OLMOCR处理PDF文档7. 理解OLMOCR输出结果9. 可视化UI界面9.1 安装界面依赖9.2 创建界面应用…

asp.net core mvc模块化开发

razor类库 新建PluginController using Microsoft.AspNetCore.Mvc;namespace RazorClassLibrary1.Controllers {public class PluginController : Controller{public IActionResult Index(){return View();}} }Views下Plugin下新建Index.cshtml {ViewBag.Title "插件页…

边缘计算革命:重构软件架构的范式与未来

摘要 边缘计算通过将算力下沉至网络边缘&#xff0c;正在颠覆传统中心化软件架构的设计逻辑。本文系统分析了边缘计算对软件架构的范式革新&#xff0c;包括分布式分层架构、实时资源调度、安全防护体系等技术变革&#xff0c;并结合工业物联网、智慧医疗等场景案例&#xff0c…

单链表:数据结构的灵动之链

本文主要讲解链表的概念和结构以及实现单链表 目录 一、链表的概念及结构 二、单链表的实现 1.1链表的实现&#xff1a; 1.2单链表的实现&#xff1a; 单链表尾插&#xff1a; 单链表的头插&#xff1a; 单链表的尾删&#xff1a; 单链表头删&#xff1a; 单链表查找&#…

链表题型-链表操作-JS

一定要注意链表现在的头节点是空节点还是有值的节点。 一、移除链表中的元素 有两种方式&#xff0c;直接使用原来的链表进行删除操作&#xff1b;设置一个虚拟头节点进行删除操作。 直接使用原来的链表进行删除操作时&#xff0c;需要考虑是不是头节点&#xff0c;因为移除…

读《浪潮之巅》:探寻科技产业的兴衰密码

引言&#xff1a;邂逅《浪潮之巅》 在信息技术飞速发展的今天&#xff0c;科技公司如繁星般闪烁&#xff0c;又似流星般划过。而我与《浪潮之巅》的相遇&#xff0c;就像在浩渺的科技海洋中&#xff0c;发现了一座指引方向的灯塔。初次听闻这本书&#xff0c;是在一次技术交流会…

【和春笋一起学C++】文本文件I/O

在windows系统中读取键盘的输入和在屏幕上显示输出统称为&#xff1a;控制台输入/输出。把读取文本文件和把字符输出到文本文件中统称为&#xff1a;文本文件I/O。 目录 1. 输出文本文件 2. 读取文本文件 1. 输出文本文件 把字符输出到文本文件中和输出到控制台很相似&#x…

【C#】WinForm自定义控件及窗体

前言 WinForm&#xff08;Windows Forms&#xff09;是Microsoft.NET框架中的技术&#xff0c;用于开发Windows桌面应用程序。它提供了一套丰富的控件和组件。通过拖放控件、编写事件处理程序等方式快速构建用户界面。 通过属性窗口定制这些控件的外观和行为。 通过数据绑定&am…

Live555+Windows+MSys2 编译Androidso库和运行使用

下载 wget http://www.live555.com/liveMedia/public/live555-latest.tar.gz tar -xzvf live555-latest.tar.gz加入版本控制 git init git add . git commit -a -m "first init" git log修改config.android-arm64 cd live vim config.android-arm64 ./genMakefile…

大模型-提示词工程与架构

什么是提示工程 提示工程&#xff08;Prompt Engineering&#xff09;是一门新兴的技术领域&#xff0c;专注于研究如何设计、构建和优化提示词&#xff0c;以充分发挥大模型的潜力 。它涉及到对语言结构、任务需求、模型特性等多方面因素的综合考量。提示工程的目标是通过精心…

Agent Team 多智能体系统解析

引言 在人工智能技术高速发展的今天&#xff0c;"多智能体协作系统"&#xff08;Agent Team&#xff09;正成为突破效率瓶颈的关键技术。与传统的单体AI不同&#xff0c;这种由多个专业化智能体组成的协同网络&#xff0c;通过分工协作和动态调整&#xff0c;展现出…

【蓝桥杯—单片机】IAP15F2K61S2专项 | 真题整理、解析与拓展 | 省赛题(更新ing...)

IAP15F2K61S2 专项 前言IAP15F2K61S2 介绍&#xff08;基于手册&#xff09;I/O口结构复位管脚RST中断第十四届省赛 外设通过PWM控制第十五届省赛题 性能与工作参数在线调试第十四届省赛题拓展与小结&#xff1a;单片机在线调试常用的接口 功耗第十五届省赛题 前言 在本文中我…

生物化学笔记:医学免疫学原理02 抗原概念+免疫应答+抗原的分类

抗原基本概念 影响抗原刺激机体产生免疫应答的因素 抗原的分类 CG 【北京大学】1080p 王月丹教授 《医学免疫学原理》2022春 全81p

(UI自动化测试)第二篇:元素定位的方法_name定位

二、name定位 ⽅法&#xff1a; driver.find_element_by_name(“name属性值”) 前置&#xff1a; 标签必须name属性 特点&#xff1a; 当前⻚⾯可以重复 提示&#xff1a; 由于name属性值可以重复&#xff0c;所以使⽤时需要查看是否为唯⼀。 # 导包selenium from selenium i…

软考中级-软件设计师 准备

软考中级-软件设计师 准备 一、软考相关1.1、考试时间1.2、考试时长1.3、题型和分值&#xff1a; 二、软考备考2.1、相关书籍2.2、推荐课程&#xff1a;B站up主zst_20012.3、学习路线 一、软考相关 1.1、考试时间 一年有两次软考&#xff0c;一般是五月末和十一月的中旬 以下…