0

それぞれに SpannableString を含む TextView 要素を持つリストビューを作成しようとしています。これらの TextViews のコンテンツは、Html マークアップの ArrayList からフェッチされ、Html.fromHtml を使用して SpannableStrings に変換されます。現在、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 による以前の回答に触発されてこれを行いましたHtml.fromHtml() よりも html 文字を文字列にデコードするより高速な方法はありますか? . 最小限の機能 (太字、斜体、下線、改行) しかありませんが、それでもパフォーマンスはそれほど向上していません。テキストビューをビットマップに合成してメモリにキャッシュし、リストビューのリサイクル時に再度レンダリングする必要がないなど、いくつかのアイデアがあります。誰でもアイデアを提案できますか? ..(NDKベースのソリューションは避けてください。コンパイルに成功したことがなく、不要な複雑さが追加されているためです)

4

1 に答える 1

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;
}

この関数は要素を太字にするだけですが、他のタグを実行するように簡単に変更できます。

于 2014-10-22T08:28:19.977 に答える