我有文本“Android是一个软件堆栈”。在这个文本中,我想设置“堆栈”文本为可点击。所以,如果你点击它,它将重定向到一个新的活动(不在浏览器中)。

我试过了,但没有找到解决办法。


当前回答

对于kotlin使用这个扩展

fun TextView.makeLinks(vararg links: Pair<String, View.OnClickListener>) {
val spannableString = SpannableString(this.text)
for (link in links) {
    val clickableSpan = object : ClickableSpan() {
        override fun onClick(view: View) {
            Selection.setSelection((view as TextView).text as Spannable, 0)
            view.invalidate()
            link.second.onClick(view)
        }
    }
    val startIndexOfLink = this.text.toString().indexOf(link.first)
    spannableString.setSpan(
        clickableSpan, startIndexOfLink, startIndexOfLink + link.first.length,
        Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
    )
    spannableString.setSpan(
        ForegroundColorSpan(Color.parseColor("#46C2CC")),
        startIndexOfLink,
        startIndexOfLink + link.first.length,
        Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
    )
}
this.movementMethod =
    LinkMovementMethod.getInstance() // without LinkMovementMethod, link can not click
this.setText(spannableString, TextView.BufferType.SPANNABLE)

}

像这样调用它

binding.agreeText.makeLinks(Pair(getString(R.string.terms_conditionsClick),View.OnClickListener {
        startActivity(TermsAndConditionActivity.getIntent(this))
    }))

其他回答

我的功能使TextView内的多个链接 更新2020:现在这个函数能够支持多个相同的文本链接在1 TextView,但记得把链接在正确的顺序

fun TextView.makeLinks(vararg links: Pair<String, View.OnClickListener>) {
    val spannableString = SpannableString(this.text)
    var startIndexOfLink = -1
    for (link in links) {
        val clickableSpan = object : ClickableSpan() {
            override fun updateDrawState(textPaint: TextPaint) {
                // use this to change the link color
                textPaint.color = textPaint.linkColor
                // toggle below value to enable/disable
                // the underline shown below the clickable text
                textPaint.isUnderlineText = true
            }

            override fun onClick(view: View) {
                Selection.setSelection((view as TextView).text as Spannable, 0)
                view.invalidate()
                link.second.onClick(view)
            }
        }
        startIndexOfLink = this.text.toString().indexOf(link.first, startIndexOfLink + 1)
//      if(startIndexOfLink == -1) continue // todo if you want to verify your texts contains links text
        spannableString.setSpan(
            clickableSpan, startIndexOfLink, startIndexOfLink + link.first.length,
            Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
        )
    }
    this.movementMethod =
        LinkMovementMethod.getInstance() // without LinkMovementMethod, link can not click
    this.setText(spannableString, TextView.BufferType.SPANNABLE)
}

使用

my_text_view.makeLinks(
        Pair("Terms of Service", View.OnClickListener {
            Toast.makeText(applicationContext, "Terms of Service Clicked", Toast.LENGTH_SHORT).show()
        }),
        Pair("Privacy Policy", View.OnClickListener {
            Toast.makeText(applicationContext, "Privacy Policy Clicked", Toast.LENGTH_SHORT).show()
        }))

XML

<TextView
    android:id="@+id/my_text_view"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Please accept Terms of Service and Privacy Policy"
    android:textColorHighlight="#f00" // background color when pressed
    android:textColorLink="#0f0"
    android:textSize="20sp" />

DEMO

参考

解决方案清除链接高亮选择遵循https://stackoverflow.com/a/19445108/5381331

创建优雅的Kotlin方式与扩展:

fun TextView.setClickableText(text: Spanned,
                              clickableText: String,
                              @ColorInt clickableColor: Int,
                              clickListener: () -> Unit) {
    val spannableString = SpannableString(text)

    val startingPosition: Int = text.indexOf(clickableText)

    if (startingPosition > -1) {
        val clickableSpan: ClickableSpan = object : ClickableSpan() {
            override fun onClick(textView: View) {
                clickListener()
            }

            override fun updateDrawState(textPaint: TextPaint) {
                super.updateDrawState(textPaint)
                textPaint.isUnderlineText = false
            }
        }

        val endingPosition: Int = startingPosition + clickableText.length
        spannableString.setSpan(clickableSpan, startingPosition,
                endingPosition, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
        spannableString.setSpan(ForegroundColorSpan(clickableColor), startingPosition,
                endingPosition, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
        movementMethod = LinkMovementMethod.getInstance()
        highlightColor = Color.TRANSPARENT
    }

    setText(spannableString)
}

我编写了一个例子来解决你的问题在Kotlin。

这是准则:

    val completeText = getString(R.string.terms_description)
    val textToFind = getString(R.string.show_terms)
    val spannableString: Spannable = SpannableString(completeText)
    val startFocus = completeText.indexOf(textToFind)
    val endFocus = startFocus + textToFind.length

    spannableString.setSpan(object: ClickableSpan() {
        override fun onClick(p0: View) {
            showMessage()
        }
    }, startFocus, endFocus, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
    show_terms.text = spannableString
    show_terms.movementMethod = LinkMovementMethod.getInstance();
    show_terms.highlightColor = Color.TRANSPARENT;

这是XML

    <CheckBox
            android:id="@+id/check_agree_terms"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

    <TextView
            android:id="@+id/show_terms"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textColorLink="@color/colorPrimary"
            android:layout_toEndOf="@id/check_agree_terms"/>

这就是它的样子

在这里输入图像描述

它对文本的某些部分的可点击部分非常有帮助。

点是正则表达式中的一个特殊字符。如果你想要分隔圆点,需要将圆点转义为\\。而不是仅仅将"."传递给可扩展的文本方法。或者,也可以使用正则表达式[。在Java中通过一个点来分隔字符串。

这是java爱好者的Boom Check:D 我们可以根据自己的需要进行修改:

List<Pair<String, View.OnClickListener>> pairsList = new ArrayList<>();

        pairsList.add(new Pair<>("38,50", v -> {
            Intent intent = new Intent(SignUpActivity.this, WebActivity.class);
            intent.putExtra("which", "tos");
            startActivity(intent);
        }));

        pairsList.add(new Pair<>("81,95", v -> {
            Intent intent = new Intent(SignUpActivity.this, WebActivity.class);
            intent.putExtra("which", "policy");
            startActivity(intent);
        }));

        makeLinks(pairsList); // Method calling


private void makeLinks(List<Pair<String, View.OnClickListener>> pairsList) {

        SpannableString ss = new SpannableString(By signing up, I’m agree to PAKRISM’s Terms of Use and confirms that I have read Privacy Policy);

        for (Pair<String, View.OnClickListener> pair : pairsList) {

            ClickableSpan clickableSpan = new ClickableSpan() {
                @Override
                public void onClick(View textView) {
                    //Toast.makeText(MyApplication.getAppContext(), "Clicked!", Toast.LENGTH_SHORT).show();
                    pair.second.onClick(textView);
                }

                @Override
                public void updateDrawState(TextPaint ds) {

                    ds.linkColor = ContextCompat.getColor(SignUpActivity.this, R.color.primary_main);
                    ds.setUnderlineText(true);

                    super.updateDrawState(ds);
                }
            };

            String[] indexes = pair.first.split(",");
            ss.setSpan(clickableSpan, Integer.parseInt(indexes[0]), Integer.parseInt(indexes[1]), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        }
        
        TextView tv = findViewById(R.id.txtView);
        tv.setText(ss);
        tv.setMovementMethod(LinkMovementMethod.getInstance());
    }