DialogFragment——解决PopupWindow中的输入框无法复制粘贴的问题;Android中的两种弹窗PopupWindow和Dialog的区别。

本文主要是介绍DialogFragment——解决PopupWindow中的输入框无法复制粘贴的问题;Android中的两种弹窗PopupWindow和Dialog的区别。,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本文旨在介绍Android中的两种弹窗PopupWindow和Dialog的区别。以及关于写代码的一些思考。

其实之前各类弹窗,都是使用PopupWindow来实现的。因为PopupWindow能实现这些需求,虽然有的时候有些麻烦,比如前面的文章有写到PopupWindow去实现蒙版遮罩的问题。它本身是没有蒙版提供的。

我们项目中使用各种方法去给它增加遮盖层。如今看来确实是有些愚蠢的。我不介意说出以前存在的问题,因为发现问题并改进问题才是学习的过程。当然也希望看到这篇文章的小伙伴有自己的想法可以多多沟通,如果也有跟过去的我一样盲目的使用PopupWindow来做需求的同学,可以从这篇文章中学到东西。

这次遇到PopupWindow中的输入框无法复制粘贴,惯例先去网上搜了一下,发现很多人遇到同样的问题,解决方案全部都是换成DialogFragment就好了。得到这个结果后我有点不服气,为啥我PopupWindow复制粘贴就不行,为啥就非得换成DialogFragment。关于为啥PopupWindow复制粘贴不行,我开始各种搜索,也去学习了一下长按复制粘贴的源码,但是感觉自己的智商不是很够,到现在也没弄明白到底为啥不行。如果有知道的小伙伴希望不吝赐教。

通过这个问题我开始思考,为什么我不管什么弹窗类的需求都用PopupWindow来实现,到底它有啥好的?既然它这么好,那dialog存在的意义又是什么呢。其实以前的做法说白了,就是有项目里有了一套没什么问题的类似代码以后,再来相关的需求,不外乎就是复制粘贴去实现。所以就导致了一直用PopupWindow的这个问题。其实在用的时候,尤其是在强行给PopupWindow加入灰色蒙版的时候,我就有个疑问,为什么PopupWindow不自带蒙版,还要自己去实现,而且网上处理这类问题的文章并不多。这次真的想弄明白官方为什么要提供两种弹窗以后,这些疑惑也就想通了。

简单介绍:

Dialog
默认带灰色遮盖层,会覆盖整个屏幕,使dialog下层的内容不可点击,只有先取消dialog才能继续点击其他内容。
所以当你的需求,是需要一个灰色覆盖层的时候,优先考虑使用Dialog。
Dialog可以指定显示在屏幕个各个位置,可以通过设置偏移实现显示在屏幕的某个位置上。
灰色蒙层的透明度可控,展示位置可控,页面布局可控。

AlertDialog
没啥说的,是Dialog的一个子类,就是为了更方便使用而存在的。

DialogFragment
谷歌官网推荐的Dialog实现方式,使用这个可以让Dialog的生命周期可控。
用法可以参考官网对DialogFragment的介绍:https://developer.android.google.cn/guide/topics/ui/dialogs#java

PopupWindow
不带灰色遮盖层,可以显示在屏幕的任意位置,也可以基于某个view的位置显示。
其他能实现的功能基本与dialog一致。所以其实这两个确实是可以互相替代的。

总结,我的理解:
一般来说,我们开发需求的时候很少会使用到系统自带的样式,基本上都需要自定义样式的。在这一点上,Dialog和PopupWindow并没什么区别,都是可以做到的。

1.那么通常当需求中需要实现灰色蒙版的时候,建议使用DialogFragment实现,自带蒙版。
2.当需求的弹窗里面有输入框的时候,建议使用DialogFragment(因为一般正常都需要支持复制粘贴的)
3.如果需求是要求基于某个view的位置去显示,那么建议使用PopupWindow。如果不带蒙版效果,建议使用PopupWindow。

具体情况还是具体分析啦。不过通过这次让我明白一个道理,官方提供的同类View是针对不同情况下存在更合适使用的。虽然很多功能我们通过一套逻辑就能实现,但是还是应该多去思考一下不同的实现方式到底有什么不同,选一个更合适更合理的方法。

