Android TextView 点击超链接跳转实现

简介: 前提:之前遇到过一次textview显示url的方式,但是并未深入探究。但是,上个礼拜一个朋友问我如何在textview上面加载url,并且点击跳转到指定页面。

前提:之前遇到过一次textview显示url的方式,但是并未深入探究。但是,上个礼拜一个朋友问我如何在textview上面加载url,并且点击跳转到指定页面。当时对这个比较感兴趣也就深入探究了一番。虽然实现了,但是效果并不理想。如果哪位看官对这一点,理解的比较深入,请告诉我一声,谢谢了。

首先

  • 对TextView属性比较熟悉的开发者应该都知道TextView有一个叫做autoLink的属性,可以将符合指定格式的文本转换为可单击的超链接形式,在帮助文档中也可以发现Android给我们提供了如下几种格式:

1、none:表示不进行任何匹配,默认;
2、Web:表示匹配Web Url, 如: 连接地址为http://www.baidu.com会成为可单击跳转的超链接;
3、Email:表示匹配邮件地址, 如:邮件地址为xx@sina.com会成为可单击的超链接;
4、Phone:表示匹配电话号码,如:点击号码10000会跳到拨号界面;
5、Map:表示匹配地图地址;
6、All:表示将会匹配web、email、phone、map;

如下图所示

img_9cb4ad049623ebe85f647189ae2a0d43.png
TextView autoLink.png

 <TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:layout_margin="16dp"
    android:text="123"
    android:autoLink="phone"/>
  • 其中android:autoLink=" "就是加载的属性

其次

  • 要实现点击textview中url的跳转到指定功能页面的功能,有这样两种功能

1、直接跳转到指定页面(可以直接自定义页面);
2、通过手机浏览器到指定页面

