使字符串可点击,在 TextView 中加下划线

Make a string clickable, underlined in a TextView

我想使字符串 "this link" 带有下划线并可点击,但我不知道如何实现。

XML 文件:

<string name="submitText">Before you submit, please check out &lt;u>this link&lt;/u></string>

在我的片段中:

tvSubmit.setText(Html.fromHtml(getString(R.string.submitText)));

我不希望整个字符串都可以点击,只有带下划线的部分。我不能使用带有 2 个单元格的水平 LinearLayout,因为在较小的设备上,字符串不会有连续的外观,它将被分成 2 个单元格。

我尝试了什么:

tvSubmit.setMovementMethod(LinkMovementMethod.getInstance());
Spannable sp = (Spannable) tvSubmit.getText();
ClickableSpan click = new ClickableSpan() {
    @Override
    public void onClick(View widget) {
        showLink();
    }
};
sp.setSpan(click, 0, sp.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

上面的代码使整个字符串都带有下划线,并且文本的颜色也变成了浅蓝色。

你可以试试下面的代码..

String str = "Before you submit, please check out this link";
tvSubmit.setMovementMethod(LinkMovementMethod.getInstance());
tvSubmit.setText(setClickablePart(str), BufferType.SPANNABLE);

使用以下方法处理 Textview 中的点击事件

 private SpannableStringBuilder setClickablePart(String str)
    {
        SpannableStringBuilder m_spannableStringBuilder = new SpannableStringBuilder(str);

        int m_index = str.indexOf("this");

        final String clickString = str.substring(m_index, str.length());
        m_spannableStringBuilder.setSpan(new ClickableSpan()
        {
            @Override
            public void onClick(View widget)
            {
                Toast.makeText(MainActivity.this, clickString, Toast.LENGTH_SHORT).show();
            }
        }, m_index, str.length(), 0);

        return m_spannableStringBuilder;
    }

您可以在 strings.xml

中定义
<string name="submitText">Before you submit, please check out <a href="actual url">this link</a>
 <TextView  
       android:id="@+id/tvSubmit"  
       android:layout_width="wrap_content"  
       android:layout_height="wrap_content"  
       android:layout_alignParentTop="true"  
       android:autoLink=@String/submitText //link the content of web  
       android:textColorLink="#576586" //change the color of the link  
       android:textColor="#555555" />

在activity //样本

String webLinkText = <a href="https://prativas.files.wordpress.com/2013/05/screenshot-mozilla-firefox-private-browsing.png"><img src="https://prativas.files.wordpress.com/2013/05/screenshot-mozilla-firefox-private-browsing.png" alt="Screenshot-Mozilla Firefox (Private Browsing)" width="293" height="254" class="alignnone size-full wp-image-291" /></a>  
 tvSubmit = (TextView) findViewById(R.id.tvSubmit);  
 tvSubmit.setText(Html.fromHtml(webLinkText))); 

在此处查看 for more detailed answer

问题是您将跨度设置为整个字符串 (sp.setSpan(click, 0, sp.length())。要解决此问题,您必须仅在 this link 上设置可点击范围。我用这种方式做了同样的事情:

<string name="submitText">Before you submit, please check out %1$s</string>
<string name="this_link">this link</string>

在你的 Activity

String thisLink = getString(R.string.thisLink);
String yourString = getString(R.string.submitText, thisLink);
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(yourString);
spannableStringBuilder.setSpan(click,
                startIndex, endIndex, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

其中 startIndex 和 endIndex 是 thisLinkyourString 中的索引。我将这两个字符串分开是因为这样更容易查找索引,尤其是当您必须处理翻译时。要计算 startIndex,您可以使用 yourString.indexOf(thisLink),endIndex 是 startIndex + the length of thisLink。我会把普通支票留给你,(负索引,以及所有其他可能导致 IndexOutBoundException

sp.setSpan(click, 0, sp.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

更改值 0:在文本中的位置开始 link,示例更改值:10 如果你设置 0 它将超link所有文本。

刚刚创建了这个功能来帮助我将可点击的文本附加到文本视图:

public static SpannableStringBuilder getSpannablableClickFor(CharSequence initialText, ClickableSpan click, String textToAppend) {
    String description = String.format("%s %s", initialText, textToAppend);
    SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(description);
    int start = description.indexOf(textToAppend);
    int end = start + textToAppend.length();
    spannableStringBuilder.setSpan(click,
            start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    spannableStringBuilder.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    spannableStringBuilder.setSpan(new UnderlineSpan(), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    final ForegroundColorSpan fcs = new ForegroundColorSpan(Color.WHITE);
    spannableStringBuilder.setSpan(fcs, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    return spannableStringBuilder;
}

您可以尝试使用 Kotlin 扩展功能来创建类似文本且可点击的下划线。

fun TextView.colorSpannableStringWithUnderLineOne(
    prefixString: String,
    postfixString: String,
    callback: (Int) -> Unit
) {
    val spanTxt = SpannableStringBuilder()
    spanTxt.append("$prefixString ")
    spanTxt.append(" $postfixString")
    spanTxt.setSpan(object : ClickableSpan() {
        override fun onClick(widget: View) {
            callback(0)
            widget.invalidate()
        }

        override fun updateDrawState(ds: TextPaint) {
            ds.color = ContextCompat.getColor(context, R.color.highlight)
            ds.isUnderlineText = true
        }
    }, prefixString.length, spanTxt.length, 0)
    this.movementMethod = LinkMovementMethod.getInstance()
    this.setText(spanTxt, TextView.BufferType.SPANNABLE)
}

`

如何使用:

textViewLink.colorSpannableStringWithUnderLineOne(
                "Normal string",
                "Clickable string",
                callback = {
                    JLog.e("==>","Clicked")
                })
  textViewLink.invalidate()

在我的例子中,我需要一个本地化的字符串,其中的一部分是可点击的。 我所做的是在我的资源中定义一个字符串(每个区域设置一个),其中可点击部分带有下划线,如下所示:

<string name="my_message">Blah blah blah <u>call us</u> blah blah.</string>

然后我创建了一个扩展来查找带下划线的文本并在其上添加可点击范围,如下所示:

fun CharSequence.makeUnderlineClickable(listener: (index: Int) -> Unit): SpannableString {
    val spannedString = SpannableString(this)
    spannedString.getSpans(0, length, UnderlineSpan::class.java)?.forEachIndexed { index, underlineSpan ->
        val clickableSpan = object : ClickableSpan() {
            override fun onClick(widget: View) {
                listener.invoke(index)
            }

            override fun updateDrawState(ds: TextPaint) {
                ds.isUnderlineText = true
            }
        }
        spannedString.setSpan(
            clickableSpan,
            spannedString.getSpanStart(underlineSpan),
            spannedString.getSpanEnd(underlineSpan),
            Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
        )
    }
    return spannedString 
}

你可以这样使用它:

    textView.text = resources.getText(R.string.my_message).makeUnderlineClickable { index ->
        //handle click here
    }
    textView.movementMethod = LinkMovementMethod.getInstance()
    textView.highlightColor = Color.TRANSPARENT