我有文本“Android是一个软件堆栈”。在这个文本中,我想设置“堆栈”文本为可点击。所以,如果你点击它,它将重定向到一个新的活动(不在浏览器中)。
我试过了,但没有找到解决办法。
我有文本“Android是一个软件堆栈”。在这个文本中,我想设置“堆栈”文本为可点击。所以,如果你点击它,它将重定向到一个新的活动(不在浏览器中)。
我试过了,但没有找到解决办法。
当前回答
创建优雅的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)
}
其他回答
它对文本的某些部分的可点击部分非常有帮助。
点是正则表达式中的一个特殊字符。如果你想要分隔圆点,需要将圆点转义为\\。而不是仅仅将"."传递给可扩展的文本方法。或者,也可以使用正则表达式[。在Java中通过一个点来分隔字符串。
这里有一个Kotlin解决方案,与本地化工作得更好:
data class LinkedText(@StringRes val textRes: Int, val clickListener: View.OnClickListener? = null)
fun TextView.setPartiallyLinkedText(vararg texts: LinkedText) {
this.text = texts.joinToString(" ") { context.getString(it.textRes) }
val spannableString = SpannableString(this.text)
var startIndexOfLink = -1
texts.forEach { text ->
val string = context.getString(text.textRes)
if (text.clickListener != null) {
val clickableSpan = object : ClickableSpan() {
override fun updateDrawState(textPaint: TextPaint) {
textPaint.color = textPaint.linkColor
textPaint.isUnderlineText = true
}
override fun onClick(view: View) {
Selection.setSelection((view as TextView).text as Spannable, 0)
view.invalidate()
text.clickListener.onClick(view)
}
}
startIndexOfLink = this.text.toString().indexOf(string, startIndexOfLink + 1)
spannableString.setSpan(
clickableSpan, startIndexOfLink, startIndexOfLink + string.length,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
)
}
}
this.movementMethod = LinkMovementMethod.getInstance()
this.setText(spannableString, TextView.BufferType.SPANNABLE)
}
像这样使用它:
textView.setPartiallyLinkedText(
LinkedText(R.string.not_linked_text),
LinkedText(R.string.linked_text) {
Toast.makeText(context, "You clicked", Toast.LENGTH_LONG).show()
},
)
提供的解决方案相当不错。然而,我通常使用更简单的解决方案。
这是一个linkify效用函数
/**
* Method is used to Linkify words in a TextView
*
* @param textView TextView who's text you want to change
* @param textToLink The text to turn into a link
* @param url The url you want to send the user to
*/
fun linkify(textView: TextView, textToLink: String, url: String) {
val pattern = Pattern.compile(textToLink)
Linkify.addLinks(textView, pattern, url, { _, _, _ -> true })
{ _, _ -> "" }
}
使用这个函数非常简单。这里有一个例子
// terms and privacy
val tvTerms = findViewById<TextView>(R.id.tv_terms)
val tvPrivacy = findViewById<TextView>(R.id.tv_privacy)
Utils.linkify(tvTerms, resources.getString(R.string.terms),
Constants.TERMS_URL)
Utils.linkify(tvPrivacy, resources.getString(R.string.privacy),
Constants.PRIVACY_URL)
您可以使用示例代码。您希望了解关于ClickableSpan的详细信息。请检查这份文件
SpannableString myString = new SpannableString("This is example");
ClickableSpan clickableSpan = new ClickableSpan() {
@Override
public void onClick(View textView) {
ToastUtil.show(getContext(),"Clicked Smile ");
}
};
//For Click
myString.setSpan(clickableSpan,startIndex,lastIndex,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
//For UnderLine
myString.setSpan(new UnderlineSpan(),startIndex,lastIndex,0);
//For Bold
myString.setSpan(new StyleSpan(Typeface.BOLD),startIndex,lastIndex,0);
//Finally you can set to textView.
TextView textView = (TextView) findViewById(R.id.txtSpan);
textView.setText(myString);
textView.setMovementMethod(LinkMovementMethod.getInstance());
我会建议一种不同的方法,我认为这种方法需要更少的代码,而且更“本地化友好”。
假设你的目标活动被称为“ActivityStack”,在manifest中定义一个意图过滤器,使用一个自定义的方案(例如。“myappscheme”)
<activity
android:name=".ActivityStack">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:host="stack"/>
<data android:scheme="myappscheme" />
</intent-filter>
</activity>
定义没有任何特殊标签的TextView(重要的是不要使用"android:autoLink"标签,参见:https://stackoverflow.com/a/20647011/1699702):
<TextView
android:id="@+id/stackView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/stack_string" />
然后在TextView的文本中使用带有自定义方案和主机的链接作为(在String.xml中):
<string name="stack_string">Android is a Software <a href="myappscheme://stack">stack</a></string>
和“激活”与setMovementMethod()(在onCreate()的活动或onCreateView()的片段链接):
TextView stack = findViewById(R.id.stackView);
stack.setMovementMethod(LinkMovementMethod.getInstance());
这将通过点击“stack”字打开堆栈活动。