Альтернативы Html.fromHtml?
Я пытаюсь сделать просмотр списка, который имеет элементы TextView, каждый из которых содержит SpannableString. Содержимое этих TextView извлекается из ArrayList в разметке Html и преобразуется в SpannableStrings с использованием Html.fromHtml. Теперь у Html.fromHtml много проблем с производительностью. Поэтому я попытался сделать свою собственную версию Html.fromHtml
class NeoHTML extends DefaultHandler {
SpannableStringBuilder s;
String html;
Context context;
public NeoHTML(String html,Context context) {
s = new SpannableStringBuilder("");
this.html = html;
this.context=context;
getXml();
}
public SpannableStringBuilder fromHTML() {
return s;
}
public void getXml() {
try {
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
SAXParser saxParser = saxParserFactory.newSAXParser();
DefaultHandler defaultHandler = new DefaultHandler() {
int boldTag = 0;
int italicsTag = 0;
int underlineTag = 0;
int pointer = 0;
boolean brpassed=false;
public void startElement(String uri, String localName,
String qName, Attributes attributes)
throws SAXException {
if (qName.equalsIgnoreCase("B")) {
boldTag += 1;
}
if (qName.equalsIgnoreCase("I")) {
italicsTag += 1;
}
if (qName.equalsIgnoreCase("U")) {
underlineTag += 1;
}
}
public void characters(char ch[], int start, int length)
throws SAXException {
int tstart=start;
if(new String(ch, start, length).startsWith("[ ]")){
s.append("b");
Typeface font = Typeface.createFromAsset(context.getAssets(), "tickfont.ttf");
s.setSpan (new CustomTypefaceSpan("", font),pointer, pointer+1,Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
pointer+=1;
tstart+=3;
}
else if(new String(ch, start, length).startsWith("[*]")){
s.append("a");
Typeface font = Typeface.createFromAsset(context.getAssets(), "tickfont.ttf");
s.setSpan (new CustomTypefaceSpan("", font),pointer, pointer+1,Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
pointer+=1;
tstart+=3;
}
if (boldTag > 0 || italicsTag > 0 || underlineTag > 0) {
s.append(new String(ch, tstart, length));
if (boldTag > 0) {
s.setSpan(new StyleSpan(
android.graphics.Typeface.BOLD), pointer,
pointer + length,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
if (italicsTag > 0) {
s.setSpan(new StyleSpan(
android.graphics.Typeface.ITALIC), pointer,
pointer + length,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
if (underlineTag > 0) {
s.setSpan(new UnderlineSpan(), pointer, pointer
+ length,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
} else {
s.append(new String(ch, tstart, length));
}
pointer += length;
}
public void endElement(String uri, String localName,
String qName) throws SAXException {
if (qName.equalsIgnoreCase("B")) {
boldTag -= 1;
}
if (qName.equalsIgnoreCase("BR")) {
s.append("\n");
pointer+=1;
brpassed=true;
}
if (qName.equalsIgnoreCase("I")) {
italicsTag -= 1;
}
if (qName.equalsIgnoreCase("U")) {
underlineTag -= 1;
}
}
};
saxParser.parse(new InputSource(new StringReader(html)),
defaultHandler);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Это простой синтаксический анализатор на основе саксофона. Я сделал это, вдохновленный предыдущим ответом CommonsWare. Есть ли более быстрый способ декодирования символов html в строку, чем Html.fromHtml()?, Он имеет минимальную функциональность (жирный, курсив, подчеркивание и разрывы). Но даже в этом случае производительность не настолько улучшена. У меня есть некоторые идеи, такие как наложение текстового представления на растровое изображение и кэширование его в памяти, и нет необходимости повторной визуализации при повторном просмотре списка. Кто-нибудь может предложить какие-либо идеи?.. (пожалуйста, избегайте решений на основе NDK, так как я никогда их не компилировал, и это добавляет нежелательную сложность)
1 ответ
Некоторое время назад у меня была схожая проблема, когда я использовал Html.fromHtml, на некоторых устройствах текст был размытым, когда он должен был быть жирным. Так что это было мое решение:
public static Spannable boldFromHtml(Context c, String text, boolean extraBold){
String textTemp = text;
int boldStartPos = 0;
int boldEndPos = 1;
List<int[]> spanList = new LinkedList<int[]>();
while((boldStartPos = textTemp.indexOf("<b>", boldStartPos)) != -1 && (boldEndPos = textTemp.indexOf("</b>", boldStartPos) - 3) != -1){
textTemp = textTemp.replaceFirst("<b>", "").replaceFirst("</b>", "");
spanList.add(new int[]{boldStartPos, boldEndPos});
boldStartPos += 3;
}
Spannable span = new SpannableString(textTemp);
for(int[] selection: spanList){
span.setSpan(new BoldTypefaceSpan("sans-serif", (extraBold) ? MyExtraBoldFont(c) : MyBoldFont(c)), selection[0], selection[1], Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
return span;
}
Эта функция только выделяет ваши элементы, но ее можно легко изменить, чтобы сделать другие теги.