当前位置: 首页 > news >正文

实现弹窗随键盘上移居中

实现弹窗随键盘上移的核心思路

在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" />

注意事项

  1. 键盘高度计算需要排除系统状态栏和导航栏的影响
  2. 在横屏模式下需要特殊处理布局逻辑
  3. 不同Android版本可能存在行为差异,需要充分测试
  4. 对于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);}}

相关文章:

  • 基于stm32F10x 系列微控制器的智能电子琴(附完整项目源码、详细接线及讲解视频)
  • 协议转换利器,profinet转ethercat网关的两大派系,各有千秋
  • 【阅读笔记】MemOS: 大语言模型内存增强生成操作系统
  • 论文笔记:Urban Computing in the Era of Large Language Models
  • 基于51单片机的篮球计分器
  • 【第一章:人工智能基础】01.Python基础及常用工具包-(4)Python环境管理
  • REBT 分类任务中,`loss`(损失值)和 `logits`(原始预测分数)是什么
  • 用 Rust 重写 Linux 内核模块实战:迈向安全内核的新篇章
  • SAM2Long本地部署,视频分割处理,绿幕抠像,超长视频支持
  • Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式
  • 深度解析云存储:概念、架构与应用实践
  • XMLGregorianCalendar跟Date、localDateTime以及String有什么区别
  • VisualXML全新升级 | 新增数据库编辑功能
  • 【深度学习新浪潮】大模型中,active parameters和total parameters都是什么?
  • rnn判断string中第一次出现a的下标
  • Unity-ECS详解
  • Ubuntu里面单独编译某一个模块
  • DriveGPT4: Interpretable End-to-end Autonomous Driving via Large Language Model
  • FreeRTOS学习02_任务管理
  • [论文阅读]人工智能 | CoMemo:给大视觉语言模型装个“图像记忆”
  • 中国企业名录黄页/站长工具seo下载
  • 济源制作网站/百度app免费下载
  • 沈阳做网站好的/百度学术论文查重入口
  • 网站打开慢 可以只换空间不换域名吗/最新实时新闻
  • 住房和城乡建设部网站园林一级/优化什么
  • 做便民网站都需要哪些模块/优化设计答案四年级上册语文