Hi All,
I have a pretty specific question that no one has been able to answer so far.
I have a function that parses a text with specific markup and adds clickableSpans -(extended as TouchableSpan in my case- to a SpannableStringBuilder (ssb) to make text highlightable and check some data
[HIGH]textView.setMovementMethod(new LinkTouchMovementMethod());
ssb = addClickablePart(chapterTextStr,markupCharactersArray, false);
textView.setText(ssb);
// PARSE MARKERS AND CREATE CLICKABLE SPANS FUNCTION
private static SpannableStringBuilder addClickablePart(
String chapterTextStr2, final String[] mcArray,
final boolean parseVocab) {
SpannableStringBuilder ssb2 = new SpannableStringBuilder(chapterTextStr2);
String[] markupOpen = { "|*", "|_", "|=", "|@" };
String [] markupClose = { "*|", "_|", "=|", "@|"};
String [] spantype = { "idea", "topic", "detail", "dummy"};
for( int i=0; i<markupOpen.length; i++){
index = chapterTextStr2.indexOf(markupOpen);
index2 = 0;
while (index != -1) {
index2 = chapterTextStr2.indexOf(markupClose, index);
TouchableSpan touchableSpan = new TouchableSpan() {
@Override
public void onClick(View widget) {
this.setPressed(true);
if (selectedHighlighter == "detail") {
this.setSpanColor(detailColor);
this.setSpanTypeSelected("detailSelected");
} else if (selectedHighlighter == "idea") {
this.setSpanColor(ideaColor);
this.setSpanTypeSelected("ideaSelected");
} else if (selectedHighlighter == "topic") {
this.setSpanColor(topicColor);
this.setSpanTypeSelected("topicSelected");
} else {
this.setSpanColor(Color.TRANSPARENT);
this.setSpanTypeSelected("");
}
}
private boolean mIsPressed;
public void setPressed(boolean isSelected) {
mIsPressed = isSelected;
}
// THIS UPDATES THE DRAW STATE TO CHANGE THE SPAN BACKGROUND COLOR DEPENDING ON THE "SELECTED HIGHLIGHTER"
@Override
public void updateDrawState(TextPaint ds) {
int spanColor = this.getSpanColor();
super.updateDrawState(ds);
ds.setColor(Color.BLACK);
ds.bgColor = mIsPressed ? spanColor : 0xffeeeeee;
ds.setUnderlineText(false);
}
};
touchableSpan.setSpanType(spantype);
ssb2.setSpan(touchableSpan, index + 2, index2, 0);
try {
chapterTextStr2 = chapterTextStr2.substring(0,index)
+chapterTextStr2.substring(index+2,index2)
+chapterTextStr2.substring(index2+2,chapterTextStr2.length());
ssb2.delete(index, index+2);
ssb2.delete(index2-2, index2);
} catch(RuntimeException e) {
}
index = chapterTextStr2.indexOf(markupOpen,index2-4);
}
}
chapterTextStr = chapterTextStr2;
return ssb2;
}[/HIGH]
It works pretty good. But the problem is that when I have very long texts with lots of clickableSpans, it takes a lot of time to react, since it is executing update draw state for every element.
Anyone can think of a way to avoid this and only update the draw state on the clicked element?
I have a pretty specific question that no one has been able to answer so far.
I have a function that parses a text with specific markup and adds clickableSpans -(extended as TouchableSpan in my case- to a SpannableStringBuilder (ssb) to make text highlightable and check some data
[HIGH]textView.setMovementMethod(new LinkTouchMovementMethod());
ssb = addClickablePart(chapterTextStr,markupCharactersArray, false);
textView.setText(ssb);
// PARSE MARKERS AND CREATE CLICKABLE SPANS FUNCTION
private static SpannableStringBuilder addClickablePart(
String chapterTextStr2, final String[] mcArray,
final boolean parseVocab) {
SpannableStringBuilder ssb2 = new SpannableStringBuilder(chapterTextStr2);
String[] markupOpen = { "|*", "|_", "|=", "|@" };
String [] markupClose = { "*|", "_|", "=|", "@|"};
String [] spantype = { "idea", "topic", "detail", "dummy"};
for( int i=0; i<markupOpen.length; i++){
index = chapterTextStr2.indexOf(markupOpen);
index2 = 0;
while (index != -1) {
index2 = chapterTextStr2.indexOf(markupClose, index);
TouchableSpan touchableSpan = new TouchableSpan() {
@Override
public void onClick(View widget) {
this.setPressed(true);
if (selectedHighlighter == "detail") {
this.setSpanColor(detailColor);
this.setSpanTypeSelected("detailSelected");
} else if (selectedHighlighter == "idea") {
this.setSpanColor(ideaColor);
this.setSpanTypeSelected("ideaSelected");
} else if (selectedHighlighter == "topic") {
this.setSpanColor(topicColor);
this.setSpanTypeSelected("topicSelected");
} else {
this.setSpanColor(Color.TRANSPARENT);
this.setSpanTypeSelected("");
}
}
private boolean mIsPressed;
public void setPressed(boolean isSelected) {
mIsPressed = isSelected;
}
// THIS UPDATES THE DRAW STATE TO CHANGE THE SPAN BACKGROUND COLOR DEPENDING ON THE "SELECTED HIGHLIGHTER"
@Override
public void updateDrawState(TextPaint ds) {
int spanColor = this.getSpanColor();
super.updateDrawState(ds);
ds.setColor(Color.BLACK);
ds.bgColor = mIsPressed ? spanColor : 0xffeeeeee;
ds.setUnderlineText(false);
}
};
touchableSpan.setSpanType(spantype);
ssb2.setSpan(touchableSpan, index + 2, index2, 0);
try {
chapterTextStr2 = chapterTextStr2.substring(0,index)
+chapterTextStr2.substring(index+2,index2)
+chapterTextStr2.substring(index2+2,chapterTextStr2.length());
ssb2.delete(index, index+2);
ssb2.delete(index2-2, index2);
} catch(RuntimeException e) {
}
index = chapterTextStr2.indexOf(markupOpen,index2-4);
}
}
chapterTextStr = chapterTextStr2;
return ssb2;
}[/HIGH]
It works pretty good. But the problem is that when I have very long texts with lots of clickableSpans, it takes a lot of time to react, since it is executing update draw state for every element.
Anyone can think of a way to avoid this and only update the draw state on the clicked element?