Android 自定义 QuoteSpan 问题

标签 android html tag-handler

我在应用我的自定义 QuoteSpan 时遇到了一个奇怪的问题。 它包括此结束标记之后的所有文本:</quote> .但是当我尝试替换 <quote>...</quote> 时它起作用了进入<blockquote>...</blockquote>跳过我的 Custom HtmlTagHandler 并使用 Android 的 QuoteSpan 的默认实现。请参阅下面的屏幕截图:

预期结果(使用默认的 QuoteSpan):http://i.stack.imgur.com/bADnU.png

当前输出(使用我的自定义 QuoteSpan):http://i.stack.imgur.com/VFpkz.png

Custom HtmlTagHandler - 用于未处理的 html 标签(对于 quote 标签)

package com.demoparser.http.parser;

import android.graphics.Typeface;
import android.text.Editable;
import android.text.Html;
import android.text.Spannable;
import android.text.Spanned;
import android.text.style.RelativeSizeSpan;
import android.text.style.StrikethroughSpan;
import android.text.style.StyleSpan;
import android.text.style.TypefaceSpan;

import com.demoparser.util.CustomQuoteSpan;

import org.xml.sax.XMLReader;

public class HtmlTagHandler implements Html.TagHandler {

    private static final float[] HEADER_SIZES = {
            1.5f, 1.4f, 1.3f, 1.2f, 1.1f, 1f,
    };

    @Override
    public void handleTag(boolean opening, String tag, Editable output, XMLReader xmlReader) {
        if (tag.equalsIgnoreCase("del")) {
            if (opening) {
                start(output, new Strikethrough());
            } else {
                end(output, Strikethrough.class, new StrikethroughSpan());
            }
        } else if (tag.equalsIgnoreCase("pre")) {
            if (opening) {
                start(output, new Monospace());
            } else {
                end(output, Monospace.class, new TypefaceSpan("monospace"));
            }
        } else if (tag.equalsIgnoreCase("quote")) {
            if (opening) {
                handleP(output);
                start(output, new BlockQuote());
            } else {
                handleP(output);
                end(output, BlockQuote.class, new CustomQuoteSpan());
            }
        }
    }

    private static void handleP(Editable text) {
        int len = text.length();

        if (len >= 1 && text.charAt(len - 1) == '\n') {
            if (len >= 2 && text.charAt(len - 2) == '\n') {
                return;
            }

            text.append("\n");
            return;
        }

        if (len != 0) {
            text.append("\n\n");
        }
    }

    private static Object getLast(Spanned text, Class kind) {
        /*
         * This knows that the last returned object from getSpans()
         * will be the most recently added.
         */
        Object[] objs = text.getSpans(0, text.length(), kind);

        if (objs.length == 0) {
            return null;
        } else {
            return objs[objs.length - 1];
        }
    }

    private static void start(Editable text, Object mark) {
        int len = text.length();
        text.setSpan(mark, len, len, Spannable.SPAN_MARK_MARK);
    }

    private static void end(Editable text, Class kind, Object repl) {
        int len = text.length();
        Object obj = getLast(text, kind);
        int where = text.getSpanStart(obj);

        text.removeSpan(obj);

        if (where != len) {
            text.setSpan(repl, where, len, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        }
    }

    public static class Strikethrough {}
    public static class Monospace {}
    public static class BlockQuote {}

}

自定义报价跨度

package com.demoparser.util;

/*
 * Copyright (C) 2006 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import android.graphics.Canvas;
import android.graphics.Paint;
import android.text.Layout;
import android.text.style.LeadingMarginSpan;
import android.text.style.LineBackgroundSpan;

public class CustomQuoteSpan implements LeadingMarginSpan, LineBackgroundSpan {
    private static final int STRIPE_WIDTH = 5;
    private static final int GAP_WIDTH = 8;

    private final int mBackgroundColor;
    private final int mColor;

    public QuoteSpan() {
        super();
        mBackgroundColor = 0xffddf1fd;
        mColor = 0xff098fdf;
    }

    public int getLeadingMargin(boolean first) {
        return STRIPE_WIDTH + GAP_WIDTH;
    }

    public void drawLeadingMargin(Canvas c, Paint p, int x, int dir,
                                  int top, int baseline, int bottom,
                                  CharSequence text, int start, int end,
                                  boolean first, Layout layout) {
        Paint.Style style = p.getStyle();
        int color = p.getColor();

        p.setStyle(Paint.Style.FILL);
        p.setColor(mColor);

        c.drawRect(x, top, x + dir * STRIPE_WIDTH, bottom, p);

        p.setStyle(style);
        p.setColor(color);
    }

    @Override
    public void drawBackground(Canvas c, Paint p, int left, int right, int top, int baseline, int bottom, CharSequence text, int start, int end, int lnum) {
        int paintColor = p.getColor();
        p.setColor(mBackgroundColor);
        c.drawRect(left, top, right, bottom, p);
        p.setColor(paintColor);
    }
}

以及我尝试应用自定义 QuoteSpan 的 HTML 元素:

<quote>
 <div class="q_b">      
  <div class="q_tl">
   <div class="q_tr">
    <div class="q_bl">
     <div class="q_br">
      <div class="q_body">
       <b class="qfont">Quote:</b>
       <div style="padding:5px;">
        <div class="q_by">
         Originally Posted by 
         <strong>: <a href="/index.php?thread=1#msg2"> username on 1-1-2016 00:00 AM</a></strong>
        </div>
        Sample Quoted Text 1
        <br>
        <br>
       </div>
      </div>
     </div>
    </div>
   </div>
  </div>
 </div>
</quote>
<br>
<br>
This message should not be inside the QuoteSpan

我正在使用 Html.fromHtml(...)渲染跨度。​​

Html.fromHtml(message, null, new HtmlTagHandler())

这是开始和结束标签索引的日志:

START: 0
END: 138 <-- should be 87

有人知道如何实现与默认 QuoteSpan 的输出相同的结果或指出错误的实现吗?提前谢谢你。

最佳答案

从这里answer ,在 (Zero-width joiner - 非打印字符)前面加上解决方法解决了这个问题。

&zwj;<quote>...</quote>

关于Android 自定义 QuoteSpan 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34692666/

相关文章:

android - 我可以在 Monodroid 中使用什么来替代 Action Bar?

android - 从一个apk中读取Application.mk信息

android - 使用 Google map 时应用程序因 FragmentManager Replace 而崩溃

java - Android TagHandler 异常

android - 如何在Android TextView中显示HTML文本?

java - 编译自定义 JSP 标记处理程序

java - 为可点击范围设置 setMovementMethod 后如何防止 TextView 滚动?

html - Angular Material 和输入类型 'time' ,值属性与 ngModel

javascript - iframe 中的 HTTP 重定向而不是父窗口中的重定向

javascript - 动态改变CSS样式中的图片