2014-10-22 9 views
0

Я пытаюсь создать listview, в котором есть элементы TextView, каждый из которых содержит SpannableString. Содержимое этих TextViews извлекается из ArrayList в разметке Html и преобразуется в SpannableStrings с использованием Html.fromHtml. Теперь у 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(); 
    } 
} 

}

Это простой SAX-анализатор на основе. Я сделал это, опираясь на предыдущий ответ CommonsWare Is there a faster way to decode html characters to a string than Html.fromHtml()?. Он имеет минимальную функциональность (полужирный, курсив, подчеркивание и перерывы). Но даже при этом производительность не улучшена. У меня есть некоторые идеи, такие как компоновка текстового представления в растровое изображение и кэширование его в памяти, а также необходимость повторного рендеринга его снова при переработке списка. Может ли кто-нибудь предложить какие-либо идеи? .. (пожалуйста, избегайте решений на основе NDK, поскольку я никогда их не скомпилировал, и это добавляет нежелательную сложность)

+0

попытался использовать парсер для «низкого уровня»? – pskink

+0

@pskink, я не хочу, чтобы это было слишком сложно. Это незначительная проблема с производительностью. Добавление NDK не является вариантом. Прости. , но можете ли вы предложить хороший парсер низкого уровня? – avinayak

+0

комплекс? вы говорите проще? см .: http://pastebin.com/6yU3tGaR – pskink

ответ

2

У меня была близкая проблема, когда я сделал 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; 
} 

Эта функция выделяет только ваши элементы, но может быть легко изменена для других тегов.

+0

Это похоже на то, что я пытался. Я не думаю, что это улучшит производительность – avinayak