Reputation: 67
I have a String like this: "Hello, [user123| Alex]! Visit [club123|my club]"
It is the way social network Vkontakte returns posts with inside links. I want to replace them with spannables, that can be clickable.
For example I want to get: "Hello, Alex! Visit my club", where emphasized text is clickable
I've found out the way, how to replace such occurencies with strings, but can't figure out, how to do that with spannables. Can you help me, please? My code:
public String extractLink(String text)
{
String result=text, text1=text;
Pattern pattern = Pattern.compile("\\[((id)|(club))[0-9]+\\|\\w+\\]");
Matcher matcher = pattern.matcher(text);
List<String> allMatches = new ArrayList<String>();
while (matcher.find()) {
//matcher.replaceAll(matcher.group().substring(matcher.group().indexOf("|")+1,matcher.group().indexOf("]")));
allMatches.add(matcher.group());
Log.d("MATCH", matcher.group());
}
Integer i=0;
for (i=0; i<allMatches.size();i++)
{
text1=result.replaceFirst("\\[((id)|(club))[0-9]+\\|\\w+\\]", allMatches.get(i).substring(allMatches.get(i).indexOf("|")+1,allMatches.get(i).indexOf("]")));
result=text1;
}
return result;
}
Upvotes: 3
Views: 6214
Reputation: 191
This can help you :
private List<Hyperlink> listOfLinks = new ArrayList<>();
private Pattern myPattern = Pattern.compile("\\[((id)|(club))[0-9]+\\|\\w+\\]");
public void setTextAndActivateLinks(String text) {
SpannableString linkableText = new SpannableString(text);
gatherLinks(linkableText, myPattern);
for (Hyperlink linkSpec : listOfLinks) {
linkableText.setSpan(linkSpec.span, linkSpec.start, linkSpec.end, 0);
SpannableStringBuilder ssb = new SpannableStringBuilder();
ssb.append(linkableText, 0, linkableText.length());
ssb.replace(linkSpec.start, linkSpec.end, TODO HERE YOUR REPLACEMENT);
linkableText = SpannableString.valueOf(ssb);
}
setText(linkableText);
}
private void gatherLinks(SpannableString s, Pattern pattern) {
Matcher m = pattern.matcher(s);
while (m.find()) {
int start = m.start();
int end = m.end();
Hyperlink link = new Hyperlink();
link.type = type;
link.textSpan = s.subSequence(start, end);
link.color = mLinkColor;
link.span = new InternalURLSpan(link.textSpan.toString(), link.type, link.color);
link.start = start;
link.end = end;
listOfLinks.add(0, link);
}
}
public class InternalURLSpan extends ClickableSpan {
private String clickedSpan;
private LinkType clickedType;
private int clickedColor;
public InternalURLSpan(String span, LinkType type, int color) {
clickedSpan = span;
clickedType = type;
clickedColor = color;
}
@Override
public void updateDrawState(TextPaint ds) {
ds.bgColor = Color.TRANSPARENT;
ds.setColor(clickedColor);
ds.setUnderlineText(false);
}
@Override
public void onClick(View textView) {
OnClickLinkListener listener = wr_listener.get();
if (listener != null)
listener.onClickLink(textView, clickedSpan, clickedType);
}
}
public static class LocalLinkMovementMethod extends LinkMovementMethod {
static LocalLinkMovementMethod sInstance;
public static LocalLinkMovementMethod getInstance() {
if (sInstance == null)
sInstance = new LocalLinkMovementMethod();
return sInstance;
}
@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);
ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);
if (link.length != 0) {
if (action == MotionEvent.ACTION_UP)
link[0].onClick(widget);
else
Selection.setSelection(buffer, buffer.getSpanStart(link[0]), buffer.getSpanEnd(link[0]));
if (widget instanceof LinkTextView)
((LinkTextView) widget).mHitLink = true;
return true;
} else {
Selection.removeSelection(buffer);
Touch.onTouchEvent(widget, buffer, event);
return false;
}
}
return Touch.onTouchEvent(widget, buffer, event);
}
}
/*
* Class for storing the information about the Link Location
*/
class Hyperlink {
LinkType type;
CharSequence textSpan;
InternalURLSpan span;
int start;
int end;
int color;
}
Upvotes: 3