• TextView SpannableString 使用之实现可点击超链接效果


    TextView SpannableString 使用之实现可点击超链接效果

    如果看到这里说明你对 TextView 已经有了一定的了解,至少已经使用过该控件显示文字过。现在来实现一些复杂一点的效果。

    1. 实现可点击的超链接

    我们在APP开发过程中会遇到这样的需求,例如:

    需求

    其中标记为下划线的为可点击,点击后一般是跳转一个网页(这个在这里不做讨论)。面对这样的需求里可能已经知道TextView是可以添加下划线的,你的实现可能是:

    By Login, You agree to our Privicy Policy & Terms of use
    [TextView]----[TextView]--[TextView]---[TextView]
    [By Login, You agree to our ][Privicy Policy][ & ][Terms of use]
    

    然后为可点击的 TextView添加下划线,然后设置点击事件就ok了。
    如果你满足于这,那么你可以继续往后看,看看只用一个TextView 如何实现。

    2. 可点击的超链接(基础)

    为了介绍 SpannableString,我们来用它实现一个简单的下划线并设置监听点击事件。

    简单使用

     		String clickString = "I Love Android!";
            SpannableString spannableString =new SpannableString(clickString);
            spannableString.setSpan(new ClickableSpan() {
                @Override
                public void onClick(View widget) {
                    Toast.makeText(getActivity(),"Love",Toast.LENGTH_SHORT).show();
                }
            },2,6,Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            tv_tip.setText(spannableString);
            tv_tip.setMovementMethod(LinkMovementMethod.getInstance());
    

    3. 多个可点击的超链接(提高)

    这回就要使用一个新的类:SpannableStringBuilder。看到名字就知道,它的作用类似StringBuilder就是把多个SpannableString连接起来。
    最后的效果:

    进阶使用

    点击效果:

    点击效果

    代码实现(关键点就是把多个SpannableString连接起来):

            final String linkWord1 = "Android";
            final String linkWord2 = "Are you ok?";
            final String linkWord3 = "think you!";
            String word = "Hello " + linkWord1 + "," + linkWord2 + " I'm fine," + linkWord3;
            SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(word);
            int index1 = word.indexOf(linkWord1);
            int index2 = word.indexOf(linkWord2);
            int index3 = word.indexOf(linkWord3);
            spannableStringBuilder.setSpan(new ClickableSpan() {
                @Override
                public void onClick(View widget) {
                    Toast.makeText(getActivity(), linkWord1, Toast.LENGTH_SHORT).show();
                }
    
                @Override
                public void updateDrawState(TextPaint ds) {
                    super.updateDrawState(ds);
                    ds.setColor(Color.RED);       //设置文件颜色
                    ds.setUnderlineText(true);      //设置下划线
                }
            }, index1, index1 + linkWord1.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    
            spannableStringBuilder.setSpan(new ClickableSpan() {
                @Override
                public void onClick(View widget) {
                    Toast.makeText(getActivity(), linkWord2, Toast.LENGTH_SHORT).show();
                }
    
                @Override
                public void updateDrawState(TextPaint ds) {
                    super.updateDrawState(ds);
                    ds.setColor(Color.GREEN);       //设置文件颜色
                    ds.setUnderlineText(true);      //设置下划线
                }
            }, index2, index2 + linkWord2.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    
            spannableStringBuilder.setSpan(new ClickableSpan() {
                @Override
                public void onClick(View widget) {
                    Toast.makeText(getActivity(), linkWord3, Toast.LENGTH_SHORT).show();
                }
    
                @Override
                public void updateDrawState(TextPaint ds) {
                    super.updateDrawState(ds);
                    ds.setColor(Color.BLUE);       //设置文件颜色
                    ds.setUnderlineText(false);      //设置下划线
                }
            }, index3, index3 + linkWord3.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            tv_tip.setTextSize(14);
            tv_tip.setText(spannableStringBuilder);
            tv_tip.setMovementMethod(LinkMovementMethod.getInstance());
    

    4. 多个可点击的超链接(html)

    当然还有另外一种方法,就是使用TextView显示 html格式的文本,然后处理其中的url,过程还是类似我们上面用到的方法,直接上代码吧:

           String html = "<p>
    " +
                    "   Hello <a href="/link/click1">Android</a>,<a href="/link/click2">Are you ok?</a>I'm fine,<a href="/link/click3">think you!</a>
    " +
                    " </p>";
    
            tv_tip.setText(Html.fromHtml(html));
            tv_tip.setMovementMethod(LinkMovementMethod.getInstance());
            CharSequence text = tv_tip.getText();
            if (text instanceof Spannable) {
                int end = text.length();
                Spannable sp = (Spannable) tv_tip.getText();
                URLSpan[] urls = sp.getSpans(0, end, URLSpan.class);
                SpannableStringBuilder style = new SpannableStringBuilder(text);
                style.clearSpans(); // should clear old spans
                for (final URLSpan url : urls) {
                    // 设置Span
                    style.setSpan(new ClickableSpan() {
                        @Override
                        public void onClick(View widget) {
                            Toast.makeText(getActivity(), url.getURL(), Toast.LENGTH_SHORT).show();
                        }
    
                        @Override
                        public void updateDrawState(TextPaint ds) {
                            super.updateDrawState(ds);
                            ds.setColor(Color.RED);       //设置文件颜色
                            ds.setUnderlineText(true);      //设置下划线
                        }
                    }, sp.getSpanStart(url), sp.getSpanEnd(url), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                }
                tv_tip.setText(style);
            }
    

    效果图:
    因为我把所有的连接都设置为红色,所以显示的都是红色,实际中可能进行处理,那时对每个url都进行处理即可。

    html实现

    这里我没有讲每个类的细节,因为我觉得,如果你知道类名,那么你可以查到对应的官方文档,官方文档对api的讲解是很详细的,但是官方很少会结合实际需求告诉你如何实现,可能某一个api你不熟悉你就无法和实际需求联想起来,希望看了 这篇文章想深入了解的可以从 CharSequence 接口(与上面的类紧密联系)进行展开。
    下一篇讲 TextView ImageSpan 实现文字图片混排。

  • 相关阅读:
    编程习俗和设计模式
    Design Patterns Quick Memo
    Monty Hall Problem
    RPG game: the lost Roman Army
    A Geeky Game Idea
    App自动化测试:等待webview页面数据加载完成
    Android自动化测试元素定位
    IOS苹果开发者免费证书申请&使用Xcode打包
    pytest测试夹具(fixture)简介
    Unittest与Pytest参数化区别
  • 原文地址:https://www.cnblogs.com/didikee/p/7851260.html
Copyright © 2020-2023  润新知