Сделайте строку кликабельной, подчеркнутой в TextView
Я хочу сделать строку "эта ссылка" подчеркнутой и кликабельной, но я не знаю, как этого добиться.
XML-файл:
<string name="submitText">Before you submit, please check out <u>this link</u></string>
В моем фрагменте:
tvSubmit.setText(Html.fromHtml(getString(R.string.submitText)));
Я не хочу, чтобы вся строка была кликабельной, только подчеркнутый раздел. Я не могу использовать горизонтальный LinearLayout
с 2 ячейками, потому что на меньших устройствах строка не будет иметь продолжения, она будет разбита на 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);
Приведенный выше код подчеркивает всю строку, а также цвет текста меняется на голубой.
8 ответов
Проблема в том, что вы устанавливаете диапазон для всей строки (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>
в вашей деятельности
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 являются индексом thisLink
в yourString
, Я разделил две строки, потому что было легче искать индексы, особенно если вам приходится иметь дело с переводами. Для расчета startIndex вы можете использовать yourString.indexOf(thisLink)
и endIndex это startIndex + the length of thisLink
, Я оставлю вам обычные чеки (отрицательные индексы и все остальное, что может вызвать IndexOutBoundException
)
Вы можете определить в вашем 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" />
в деятельности // образец
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)));
проверьте здесь для более подробного ответа
В моем случае мне нужно было иметь локализованную строку, часть которой была бы интерактивной. Что я сделал, так это определил строку в своих ресурсах (по одной для каждой локали) с подчеркнутой интерактивной частью, например:
<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
Вы можете попробовать функцию расширения 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()
Только что сделал эту функцию, чтобы помочь мне добавить интерактивный текст в текстовое представление:
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;
}
sp.setSpan(click, 0, sp.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
изменить значение 0: с позиции начала ссылки в тексте, пример изменить значение с: 10, если вы установите 0, это будет гиперссылка на весь текст.
Вы можете попробовать с приведенным ниже кодом..
String str = "Before you submit, please check out this link";
tvSubmit.setMovementMethod(LinkMovementMethod.getInstance());
tvSubmit.setText(setClickablePart(str), BufferType.SPANNABLE);
Для обработки события Click в 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;
}