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

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


当前回答

这是一个Kotlin方法,使TextView的部分可点击:

private fun makeTextLink(textView: TextView, str: String, underlined: Boolean, color: Int?, action: (() -> Unit)? = null) {
    val spannableString = SpannableString(textView.text)
    val textColor = color ?: textView.currentTextColor
    val clickableSpan = object : ClickableSpan() {
        override fun onClick(textView: View) {
            action?.invoke()
        }
        override fun updateDrawState(drawState: TextPaint) {
            super.updateDrawState(drawState)
            drawState.isUnderlineText = underlined
            drawState.color = textColor
        }
    }
    val index = spannableString.indexOf(str)
    spannableString.setSpan(clickableSpan, index, index + str.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
    textView.text = spannableString
    textView.movementMethod = LinkMovementMethod.getInstance()
    textView.highlightColor = Color.TRANSPARENT
}

它可以被多次调用,在TextView中创建几个链接:

makeTextLink(myTextView, str, false, Color.RED, action = { Log.d("onClick", "link") })
makeTextLink(myTextView, str1, true, null, action = { Log.d("onClick", "link1") })

其他回答

这是一个kotlin扩展(不工作,如果文本重复)

textView.makeTextClickable(
    contentText = "Hello world",
    clickableText = "world",
    isBoldText = true,
    onClick = {
        openPageInBrowser(BuildConfig.PRIVACY_POLICY_URL)
    }
)



   internal fun TextView.makeTextClickable(
    contentText: String,
    clickableText: String,
    onClick: () -> Unit,
    isUnderlineText: Boolean = false,
    isBoldText: Boolean = false
) {
    val spannableString = SpannableString(contentText)

    val clickableSpan = object : ClickableSpan() {
        override fun onClick(widget: View) {
            onClick()
        }

        override fun updateDrawState(ds: TextPaint) {
            super.updateDrawState(ds)
            ds.isUnderlineText = isUnderlineText
            ds.isFakeBoldText = isBoldText
        }
    }

    val clickableTextStartIndex = text.indexOf(clickableText)
    val clickableTextEndIndex = clickableTextStartIndex + clickableText.length

    spannableString.setSpan(
        clickableSpan,
        clickableTextStartIndex,
        clickableTextEndIndex,
        Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
    )

    this.text = spannableString
    this.movementMethod = LinkMovementMethod.getInstance()
}

kotlin中更通用的答案

   fun setClickableText(view: TextView, firstSpan: String, secondSpan: String) {
    val context = view.context
    val builder = SpannableStringBuilder()
    val unClickableSpan = SpannableString(firstSpan)
    val span = SpannableString(" "+secondSpan)

    builder.append(unClickableSpan);
    val clickableSpan: ClickableSpan = object : ClickableSpan() {
        override fun onClick(textView: View) {
            val intent = Intent(context, HomeActivity::class.java)
         context.startActivity(intent)
        }

        override fun updateDrawState(ds: TextPaint) {
            super.updateDrawState(ds)
            ds.isUnderlineText = true
            ds.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.ITALIC));
        }
    }
    builder.append(span);
    builder.setSpan(clickableSpan, firstSpan.length, firstSpan.length+secondSpan.length+1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)

    view.setText(builder,TextView.BufferType.SPANNABLE)
    view.setMovementMethod(LinkMovementMethod.getInstance());


}

Phan Van Linh回答的版本。

请注意它有一些小的改动。

fun makeLinks(textView: TextView, links: Array<String>, clickableSpans: Array<ClickableSpan>) {
    val spannableString = SpannableString(textView.text)

    for (i in links.indices) {
        val clickableSpan = clickableSpans[i]
        val link = links[i]

        val startIndexOfLink = textView.text.indexOf(link)

        spannableString.setSpan(clickableSpan, startIndexOfLink, startIndexOfLink + link.length,
                Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
    }

    textView.movementMethod = LinkMovementMethod.getInstance()
    textView.setText(spannableString, TextView.BufferType.SPANNABLE)
}

fun setupClickableTextView() {
    val termsOfServicesClick = object : ClickableSpan() {
        override fun onClick(p0: View?) {
            Toast.makeText(applicationContext, "ToS clicked", Toast.LENGTH_SHORT).show()
        }
    }

    val privacyPolicyClick = object : ClickableSpan() {
        override fun onClick(p0: View?) {
            Toast.makeText(applicationContext, "PP clicked", Toast.LENGTH_SHORT).show()
        }
    }

    makeLinks(termsTextView, arrayOf("terms", "privacy policy"), arrayOf(termsOfServicesClick, privacyPolicyClick))
}

对于那些正在寻找Kotlin解决方案的人来说,这里是对我有用的:

private fun setupTermsAndConditions() {
    val termsAndConditions = resources.getString(R.string.terms_and_conditions)
    val spannableString = SpannableString(termsAndConditions)
    val clickableSpan = object : ClickableSpan() {
        override fun onClick(widget: View) {
            if (checkForWifiAndMobileInternet()) {
                // binding.viewModel!!.openTermsAndConditions()
                showToast("Good, open the link!!!")

            } else {
                showToast("Cannot open this file because of internet connection!")
            }

        }

        override fun updateDrawState(textPaint : TextPaint) {
            super.updateDrawState(textPaint)
            textPaint.color = resources.getColor(R.color.colorGrey)
            textPaint.isFakeBoldText = true
        }
    }

    spannableString.setSpan(clickableSpan, 34, 86, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
    binding.tvTermsAndConditions.text = spannableString
    binding.tvTermsAndConditions.movementMethod = LinkMovementMethod.getInstance()
    binding.tvTermsAndConditions.setHighlightColor(Color.TRANSPARENT);

}

大胆的,

mySpannable.setSpan(new StyleSpan(Typeface.BOLD),termStart,termStop,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);