阅读 196

Android通过富文本实现点击(?)符号后弹出自定义气泡提示框来提示用户的功能

废话不多说,先上图。此功能是当用户点击 "?" 后会弹出这么一个气泡提示框,当用户再点击任意位置时,此弹框便会消失,我寻思这功能的使用场景非常的广,未来我可能也要接到这样的需求,顺便可以巩固加强下自定义绘制一个图View和富文本的使用,所以决定手撸一下这个Demo,源码已提交,需要的看官可在文章结尾自行pull.

login1.png

一、基本实现思路

1. 气泡框的实现

首先,需要自行绘制一个长方形,然后在长方形顶部绘制一个小三角形从而得到一个BubbleView,然后把这个BubbleView,然后把这个BubbleView封装进BubbleViewLayout中(这是一个自定义的类),从而完成了气泡弹框的自定义View的实现。

2. 跟随在文本后面的可点击的 "?" 问号实现

这里我采用的是富文本,也就是SpannableStringBuilder这个类,关于它的使用方法我这里简单介绍一下: 第一步:初始化一个SpannableStringBuilder

SpannableStringBuilder spanText = new SpannableStringBuilder("我希望取得會員獨家優惠及最新著數。" + “  ”);复制代码



第二步:将 "?" 图标插入到text中的第length - 2 至 length - 1 处的位置,注意第一步中有个魔鬼细节,我在最后加了两个空格的字符串,这可不是有病才加的。因为我在开发时发现如果把这个问号图标直接加在末尾,而后面没有空格作为填充的话,那么问号后面的空白区域全都是可点击的,感觉这是个笨办法,如果有哪个大佬有更好的解决方案可以评论告诉我。

spanText.setSpan(
        new ImageSpan(finalThis,R.drawable.help_black,DynamicDrawableSpan.ALIGN_CENTER),
        spanText.length() - 2 , spanText.length() - 1,
        Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);复制代码



第三步:给 "?" 添加监听点击事件

spanText.setSpan(
        //对 ?标识添加点击事件,弹出提示气泡
        new ClickableSpan() {
            @Override
            public void onClick(@NonNull View widget) {
            //在此处添加点击后的效果
            }
        },
        spanText.length() - 2 , spanText.length() - 1,
        Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);复制代码



第四步:把spanText添加进TextView中,并激活点击事件:

subtitle_text.setText(spanText);
subtitle_text.setMovementMethod(LinkMovementMethod.getInstance());//激活事件,如果句代码缺少,那么点击事件将不会生效,请注意复制代码

好了。这就是富文本的基本使用方法,如需要详细了解的看官可以自行百度下,有很多帖子介绍的很详细,但是这富文本的使用我踩了个坑,让我解决了很久,因为我给TextView控件设置了maxWidth,并且maxLine = 2,此时如果你的设备分辨率比较低,一行显示不下文字,那么就会被自动换行,这很现象正常,可是不正常的地方是,我的 "?" 添加到文本的末尾部分,可他居然不会换行!!!于是出现了以下的情况,这真是见了老鬼了,最终在查阅资料和源码后,重写了ImageSpan里的draw() 方法,手动添加换行后的高度才解决了问题,后续会将源码放上的。

bug.jpg

3.点击 "?" 后弹出气泡提示的实现

这里我采用的window的方式, 因为这样可以保证我的气泡弹框一定处于最顶层的View,从而不会被其他view给遮挡,还有最为关键得是,他可以拦截住事件分发,保证在气泡弹框存在时,其他的view的点击事件不会响应,这点是很关键的。关于window的使用,我直接放代码,看官可以看代码里的注释进行了解:

mBubbleViewLayout = new BubbleViewLayout(context);
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);//获取一个window服务

//初始化window布局的参数
WindowManager.LayoutParams params = new WindowManager.LayoutParams(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT,0,0, PixelFormat.TRANSLUCENT);

//设置window的flags,这些参数用于设置该window的事件分发机制和锁屏显示等设置,这三条是常用默认的,具体可以参阅百度或者谷歌文档
params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
        WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |       
WindowManager.LayoutParams.FLAG_DIM_BEHIND;//注意此flag和下面的params.dimAmount是配套使用的,用于设定window背景遮罩的,window背景默认是纯黑的,现在我给他设置为透明的 

//设置window类型为dialog
params.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;

params.dimAmount = 0.0f;
params.alpha = 0.99f;
params.gravity = Gravity.LEFT | Gravity.TOP;
//将View添加至window中
mWindowManager.addView(mBubbleViewLayout, params);复制代码

二、踩坑和细节

关于踩坑问题,除了富文本不会自动换行之外,还有window使用中过程中,细心的看官发现这句代码 params.alpha = 0.99f是关于气泡框透明度问题的,我为什么不设置为1,而是要设置为0.99呢?这不是因为好玩,而是因为当我设置为1时,这里的背景遮罩设置代码params.dimAmount = 0.0f将完全失效,背景将变为纯黑色,我也分析了源码,但还是不知道为什么,根据源码逻辑,我设置为0.99是没问题的,至于为什么设置为1不行,希望有大佬给我解惑解惑。

此项目还有一个细节,就是在适配不同屏幕时, "?" 出现的位置可能会不一样,例如有的设备一行就能显示出完整文案,而有的设备需要换行,这就导致气泡框的那个三角形尖需要时时刻刻定位到 "?“ 的位置,而 "?" 并不算一个实际的View,所以无法调用view.getLocationOnScreen(position)方法直接进行定位,而我采用的方法是,在重写draw方法后获取它在TextView中的相对位置,然后通过getLocationOnScreen(position)获取TextView的绝对位置,最后进行相加得到,需要详细了解的看官可以去看下我的demo源码。


作者:Android王小波
链接:https://juejin.cn/post/7038408232284946463

 伪原创工具 SEO网站优化  https://www.237it.com/ 


文章分类
ANDROID
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