下面附一下我学习了DialogFragment后,对它的一个简单基类封装,旨在对同类弹窗的一个封装,减少每个弹窗都要去初始化dialog代码,让子类只需要处理业务逻辑。

/*** 基于DialogFragment实现的dialog基类(目的:基类完成初始化弹窗等一些配置工作,子类做逻辑处理)* 通过实现getLayoutId()返回布局文件,实现自定义布局* 通过实现initView()完成布局初始化。* 通过调用 show(FragmentManager manager, String tag) 方法展示弹窗。* DialogFragment的dismiss处理了fragment的移除操作,因此每次使用时直接New对象即可,不需考虑复用问题(亲试:考虑的话会存在一些问题)。** 可配置,弹窗位置(当居顶部显示的时候,可配置距顶部的百分比setMarginTop)* 可配置是否可取消* 可配置灰色蒙版透明度** Time:2021/2/4* Author:yang.dong*/
public abstract class BaseDialogFragment extends DialogFragment {protected View mLayout;private AlertDialog dialog;@NonNull@Overridepublic Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {if(dialog == null){AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());LayoutInflater inflater = getActivity().getLayoutInflater();mLayout = inflater.inflate(getLayoutId(), null);builder.setView(mLayout);dialog = builder.create();Window dialogWindow = dialog.getWindow();WindowManager.LayoutParams lp = dialogWindow.getAttributes();dialogWindow.setDimAmount(alpha); //设置灰色遮盖层的透明度dialogWindow.setBackgroundDrawableResource(android.R.color.transparent); //dialog会有默认背景,设置透明后,可以完美展示自己的布局dialogWindow.setGravity(gravity); //设置居顶部显示if(gravity == Gravity.TOP){ //距离屏幕顶部Display d = getActivity().getWindowManager().getDefaultDisplay(); // 获取屏幕宽、高用lp.y = (int)(d.getHeight() * marginTop); // 新位置Y坐标}dialogWindow.setAttributes(lp);dialog.setCanceledOnTouchOutside(cancelable);}initView();return dialog;}@Overridepublic void show(FragmentManager manager, String tag) {//防止重复添加fragment崩溃FragmentTransaction transaction = manager.beginTransaction();Fragment fragment = manager.findFragmentByTag(tag);if(fragment != null){transaction.remove(fragment);}transaction.commit();super.show(manager, tag);}private float alpha = 0.3f;private float marginTop = 0.3f; // 距离顶部的高度(当Gravity为top时,生效)private int gravity = Gravity.TOP;private boolean cancelable = false; //点击灰色区域是否可以取消,默认不取消private void setAlpha(float alpha){this.alpha = alpha;}protected void setMarginTop(float marginTop){this.marginTop = marginTop;}protected void setGravity(int gravity){ //Gravity.TOPthis.gravity = gravity;}protected void setCancel(boolean cancelable){ //Gravity.TOPthis.cancelable = cancelable;}protected abstract int getLayoutId();protected abstract void initView();
}

另外在使用的过程中,遇到两个问题:

1.一直觉得在实例化对象的时候(也就是点击按钮出现弹窗的时候),不应该每次都去创建fragment实例,而应该去判一个空,创建过一次以后,再次点击就只去修改UI。之前使用PopupWindow的时候一直采用这种做法。但是这次真的是,去这样处理感觉给自己挖了一个好大的坑。具体现象就是,第二次点击后UI无法正常刷新。
尝试解决了好久,最后我妥协了。还是每次都去new一个新的吧!也去看了一下dismiss方法的源码,dismiss后是会把fragment给移除掉的。并且在Profiler中去观察了我疯狂点击按钮,一直出弹窗的情况下内存变化。确实真的没啥变化。放心去new就好了。(欢迎指教)

2.快速点击导致闪退。其实这个问题我是为了解决第一个问题,在网上找答案的时候,看别人使用这个遇到的坑,说快速连着点两下就会闪退。我试了一下 ,
果然特喵的闪退了。还真的是。。。我想不出来当时的心情。感觉这种问题真的不该我们来处理的。一个方案是别人帮我踩的坑,如上对show()方法的一个重写。重写了以后连续点两次以后确实不闪退了。不过感觉体验也不是特别好,弹窗还是会出现两次,第一个先消失然后出现第二个。所以我又给点击事件加上了防止连续点击的处理。两手准备吧算是~

这次的分享就到这里啦,欢迎指教,大家加油哦

这篇关于DialogFragment——解决PopupWindow中的输入框无法复制粘贴的问题;Android中的两种弹窗PopupWindow和Dialog的区别。的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

详谈redis跟数据库的数据同步问题

《详谈redis跟数据库的数据同步问题》文章讨论了在Redis和数据库数据一致性问题上的解决方案,主要比较了先更新Redis缓存再更新数据库和先更新数据库再更新Redis缓存两种方案,文章指出,删除R... 目录一、Redis 数据库数据一致性的解决方案1.1、更新Redis缓存、删除Redis缓存的区别二

oracle数据库索引失效的问题及解决

《oracle数据库索引失效的问题及解决》本文总结了在Oracle数据库中索引失效的一些常见场景,包括使用isnull、isnotnull、!=、、、函数处理、like前置%查询以及范围索引和等值索引... 目录oracle数据库索引失效问题场景环境索引失效情况及验证结论一结论二结论三结论四结论五总结ora

element-ui下拉输入框+resetFields无法回显的问题解决

《element-ui下拉输入框+resetFields无法回显的问题解决》本文主要介绍了在使用ElementUI的下拉输入框时,点击重置按钮后输入框无法回显数据的问题,具有一定的参考价值,感兴趣的... 目录描述原因问题重现解决方案方法一方法二总结描述第一次进入页面,不做任何操作,点击重置按钮,再进行下

解决mybatis-plus-boot-starter与mybatis-spring-boot-starter的错误问题

《解决mybatis-plus-boot-starter与mybatis-spring-boot-starter的错误问题》本文主要讲述了在使用MyBatis和MyBatis-Plus时遇到的绑定异常... 目录myBATis-plus-boot-starpythonter与mybatis-spring-b

Android数据库Room的实际使用过程总结

《Android数据库Room的实际使用过程总结》这篇文章主要给大家介绍了关于Android数据库Room的实际使用过程,详细介绍了如何创建实体类、数据访问对象(DAO)和数据库抽象类,需要的朋友可以... 目录前言一、Room的基本使用1.项目配置2.创建实体类(Entity)3.创建数据访问对象(DAO

结构体和联合体的区别及说明

《结构体和联合体的区别及说明》文章主要介绍了C语言中的结构体和联合体,结构体是一种自定义的复合数据类型,可以包含多个成员,每个成员可以是不同的数据类型,联合体是一种特殊的数据结构,可以在内存中共享同一... 目录结构体和联合体的区别1. 结构体(Struct)2. 联合体(Union)3. 联合体与结构体的

SpringBoot整合kaptcha验证码过程(复制粘贴即可用)

《SpringBoot整合kaptcha验证码过程(复制粘贴即可用)》本文介绍了如何在SpringBoot项目中整合Kaptcha验证码实现,通过配置和编写相应的Controller、工具类以及前端页... 目录SpringBoot整合kaptcha验证码程序目录参考有两种方式在springboot中使用k

电脑显示hdmi无信号怎么办? 电脑显示器无信号的终极解决指南

《电脑显示hdmi无信号怎么办?电脑显示器无信号的终极解决指南》HDMI无信号的问题却让人头疼不已,遇到这种情况该怎么办?针对这种情况,我们可以采取一系列步骤来逐一排查并解决问题,以下是详细的方法... 无论你是试图为笔记本电脑设置多个显示器还是使用外部显示器,都可能会弹出“无HDMI信号”错误。此消息可能

mysql主从及遇到的问题解决

《mysql主从及遇到的问题解决》本文详细介绍了如何使用Docker配置MySQL主从复制,首先创建了两个文件夹并分别配置了`my.cnf`文件,通过执行脚本启动容器并配置好主从关系,文中还提到了一些... 目录mysql主从及遇到问题解决遇到的问题说明总结mysql主从及遇到问题解决1.基于mysql

如何测试计算机的内存是否存在问题? 判断电脑内存故障的多种方法

《如何测试计算机的内存是否存在问题?判断电脑内存故障的多种方法》内存是电脑中非常重要的组件之一,如果内存出现故障,可能会导致电脑出现各种问题,如蓝屏、死机、程序崩溃等,如何判断内存是否出现故障呢?下... 如果你的电脑是崩溃、冻结还是不稳定,那么它的内存可能有问题。要进行检查,你可以使用Windows 11