实现弹窗随键盘上移居中
实现弹窗随键盘上移的核心思路
在Android中,可以通过监听键盘的显示和隐藏事件,动态调整弹窗的位置。关键点在于获取键盘高度,并计算剩余屏幕空间以重新定位弹窗。
// 在Activity或Fragment中设置键盘监听
val rootView = findViewById<View>(android.R.id.content)
rootView.viewTreeObserver.addOnGlobalLayoutListener {val rect = Rect()rootView.getWindowVisibleDisplayFrame(rect)val screenHeight = rootView.rootView.heightval keyboardHeight = screenHeight - rect.bottomif (keyboardHeight > screenHeight * 0.15) {// 键盘显示,调整弹窗位置adjustDialogPosition(keyboardHeight)} else {// 键盘隐藏,恢复默认位置resetDialogPosition()}
}
创建自定义弹窗布局
使用Dialog或DialogFragment时,需要确保布局可以动态调整位置。示例布局文件:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/dialog_container"android:layout_width="match_parent"android:layout_height="match_parent"><LinearLayoutandroid:id="@+id/dialog_content"android:layout_width="300dp"android:layout_height="wrap_content"android:layout_gravity="center"android:orientation="vertical"android:padding="16dp"><!-- 弹窗内容 --></LinearLayout>
</FrameLayout>
动态调整弹窗位置代码
通过修改布局参数实现位置调整:
private fun adjustDialogPosition(keyboardHeight: Int) {val dialogContent = dialog.findViewById<View>(R.id.dialog_content)val params = dialogContent.layoutParams as FrameLayout.LayoutParamsval screenHeight = resources.displayMetrics.heightPixelsval targetY = (screenHeight - keyboardHeight) / 2 - dialogContent.height / 2params.topMargin = targetYdialogContent.layoutParams = params
}private fun resetDialogPosition() {val dialogContent = dialog.findViewById<View>(R.id.dialog_content)val params = dialogContent.layoutParams as FrameLayout.LayoutParamsparams.topMargin = 0params.gravity = Gravity.CENTERdialogContent.layoutParams = params
}
处理WindowSoftInputMode
在AndroidManifest.xml中为Activity设置正确的软键盘模式:
<activityandroid:name=".YourActivity"android:windowSoftInputMode="adjustResize|stateHidden" />
注意事项
- 键盘高度计算需要排除系统状态栏和导航栏的影响
- 在横屏模式下需要特殊处理布局逻辑
- 不同Android版本可能存在行为差异,需要充分测试
- 对于DialogFragment,需要在onCreateView中获取根视图进行监听
是的,这是我直接使用AI生成的文章,看了下,大致都实现了,感觉现在博客这条下坡路确实要走到底了啊。
下面是我的代码:
@Overridepublic void onStart() {super.onStart();// 在对话框显示后设置键盘监听setupKeyboardListener();}/*** 设置键盘监听*/private void setupKeyboardListener() { // 设置全局布局监听,检测键盘状态变化if (mContext instanceof android.app.Activity) {android.app.Activity activity = (android.app.Activity) mContext;View rootView = activity.findViewById(android.R.id.content);if (rootView != null) {mGlobalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {@Overridepublic void onGlobalLayout() {checkKeyboardStatus();}};rootView.getViewTreeObserver().addOnGlobalLayoutListener(mGlobalLayoutListener);}}}/*** 检查键盘状态*/private void checkKeyboardStatus() {if (mContext instanceof android.app.Activity) {android.app.Activity activity = (android.app.Activity) mContext;View rootView = activity.findViewById(android.R.id.content);if (rootView != null) {android.graphics.Rect rect = new android.graphics.Rect();rootView.getWindowVisibleDisplayFrame(rect);int screenHeight = rootView.getHeight();int visibleHeight = rect.bottom - rect.top;// 判断键盘是否弹起(可视区域高度小于屏幕高度的75%)boolean keyboardVisible = visibleHeight < screenHeight * 0.75;if (keyboardVisible && !isKeyboardShown) {// 键盘弹起,计算对话框在剩余可见区域的居中位置isKeyboardShown = true;adjustDialogPosition(true, visibleHeight);} else if (!keyboardVisible && isKeyboardShown) {// 键盘收起isKeyboardShown = false;adjustDialogPosition(false, screenHeight);}}}}/*** 调整对话框位置* @param keyboardShown 键盘是否显示* @param visibleHeight 可见区域高度*/private void adjustDialogPosition(boolean keyboardShown, int visibleHeight) {if (getDialogHelper() == null) {return;}try {View contentView = getDialogHelper().getContentView();if (keyboardShown) {// 键盘弹起时,让对话框在剩余可见区域中居中显示getDialogHelper().setGravity(Gravity.CENTER_HORIZONTAL | Gravity.TOP);// 对话框高度(根据布局文件dialog_quick_greet.xml约246dp)int dialogHeight = (int) (246 * mContext.getResources().getDisplayMetrics().density);// 计算让对话框在可见区域居中的上边距// 公式:(可见区域高度 - 对话框高度) / 2int centeredTopMargin = (visibleHeight - dialogHeight) / 2;// 设置最小边距,避免对话框贴着屏幕顶部int minTopMargin = (int) (50 * mContext.getResources().getDisplayMetrics().density);int topMargin = Math.max(centeredTopMargin, minTopMargin);setContentViewMargin(contentView, topMargin);} else {// 键盘收起时,恢复默认的居中位置 自己的方法getDialogHelper().setGravity(Gravity.CENTER);setContentViewMargin(contentView, 0);}} catch (Exception e) {e.printStackTrace();}}/*** 设置内容视图的上边距*/private void setContentViewMargin(View contentView, int topMargin) {if (contentView != null && contentView.getLayoutParams() instanceof android.view.ViewGroup.MarginLayoutParams) {android.view.ViewGroup.MarginLayoutParams params = (android.view.ViewGroup.MarginLayoutParams) contentView.getLayoutParams();params.topMargin = topMargin;contentView.setLayoutParams(params);}}
相关文章:
实现弹窗随键盘上移居中
实现弹窗随键盘上移的核心思路 在Android中,可以通过监听键盘的显示和隐藏事件,动态调整弹窗的位置。关键点在于获取键盘高度,并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...

华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建
华为云FlexusDeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色,华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型,能助力我们轻松驾驭 DeepSeek-V3/R1,本文中将分享如何…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心
当仓库学会“思考”,物流的终极形态正在诞生 想象这样的场景: 凌晨3点,某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径;AI视觉系统在0.1秒内扫描包裹信息;数字孪生平台正模拟次日峰值流量压力…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...

自然语言处理——循环神经网络
自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元(GRU)长短期记忆神经网络(LSTM)…...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...

select、poll、epoll 与 Reactor 模式
在高并发网络编程领域,高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表,以及基于它们实现的 Reactor 模式,为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。 一、I…...

SpringTask-03.入门案例
一.入门案例 启动类: package com.sky;import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCach…...
什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南
文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果 自用
outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size:0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格ÿ…...
【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分
一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...

ios苹果系统,js 滑动屏幕、锚定无效
现象:window.addEventListener监听touch无效,划不动屏幕,但是代码逻辑都有执行到。 scrollIntoView也无效。 原因:这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作,从而会影响…...

在WSL2的Ubuntu镜像中安装Docker
Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包: for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词
Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid,其中有多少个 3 3 的 “幻方” 子矩阵&am…...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...

【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...

vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...

网络编程(UDP编程)
思维导图 UDP基础编程(单播) 1.流程图 服务器:短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...

Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...
Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理
引言 Bitmap(位图)是Android应用内存占用的“头号杀手”。一张1080P(1920x1080)的图片以ARGB_8888格式加载时,内存占用高达8MB(192010804字节)。据统计,超过60%的应用OOM崩溃与Bitm…...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...

全志A40i android7.1 调试信息打印串口由uart0改为uart3
一,概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本:2014.07; Kernel版本:Linux-3.10; 二,Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01),并让boo…...
JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案
JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停 1. 安全点(Safepoint)阻塞 现象:JVM暂停但无GC日志,日志显示No GCs detected。原因:JVM等待所有线程进入安全点(如…...