Span使用之文字高亮及点击事件

本文介绍了一种在Android应用中实现电话号码高亮显示及点击拨打电话的方法,利用SpannableStringBuilder和自定义ClickableSpan实现核心功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

由于工作上的需求,类似于淘宝京东在获取物流信息时电话号码高亮显示,并触摸和点击电话号码时跳转到拨打电话.刚开始一时没想到什么好的方法,最后通过查找资料,看到了Span完全能够实现需求,并且使用效果好的不行.话不多说先上效果图如下:

这里写图片描述

效果图如上,现在分析实现的核心代码如下:

 //初始化SpannableStringBuilder
        mSpannableStringBuilder = new SpannableStringBuilder(mContent);
        //初始化需要高亮显示的文字和对其设置点击事件
        SpannableStringBuilder spannableStringBuilder = initClickText(mSpannableStringBuilder, mContent);
         //把mSpannableStringBuilder设置给对应的文本控件
        mTv.setText(spannableStringBuilder);
 //对文本控件设置触摸事件,当触摸区域是电话号码时拨打电话
        mTv.setOnTouchListener((v, event) -> {
            boolean ret = false;
            CharSequence text = ((TextView) v).getText();
            Spannable stext = Spannable.Factory.getInstance().newSpannable(text);
            TextView widget = (TextView) v;
            int action = event.getAction();
            //根据点击判断是否在spannable对象上;
            if (action == MotionEvent.ACTION_UP
                    || action == MotionEvent.ACTION_DOWN) {
                int x = (int) event.getX();
                int y = (int) event.getY();
                x -= widget.getTotalPaddingLeft();
                y -= widget.getTotalPaddingTop();
                x += widget.getScrollX();
                y += widget.getScrollY();
                Layout layout = widget.getLayout();
                int line = layout.getLineForVertical(y);
                int off = layout.getOffsetForHorizontal(line, x);
                ClickableSpan[] link = stext.getSpans(off, off, ClickableSpan.class);
                if (link.length != 0) {
                    if (action == MotionEvent.ACTION_UP) {
                        link[0].onClick(widget);
                    }
                    ret = true;
                }
            }
            return ret;
        });
 /**
     *  获取文字中的电话号码 并高亮显示和设置点击事件
     * @param spannableStringBuilder
     * @param text 文字内容
     * @return
     */
    private SpannableStringBuilder initClickText(SpannableStringBuilder spannableStringBuilder, String text) {
        Pattern patternPhone = Pattern.compile("\\d{3}-\\d{8}|\\d{4}-\\d{7}|\\d{11}");
        Matcher matcherPhone = patternPhone.matcher(text);
        int start = 0;
        //遍历取出字符串中所有的符合条件的;
        while (matcherPhone.find(start)) {
            start = matcherPhone.end();
            spannableStringBuilder.setSpan(new ForegroundColorSpan(CommonUtils.getColor(this, R.color.colorPrimary)), matcherPhone.start(), matcherPhone.end(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
            spannableStringBuilder.setSpan(new MyUrlSpan(matcherPhone.group()), matcherPhone.start(),
                    matcherPhone.end(), Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
            if (start >= text.length()) {
                break;
            }
        }
        return spannableStringBuilder;

    }
/**
     * Span点击的实现类
     */
    private class MyUrlSpan extends ClickableSpan {
        private String mUrl;

        public MyUrlSpan(String url) {
            mUrl = url;
        }

        //点击链接下划线,弹出dialog,提示提电话,或者发短信;通用的dialog我上篇文章有介绍.
        @Override
        public void onClick(View widget) {
            CommonBaseDialog.showDialog(SpanActivity.this, R.layout.common_dialog)
                    .setText(R.id.title, getPhoneText(mUrl))
                    .setViewVisibility(R.id.content, View.GONE)
                    .setDialogLocation(Gravity.CENTER, 60, 0, 60, 0)
                    .setViewListener((dialog, viewId) -> {
                        switch (viewId) {
                            case R.id.confirm:
                                Intent intent = new Intent(Intent.ACTION_DIAL);
                                Uri data = Uri.parse("tel:" + mUrl);
                                intent.setData(data);
                                SpanActivity.this.startActivity(intent);
                            case R.id.cancel:
                                dialog.dismiss();
                                break;
                        }
                    }, R.id.cancel, R.id.confirm);


        }
    }

这样就完美的实现了上述的需求希望这篇文章对你有所帮助谢谢!!!!!!!!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值