Android 實現TextView的部分文字和網絡連接及電話號碼點擊監聽

前言

最近在寫項目的時候遇到了一個這樣的需求,要像qq同樣,點擊評論的者的名字要跳轉評論者的用戶信息界面,而且點擊評論信息中的web連接要跳轉到WebActivity,同時若是是其餘數字的話要像qq同樣點擊並顯示底部Dialog提示是播打電話仍是複製號碼。android

效果

先給你們看看效果web

image

下面的評論由一個TextView顯示,其實顯示爲淡藍的都是能夠點擊的區域。bash

思路

由於沒作過確定是先百度瞭解一下,大部分的處理都是先設置TextView的autolink,而後系統會給你判斷TextView中是否能夠匹配到連接。而後經過SpannableStringBuilder來設置點擊事件,當百度的部分有限,只能瞭解到web連接的點擊事件監聽,因此我在此基礎上並綜合直接給TextView設置部分點擊的知識作了一些嘗試,可是出現了一些問題,就是當autolink設置的過濾在TextView中的文字中沒有匹配到的時候不能獲取到Spannable對象。我就本身new了一個,可是卻不能處罰點擊事件,最後找到了一個TextViewtv.setMovementMethod(LinkMovementMethod.getInstance());方法,設置以後才能觸發點擊事件。ide

實現步驟

首先給你的TextView設置autoLink屬性 以下佈局

android:autoLink="all"
複製代碼

而後實現一個初始化web和數字連接點擊的監聽,以下ui

public static SpannableStringBuilder getWebLinkStyle(CharSequence text, Context context) {
    if (text instanceof Spannable) {
      int end = text.length();
      Spannable sp = (Spannable) text;
      URLSpan urls[] = sp.getSpans(0, end, URLSpan.class);
      SpannableStringBuilder style = new SpannableStringBuilder(text);
      style.clearSpans();
      for (URLSpan urlSpan : urls) {
        ClickableSpan myURLSpan = new ClickableSpan() {
          @Override
          public void onClick(@NonNull View view) {
            if (urlSpan.getURL().startsWith("http")) {
              WebActivity.startWebBrowsing(context, urlSpan.getURL(), "");
            } else {
              String number = urlSpan.getURL();
              if (number.contains(":")) {
                number = number.split[1](":");
              }
              showBottomSheetDialog(context, number);
            }
          }
        };
        style.setSpan(myURLSpan, sp.getSpanStart(urlSpan),
            sp.getSpanEnd(urlSpan),
            Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
      }
      return style;
    }
    return null;
  }

 public static void showBottomSheetDialog(Context context, final String number) {
    BottomSheetDialog dialog = new BottomSheetDialog(context);
    View dialogView = LayoutInflater.from(context).inflate(R.layout.dialog_bottom, null);
    TextView tvTitle = dialogView.findViewById(R.id.tv_title);
    tvTitle.setText(String.format("%s\n多是一個電話號碼或者其餘聯繫方式,你能夠", number));
    TextView tvCall = dialogView.findViewById(R.id.tv_call);
    tvCall.setOnClickListener(view -> {
      Intent dialIntent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + number));
      context.startActivity(dialIntent);
      dialog.dismiss();
    });
    TextView tvCopty = dialogView.findViewById(R.id.tv_copy);
    tvCopty.setOnClickListener(view -> {
      ClipboardManager copy =
          (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
      copy.setText(number);
      dialog.dismiss();
      ToastHelper.toast("已複製到剪切板");
    });
    TextView tvCancel = dialogView.findViewById(R.id.tv_cancel);
    tvCancel.setOnClickListener(view -> dialog.dismiss());
    dialog.setContentView(dialogView);
    dialog.show();
  }
複製代碼

從這個代碼裏面能夠看到text instanceof Spannable成立的時候即TextView中包含符合autolink過濾的連接。咱們能夠經過URLSpan來找到對應的連接。而後判斷是否爲web連接和數字,若是是數字的話顯示彈窗,提示打電話或者複製。代碼以下,同理若是不成立則說明TextView不包含autolink過濾的連接。只能返回null,須要新建一個。 接下來就是評論用戶設置點擊事件了。TextPositionBean是記錄每個評論者用戶名在TextView文字中開始和結束的位置,由於在給每一個評論者名字加上點擊事件時須要給定點擊文字的範圍。style.setSpan(clickableSpan,textPositionBean.getStart(),textPositionBean.getEnd(),Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);這其中getStart()和getEnd()就肯定了點擊文字的範圍。url

代碼以下spa

SpannableStringBuilder style = UiHelper.getWebLinkStyle(tvCommentInfo.getText(),context);
    if (style == null){
      style = new SpannableStringBuilder(stringBuilder.toString());
    }
    for (TextPositionBean<String> textPositionBean : textPositionBeans) {
      ClickableSpan clickableSpan = new ClickableSpan() {
        @Override
        public void onClick(@NonNull View view) {
          UserInfoActivity.goToUserInfoActivity(context,textPositionBean.getData());
        }
      };
      style.setSpan(clickableSpan,textPositionBean.getStart(),textPositionBean.getEnd(),Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
      tvCommentInfo.setMovementMethod(LinkMovementMethod.getInstance());
    }
    tvCommentInfo.setText(style);
複製代碼

當不存在過濾條件的時候,我就本身手動獲取一個,而後根據以前紀錄的評論用戶的用戶名出現的位置,來添加點擊事件,而且激活點擊響應。便可3d

若是須要BottomSheetDialog的佈局文件可看以下代碼code

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  android:orientation="vertical"
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent">

  <TextView
    android:id="@+id/tv_title"
    android:gravity="center"
    android:textColor="#a9a8a8"
    android:textSize="12sp"
    android:layout_width="match_parent"
    android:layout_height="50dp" />

  <View
    android:background="#e6e6e6"
    android:layout_width="match_parent"
    android:layout_height="0.3dp"/>

  <TextView
    android:id="@+id/tv_call"
    android:text="@string/call"
    android:gravity="center"
    android:textColor="@color/front_black"
    android:textSize="16sp"
    android:layout_width="match_parent"
    android:layout_height="50dp" />

  <View
    android:background="#e6e6e6"
    android:layout_width="match_parent"
    android:layout_height="0.3dp"/>

  <TextView
    android:id="@+id/tv_copy"
    android:text="@string/copy"
    android:gravity="center"
    android:textColor="@color/front_black"
    android:textSize="16sp"
    android:layout_width="match_parent"
    android:layout_height="50dp" />

  <View
    android:background="#dfdfdf"
    android:layout_width="match_parent"
    android:layout_height="10dp"/>
  <TextView
    android:id="@+id/tv_cancel"
    android:text="@string/cancel"
    android:gravity="center"
    android:textColor="@color/front_black"
    android:textSize="16sp"
    android:layout_width="match_parent"
    android:layout_height="50dp" />

</LinearLayout>
複製代碼

有興趣的朋友能夠留言討論哦

相關文章
相關標籤/搜索