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 BaseDialogFragmentextends DialogFragment {

protected ViewmLayout;

    private AlertDialogdialog;

   @NonNull

@Override

   public DialogonCreateDialog(@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;

   }

@Override

   public 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.TOP

       this.gravity = gravity;

   }

protected void setCancel(boolean cancelable){//Gravity.TOP

       this.cancelable = cancelable;

   }

protected abstract int getLayoutId();

    protected abstract void initView();

}

```

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

1.一直觉得在实例化对象的时候(也就是点击按钮出现弹窗的时候),不应该每次都去创建fragment实例,而应该去判一个空,创建过一次以后,再次点击就只去修改UI。之前使用PopupWindow的时候一直采用这种做法。但是这次真的是,去这样处理感觉给自己挖了一个好大的坑。具体现象就是,第二次点击后UI无法正常刷新。

尝试解决了好久,最后我妥协了。还是每次都去new一个新的吧!也去看了一下dismiss方法的源码,dismiss后是会把fragment给移除掉的。并且在Profiler中去观察了我疯狂点击按钮,一直出弹窗的情况下内存变化。确实真的没啥变化。放心去new就好了。(欢迎指教)

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

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,504评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,434评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,089评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,378评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,472评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,506评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,519评论 3 413
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,292评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,738评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,022评论 2 329
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,194评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,873评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,536评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,162评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,413评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,075评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,080评论 2 352

推荐阅读更多精彩内容