首先,来看跳转到指定页面的写法

  public class MainActivity extends AppCompatActivity {

  TextView mTxtWeb;
  CharSequence mContent;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    initView();
  }

  /**
   * 初始化控件
   */
  private void initView() {
    mTxtWeb = (TextView) findViewById(R.id.txt_web);
    String htmlLinkText = "天下"+"www.google.com"+"为公";
    mTxtWeb.setText(Html.fromHtml(htmlLinkText));
    mTxtWeb.setMovementMethod(LinkMovementMethod.getInstance());
    CharSequence text = mTxtWeb.getText();
    if (text instanceof Spannable) {
        int end = text.length();
        Spannable sp = (Spannable) mTxtWeb.getText();
        URLSpan[] urls = sp.getSpans(0, end, URLSpan.class);
        SpannableStringBuilder style = new SpannableStringBuilder(text);
        style.clearSpans();
        for (final URLSpan url : urls) {
              //最主要的一点
            CustomClickUrlSpan myURLSpan = new CustomClickUrlSpan(url.getURL(), new CustomClickUrlSpan.OnLinkClickListener() {
                @Override
                public void onLinkClick(View view) {
                    Intent intent= new Intent(this,WebActivity.class);
                    intent.putExtra("url",url.getURL());
                    startActivity(intent);
                }
            });
            style.setSpan(myURLSpan, sp.getSpanStart(url), sp.getSpanEnd(url), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        }
        mTxtWeb.setText(style);
    }
   }
  • 其中CustomClickUrlSpan,是点击url跳转,其中传入一个url,一个自定义接口,达到跳转到指定页面的目的。

     public class CustomClickUrlSpan extends ClickableSpan {
     private String url;
     private OnLinkClickListener mListener;
    
     public CustomClickUrlSpan(String url, OnLinkClickListener listener) {
      this.url=url;
      this.mListener=listener;
    }
    
     @Override
    public void onClick(View widget) {
      if (mListener!=null){
          mListener.onLinkClick(widget);
      }
     }
    
    /**
     * 跳转链接接口
     */
    public interface OnLinkClickListener{
      void onLinkClick(View view);
    }
     }
    
  • 其中ClicableSpan是系统的方法,其中定义了一个抽象点击的方法(来看看系统源码)

    public abstract class ClickableSpan extends CharacterStyle implements UpdateAppearance {
     private static int sIdCounter = 0;
    
     private int mId = sIdCounter++;
    
    /**
     * Performs the click action associated with this span.
     * 这个是点击方法
     */
    public abstract void onClick(View widget);
    
    /**
     * Makes the text underlined and in the link color.
     */
    @Override
    public void updateDrawState(TextPaint ds) {
       //这个是设置url颜色
      ds.setColor(ds.linkColor);
       //这个是设置是否有下划线
      ds.setUnderlineText(true);
    }
    
    /**
     * Get the unique ID for this span.
     *
     * @return The unique ID.
     * @hide
     */
    public int getId() {
      return mId;
      }
    }
    
  • 当然也有简单的写法,比如:

    /**
     * 点击跳转
     */
    private class MyURLSpan extends ClickableSpan {
    
      private String mUrl;
    
      MyURLSpan(String url) {
          mUrl = url;
      }
    
      @Override
      public void onClick(View widget) {
          Toast.makeText(MainActivity.this, mContent.toString(), Toast.LENGTH_LONG).show();
      }
    }
    
  • 第二种用的内部类的方法,但是会有局限性,会让主页变得太繁琐,也会让跳转受限,为了让代码看着清晰简洁,所以推荐使用第一种方法。(个人理解,不对的还请指正)

其次,通过浏览器跳转到指定页面(并取消下划线)

public class CustomUrlSpan extends UnderlineSpan implements Parcelable {


String url;

public CustomUrlSpan(String url) {
    this.url = url;

}

@Override
public void updateDrawState(TextPaint ds) {
    super.updateDrawState(ds);
    if (ds != null) {
        ds.setUnderlineText(false);
    }
}


@Override
public int describeContents() {
    return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeString(this.url);
}

protected CustomUrlSpan(Parcel in) {
    super(in);
    this.url = in.readString();
}

public static final Creator<CustomUrlSpan> CREATOR = new Creator<CustomUrlSpan>() {
    public CustomUrlSpan createFromParcel(Parcel source) {
        return new CustomUrlSpan(source);
    }

    public CustomUrlSpan[] newArray(int size) {
        return new CustomUrlSpan[size];
    }
};
}
  • 一定要实现Parcelable接口,要不会有错误提示(下面是activity中的用法,其中通过浏览器跳转到指定页面,并且取消了下划线)。

    /**
     * 初始化控件
     */
    private void initView() {
      mTxtWeb = (TextView) findViewById(R.id.txt_web);
      String htmlLinkText = "天下"+"www.google.com"+"为公";
      mTxtWeb.setText(Html.fromHtml(htmlLinkText));
      mTxtWeb.setMovementMethod(LinkMovementMethod.getInstance());
      CharSequence text = mTxtWeb.getText();
      if (text instanceof Spannable) {
          int end = text.length();
          Spannable sp = (Spannable) mTxtWeb.getText();
          URLSpan[] urls = sp.getSpans(0, end, URLSpan.class);
          SpannableStringBuilder style = new SpannableStringBuilder(text);
          style.clearSpans();
          for (final URLSpan url : urls) {
              CustomUrlSpan myURLSpan = new CustomUrlSpan(url.getURL());
              style.setSpan(myURLSpan, sp.getSpanStart(url), sp.getSpanEnd(url), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
          }
          mTxtWeb.setText(style);
      }
    }
    

最后(还有一点比较困惑)

  • UnderlineSpan和ClickableSpan都有设置取消下划线的方法(updateDrawState),重写了方法之后,UnderlineSpan取消了下划线,但是ClickableSpan却取消不了这一点比较困惑。
  • 看源码可以看到UnderlineSpan和ClickableSpan都是继承CharacterStyle,并且有一个抽象方法updateDrawState(),那么直接继承CharacterStyle,然后再自定义一个跳转接口可否实现跳转到指定接口呢,经过试验之后还是会有些许不尽如人意。如果哪位仁兄对这一点比较了解,还请告诉我一声,不胜感激。

感悟

  • 对于我们来说,不管做什么事情应该尽自己最大努力去做好,事事都怕认真二字

  • 引用知乎上面的一段话就是:
    如果天空是黑暗的,那就摸黑生存;如果发出声音是危险的,那就保持沉默;如果自觉无力发光的,那就蜷伏于墙角。但不要习惯了黑暗就为黑暗辩护;不要为自己的苟且而得意;不要嘲讽那些比自己更勇敢热情的人们。我们可以卑微如尘土,不可扭曲如蛆虫。——季业

  • 推荐一个探讨技术的技术群(493180098)

相关文章
|
2月前
|
程序员 开发工具 Android开发
Android|WebView 禁止长按,限制非白名单域名的跳转层级
如何限制 WebView 仅域名白名单网址能随意跳转,并禁用长按选择文字。
42 2
|
3月前
|
Android开发 UED Kotlin
Android中如何跳转到Wi-Fi开关设置页
本文介绍如何在Android应用开发中使用隐式Intent引导用户至特定系统设置页面,如Wi-Fi设置页,并提供Kotlin代码示例。通过设置Intent的Action属性并检查设备兼容性,可轻松实现跳转功能,提升用户体验。此外,还列举了其他常用设置页面的Intent Action及注意事项。
90 15
|
2月前
|
XML 存储 Java
浅谈Android的TextView控件
浅谈Android的TextView控件
41 0
|
3月前
|
Android开发
Android经典实战之Textview文字设置不同颜色、下划线、加粗、超链接等效果
本文介绍了 `SpannableString` 在 Android 开发中的强大功能,包括如何在单个字符串中应用多种样式,如颜色、字体大小、风格等,并提供了详细代码示例,展示如何设置文本颜色、添加点击事件等,助你实现丰富文本效果。
289 3
|
4月前
|
存储 安全 物联网
Android经典实战之跳转到系统设置页面或其他系统应用页面大全
本文首发于公众号“AntDream”,关注获取更多技巧。文章总结了Android开发中跳转至系统设置页面的方法,包括设备信息、Wi-Fi、显示与声音设置等,并涉及应用详情与电池优化页面。通过简单的Intent动作即可实现,需注意权限与版本兼容性。每日进步,尽在“AntDream”。
449 2
|
4月前
|
Android开发 iOS开发
Android项目架构设计问题之将隐式跳转的逻辑进行抽象和封装如何解决
Android项目架构设计问题之将隐式跳转的逻辑进行抽象和封装如何解决
47 0
|
4月前
|
Android开发
AutoX——当Android中clickable属性显示为false,实际可点击的布局如何处理
AutoX——当Android中clickable属性显示为false,实际可点击的布局如何处理
63 0
|
6月前
|
安全 JavaScript 前端开发
kotlin开发安卓app,JetPack Compose框架,给webview新增一个按钮,点击刷新网页
在Kotlin中开发Android应用,使用Jetpack Compose框架时,可以通过添加一个按钮到TopAppBar来实现WebView页面的刷新功能。按钮位于右上角,点击后调用`webViewState?.reload()`来刷新网页内容。以下是代码摘要:
|
6月前
|
XML IDE 开发工具
13. 【Android教程】文本框 TextView
13. 【Android教程】文本框 TextView
114 2
|
5月前
|
Android开发
Android 开发中跳转到评论页面
Android 开发中跳转到评论页面
70 0