如何设置部分文本视图可点击
Posted
技术标签:
【中文标题】如何设置部分文本视图可点击【英文标题】:How to set the part of the text view is clickable 【发布时间】:2012-05-28 15:30:36 【问题描述】:我有文本“Android 是一个软件堆栈”。在此文本中,我想设置“stack”文本是可点击的。从某种意义上说,如果您单击它将重定向到新活动(而不是在浏览器中)。
我试过了,但我没有。
【问题讨论】:
“我试过了,但我没有得到”我想知道你尝试了什么以及你失败的地方 【参考方案1】:android.text.style.ClickableSpan
可以解决你的问题。
SpannableString ss = new SpannableString("Android is a Software stack");
ClickableSpan clickableSpan = new ClickableSpan()
@Override
public void onClick(View textView)
startActivity(new Intent(MyActivity.this, NextActivity.class));
@Override
public void updateDrawState(TextPaint ds)
super.updateDrawState(ds);
ds.setUnderlineText(false);
;
ss.setSpan(clickableSpan, 22, 27, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
TextView textView = (TextView) findViewById(R.id.hello);
textView.setText(ss);
textView.setMovementMethod(LinkMovementMethod.getInstance());
textView.setHighlightColor(Color.TRANSPARENT);
在 XML 中:
<TextView
...
android:textColorLink="@drawable/your_selector"
/>
【讨论】:
你可以在一个文本视图中设置多个 ClickableSpan 对象吗? 是的,您可以将几个可点击的跨度设置为可跨度字符串。 要使颜色变为蓝色,您可以添加:ForegroundColorSpan fcs = new ForegroundColorSpan(Color.BLUE); ss.setSpan(fcs, 22, 27, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
这发生在我的案例中,将颜色从蓝色变为其他颜色。 在设置了可点击范围之后,在setSpan
中设置ForegroundColorSpan
。在 Clickable span 之前放置 Foreground,新颜色不会被反射。
感谢这一行 stextView.setMovementMethod(LinkMovementMethod.getInstance()); textView.setHighlightColor(Color.TRANSPARENT);【参考方案2】:
我在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_
android:layout_
android:text="Please accept Terms of Service and Privacy Policy"
android:textColorHighlight="#f00" // background color when pressed
android:textColorLink="#0f0"
android:textSize="20sp" />
演示
参考
清除链接高亮选择的解决方案关注https://***.com/a/19445108/5381331
【讨论】:
它运行良好。但是出现了一些奇怪的行为。我有一个以“政策”结尾的文本。 “。”在哪里将被 Clickable spannable 跳过。有没有人有同样的问题?这 ”。”仅当它是文本视图的结束字符时才被跳过。 很好的解决方案,但是如果有字符串的本地化(多语言应用程序),有人需要小心 @BlackBlind 你得到哪个错误?如果导入有问题,请正确导入。你也不应该把函数放在onCreate里面,把它放在外面 在重复链接的情况下,它总是返回第一个,因为此解决方案使用indexOf
谢谢!我的 java 等价物:gist.github.com/daler445/b7106b5c5ed431ecfb206afe98746bbe【参考方案3】:
您可以按照post 中的说明使用ClickableSpan
示例代码:
TextView myTextView = new TextView(this);
String myString = "Some text [clickable]";
int i1 = myString.indexOf("[");
int i2 = myString.indexOf("]");
myTextView.setMovementMethod(LinkMovementMethod.getInstance());
myTextView.setText(myString, BufferType.SPANNABLE);
Spannable mySpannable = (Spannable)myTextView.getText();
ClickableSpan myClickableSpan = new ClickableSpan()
@Override
public void onClick(View widget) /* do something */
;
mySpannable.setSpan(myClickableSpan, i1, i2 + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
Reference
【讨论】:
感谢@ImranRana,支持startIndex
和endIndex
逻辑。
使用 [] 计算起始索引和结束索引,是完美的方法,但也可以在文本中显示 []。我不想在文本中显示 []。【参考方案4】:
您可以使用示例代码。您想了解有关 ClickableSpan 的详细信息。请检查这个documentaion
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());
【讨论】:
【参考方案5】:我做了这个辅助方法,以防有人需要字符串的开始和结束位置。
public static TextView createLink(TextView targetTextView, String completeString,
String partToClick, ClickableSpan clickableAction)
SpannableString spannableString = new SpannableString(completeString);
// make sure the String is exist, if it doesn't exist
// it will throw IndexOutOfBoundException
int startPosition = completeString.indexOf(partToClick);
int endPosition = completeString.lastIndexOf(partToClick) + partToClick.length();
spannableString.setSpan(clickableAction, startPosition, endPosition,
Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
targetTextView.setText(spannableString);
targetTextView.setMovementMethod(LinkMovementMethod.getInstance());
return targetTextView;
这就是你如何使用它
private void initSignUp()
String completeString = "New to Reddit? Sign up here.";
String partToClick = "Sign up";
ClickableTextUtil
.createLink(signUpEditText, completeString, partToClick,
new ClickableSpan()
@Override
public void onClick(View widget)
// your action
Toast.makeText(activity, "Start Sign up activity",
Toast.LENGTH_SHORT).show();
@Override
public void updateDrawState(TextPaint ds)
super.updateDrawState(ds);
// this is where you set link color, underline, typeface etc.
int linkColor = ContextCompat.getColor(activity, R.color.blumine);
ds.setColor(linkColor);
ds.setUnderlineText(false);
);
【讨论】:
这更好,因为它考虑到本地化【参考方案6】:这是一个 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") )
【讨论】:
【参考方案7】: t= (TextView) findViewById(R.id.PP1);
t.setText(html.fromHtml("<bThis is normal text </b>" +
"<a href=\"http://www.xyz-zyyx.com\">This is cliclable text</a> "));
t.setMovementMethod(LinkMovementMethod.getInstance());
【讨论】:
你能解释一下你的答案吗?有解释的回答总是更好。我还编辑了您的代码 sn-p 格式不正确。 看起来链接将指向网页,而不是 OP 请求的活动。【参考方案8】:我会建议一种不同的方法,我认为它需要更少的代码并且更“本地化”。
假设您的目标活动名为“ActivityStack”,请在清单中为它定义一个意图过滤器,并在 AndroidManifest.xml 中使用自定义方案(例如“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://***.com/a/20647011/1699702):
<TextView
android:id="@+id/stackView"
android:layout_
android:layout_
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());
这将打开堆栈活动,点击“堆栈”一词。
【讨论】:
【参考方案9】:Kotlin 版本 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))
【讨论】:
【参考方案10】:你可以用这个方法来设置可点击值
public void setClickableString(String clickableValue, String wholeValue, TextView yourTextView)
String value = wholeValue;
SpannableString spannableString = new SpannableString(value);
int startIndex = value.indexOf(clickableValue);
int endIndex = startIndex + clickableValue.length();
spannableString.setSpan(new ClickableSpan()
@Override
public void updateDrawState(TextPaint ds)
super.updateDrawState(ds);
ds.setUnderlineText(false); // <-- this will remove automatic underline in set span
@Override
public void onClick(View widget)
// do what you want with clickable value
, startIndex, endIndex, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
yourTextView.setText(spannableString);
yourTextView.setMovementMethod(LinkMovementMethod.getInstance()); // <-- important, onClick in ClickableSpan won't work without this
这是如何使用它:
TextView myTextView = findViewById(R.id.myTextView);
setClickableString("stack", "Android is a Software stack", myTextView);
【讨论】:
【参考方案11】:创建优雅的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)
【讨论】:
【参考方案12】:对于那些在 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);
【讨论】:
【参考方案13】:对于粗体,
mySpannable.setSpan(new StyleSpan(Typeface.BOLD),termStart,termStop,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
【讨论】:
【参考方案14】:我编写了一个示例来解决您在 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_
android:layout_/>
<TextView
android:id="@+id/show_terms"
android:layout_
android:layout_
android:textColorLink="@color/colorPrimary"
android:layout_toEndOf="@id/check_agree_terms"/>
这就是它的样子
enter image description here
【讨论】:
【参考方案15】:为java爱好者检查一下这个: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());
【讨论】:
【参考方案16】:这是我的MovementMethod
,用于检测链接/文本/图像点击。修改为LinkMovementMethod
。
import android.text.Layout;
import android.text.NoCopySpan;
import android.text.Selection;
import android.text.Spannable;
import android.text.method.ScrollingMovementMethod;
import android.text.style.ClickableSpan;
import android.text.style.ImageSpan;
import android.text.style.URLSpan;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;
public class ClickMovementMethod extends ScrollingMovementMethod
private Object FROM_BELOW = new NoCopySpan.Concrete();
private static final int CLICK = 1;
private static final int UP = 2;
private static final int DOWN = 3;
private Listener listener;
public void setListener(Listener listener)
this.listener = listener;
@Override
public boolean canSelectArbitrarily()
return true;
@Override
protected boolean handleMovementKey(TextView widget, Spannable buffer, int keyCode,
int movementMetaState, KeyEvent event)
switch (keyCode)
case KeyEvent.KEYCODE_DPAD_CENTER:
case KeyEvent.KEYCODE_ENTER:
if (KeyEvent.metaStateHasNoModifiers(movementMetaState))
if (event.getAction() == KeyEvent.ACTION_DOWN &&
event.getRepeatCount() == 0 && action(CLICK, widget, buffer))
return true;
break;
return super.handleMovementKey(widget, buffer, keyCode, movementMetaState, event);
@Override
protected boolean up(TextView widget, Spannable buffer)
if (action(UP, widget, buffer))
return true;
return super.up(widget, buffer);
@Override
protected boolean down(TextView widget, Spannable buffer)
if (action(DOWN, widget, buffer))
return true;
return super.down(widget, buffer);
@Override
protected boolean left(TextView widget, Spannable buffer)
if (action(UP, widget, buffer))
return true;
return super.left(widget, buffer);
@Override
protected boolean right(TextView widget, Spannable buffer)
if (action(DOWN, widget, buffer))
return true;
return super.right(widget, buffer);
private boolean action(int what, TextView widget, Spannable buffer)
Layout layout = widget.getLayout();
int padding = widget.getTotalPaddingTop() +
widget.getTotalPaddingBottom();
int areatop = widget.getScrollY();
int areabot = areatop + widget.getHeight() - padding;
int linetop = layout.getLineForVertical(areatop);
int linebot = layout.getLineForVertical(areabot);
int first = layout.getLineStart(linetop);
int last = layout.getLineEnd(linebot);
ClickableSpan[] candidates = buffer.getSpans(first, last, URLSpan.class);
int a = Selection.getSelectionStart(buffer);
int b = Selection.getSelectionEnd(buffer);
int selStart = Math.min(a, b);
int selEnd = Math.max(a, b);
if (selStart < 0)
if (buffer.getSpanStart(FROM_BELOW) >= 0)
selStart = selEnd = buffer.length();
if (selStart > last)
selStart = selEnd = Integer.MAX_VALUE;
if (selEnd < first)
selStart = selEnd = -1;
switch (what)
case CLICK:
if (selStart == selEnd)
return false;
if (listener != null)
URLSpan[] link = buffer.getSpans(selStart, selEnd, URLSpan.class);
if (link.length >= 1)
listener.onClick(link[0].getURL());
else
ImageSpan[] image = buffer.getSpans(selStart, selEnd, ImageSpan.class);
if (image.length >= 1)
listener.onImageClicked(image[0].getSource());
else
listener.onTextClicked();
break;
case UP:
int beststart, bestend;
beststart = -1;
bestend = -1;
for (int i = 0; i < candidates.length; i++)
int end = buffer.getSpanEnd(candidates[i]);
if (end < selEnd || selStart == selEnd)
if (end > bestend)
beststart = buffer.getSpanStart(candidates[i]);
bestend = end;
if (beststart >= 0)
Selection.setSelection(buffer, bestend, beststart);
return true;
break;
case DOWN:
beststart = Integer.MAX_VALUE;
bestend = Integer.MAX_VALUE;
for (int i = 0; i < candidates.length; i++)
int start = buffer.getSpanStart(candidates[i]);
if (start > selStart || selStart == selEnd)
if (start < beststart)
beststart = start;
bestend = buffer.getSpanEnd(candidates[i]);
if (bestend < Integer.MAX_VALUE)
Selection.setSelection(buffer, beststart, bestend);
return true;
break;
return false;
@Override
public boolean onTouchEvent(TextView widget, Spannable buffer,
MotionEvent event)
int action = event.getAction();
if (action == MotionEvent.ACTION_UP ||
action == MotionEvent.ACTION_DOWN)
int x = (int) event.getX();
int y = (int) event.getY();
x -= widget.getTotalPaddingLeft();
y -= widget.getTotalPaddingTop();
x += widget.getScrollX();
y += widget.getScrollY();
Layout layout = widget.getLayout();
int line = layout.getLineForVertical(y);
int off = layout.getOffsetForHorizontal(line, x);
URLSpan[] link = buffer.getSpans(off, off, URLSpan.class);
if (action == MotionEvent.ACTION_UP)
if (listener != null)
if (link.length >= 1)
listener.onClick(link[0].getURL());
else
ImageSpan[] image = buffer.getSpans(off, off, ImageSpan.class);
if (image.length >= 1)
listener.onImageClicked(image[0].getSource());
else if (Selection.getSelectionStart(buffer) == Selection.getSelectionEnd(buffer))
listener.onTextClicked();
if (action == MotionEvent.ACTION_DOWN && link.length != 0)
Selection.setSelection(buffer,
buffer.getSpanStart(link[0]),
buffer.getSpanEnd(link[0]));
return true;
if (link.length == 0)
Selection.removeSelection(buffer);
return super.onTouchEvent(widget, buffer, event);
@Override
public void initialize(TextView widget, Spannable text)
Selection.removeSelection(text);
text.removeSpan(FROM_BELOW);
@Override
public void onTakeFocus(TextView view, Spannable text, int dir)
Selection.removeSelection(text);
if ((dir & View.FOCUS_BACKWARD) != 0)
text.setSpan(FROM_BELOW, 0, 0, Spannable.SPAN_POINT_POINT);
else
text.removeSpan(FROM_BELOW);
public interface Listener
void onClick(String clicked);
void onTextClicked();
void onImageClicked(String source);
【讨论】:
【参考方案17】: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());
【讨论】:
【参考方案18】:提供的解决方案相当不错。但是,我通常使用更简单的解决方案。
这是一个链接实用功能
/**
* 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)
【讨论】:
【参考方案19】:Kotlin 上复杂但通用的解决方案
/*
* Receive Pair of Text and Action and set it clickable and appearing as link
* */
fun TextView.setClickableText(vararg textToSpanAndClickAction: Pair<String, (String) -> Unit>)
val builder = SpannableStringBuilder(text.toString())
textToSpanAndClickAction.forEach argPair ->
val clickableSpan = object : ClickableSpan()
override fun onClick(widget: View)
argPair.second.invoke(argPair.first)
this.text.toString().let fullText ->
val indexOfFirst = fullText.indexOf(argPair.first)
val indexOfLast = indexOfFirst + argPair.first.length
if (indexOfFirst < 0)
//No match found
return
else
builder.setSpan(
clickableSpan,
indexOfFirst,
indexOfLast,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
)
this.text = builder
this.movementMethod = LinkMovementMethod.getInstance()
kotlinspannable
【讨论】:
【参考方案20】:这对于文本某些部分的可点击部分非常有帮助。
点是正则表达式中的特殊字符。如果你想扩展点需要将点转义为\\
。而不是仅仅将“.
”传递给可跨文本方法。或者,您也可以使用正则表达式 [.]
在 Java 中通过点来跨越字符串。
【讨论】:
以上是关于如何设置部分文本视图可点击的主要内容,如果未能解决你的问题,请参考以下文章
如何在 react-native 中使文本的某些部分可点击并且某些部分具有不同的文本颜色
Android:将 onClickListener 设置为 TextView 中的部分文本 - 问题
如何在可点击的文本视图中设置超链接? Android Java [重复]