问题
Is is possible to change TextView text after using Linkify to create links? I have something where I want the url to have two fields, a name and id, but then I just want the text to display the name.
So I start off with a textview with text that includes both name and id, and linkify to create the appropriate links with both fields. But for the display, I don't want to show the id.
Is this possible?
回答1:
It's kind of a pain but yes. So Linkify basically does a few things. First it scans the contents of the textview for strings that match that of a url. Next it creates UrlSpan's and ForegroundColorSpan's for those sections that match it. Then it sets the MovementMethod of the TextView.
The important part here are the UrlSpan's. If you take your TextView and call getText(), notice it returns a CharSequence. It's most likely some sort of Spanned. From the Spanned you can ask, getSpans() and specifcally the UrlSpans. Once you know all those spans you can than loop through the list and find and replace the old span objects with your new span objects.
mTextView.setText(someString, TextView.BufferType.SPANNABLE);
if(Linkify.addLinks(mTextView, Linkify.ALL)) {
//You can use a SpannableStringBuilder here if you are going to
// manipulate the displayable text too. However if not this should be fine.
Spannable spannable = (Spannable) mTextView.getText();
// Now we go through all the urls that were setup and recreate them with
// with the custom data on the url.
URLSpan[] spans = spannable.getSpans(0, spannable.length, URLSpan.class);
for (URLSpan span : spans) {
// If you do manipulate the displayable text, like by removing the id
// from it or what not, be sure to keep track of the start and ends
// because they will obviously change.
// In which case you may have to update the ForegroundColorSpan's as well
// depending on the flags used
int start = spannable.getSpanStart(span);
int end = spannable.getSpanEnd(span);
int flags = spannable.getSpanFlags(span);
spannable.removeSpan(span);
// Create your new real url with the parameter you want on it.
URLSpan myUrlSpan = new URLSpan(Uri.parse(span.getUrl).addQueryParam("foo", "bar");
spannable.setSpan(myUrlSpan, start, end, flags);
}
mTextView.setText(spannable);
}
Hopefully that makes sense. Linkify is just a nice tool to setup the correct Spans. Spans just get interpreted when rendering text.
回答2:
Greg's answer doesn't really answer the original question. But it does contain some insight as to where to start. Here's a function that you can use. It assumes that you have Linkified your textview prior to this call. It's in Kotlin, but you can get the gist of it if you are using Java.
In short, it builds a new Spannable with your new text. During the build, it copies over the url/flags of the URLSpans that the Linkify call created previously.
fun TextView.replaceLinkedText(pattern: String) { // whatever pattern you used to Linkify textview
if(this.text !is Spannable) return // no need to process since there are no URLSpans
val pattern = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE)
val matcher = pattern.matcher(this.text)
val linkifiedText = SpannableStringBuilder()
var cursorPos = 0
val spannable = this.text as Spannable
while (matcher.find()) {
linkifiedText.append(this.text.subSequence(cursorPos, matcher.start()))
cursorPos = matcher.end()
val span = spannable.getSpans(matcher.start(), matcher.end(), URLSpan::class.java).first()
val spanFlags = spannable.getSpanFlags(span)
val tag = matcher.group(2) // whatever you want to display
linkifiedText.append(tag)
linkifiedText.setSpan(URLSpan(span.url), linkifiedText.length - tag.length, linkifiedText.length, spanFlags)
}
this.text = linkifiedText
}
来源:https://stackoverflow.com/questions/3983409/can-i-change-textview-link-text-after-using-linkify