简体   繁体   中英

Android add padding for spanned text

In my app, I fetch and parse html content and show it using Spanned. I use Spanned like that:

String html = "<p>Html Content</p>"
Spanned htmlSpan = Html.fromHtml(html, imageParser, null);

I've tried to use apache commons library to set padding but it didn't work.

Is there any way to set left and right padding?

Edit: forgot to mention, I also have images in that html content. I've tried to add padding to the TextView itself, but that way, all images also have padding.

Generally speaking, the easiest solution to display HTML is using a WebView . It is not the best solution, but it will also work with css and javascript.

To apply padding on spanned text in a TextView you can use <blockquote> which Html.fromHtml() will convert to a QuoteSpan . If you don't like the format of that span, you can replace it and add your own implementation of LeadingMarginSpan . The same would work by adding a TagHandler to create and handle your own tag on the spannable string.

You can search and replace the span by using something like the following

 QuoteSpan[] spans = text.getSpans(0, text.length(), QuoteSpan.class);
text.setSpan(YOUR_SPAN, text.getSpanStart(spans[0]), text.getSpanEnd(spans[0]), 0);

Working with spans is poorly documented and there are little tutorials, but you could look at this for further reading.

I have chosen the hard way.

https://developer.android.com/reference/android/text/style/QuoteSpan#quotespan

It shows Android P Developer Preview will have following constructor

QuoteSpan (int color, 
                int stripeWidth, 
                int gapWidth)

How unfortunate

Therefore the only way is to implement a new QuoteText as David expected. Fortunately Android is open sourced.

https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/text/style/QuoteSpan.java

Where is the Android P source? I still cannot locate it.

Copy the source and implement the constructor then.

import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Parcel;
import android.support.annotation.ColorInt;
import android.text.Layout;
import android.text.ParcelableSpan;
import android.text.TextUtils;
import android.text.style.LeadingMarginSpan;

// https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/text/style/QuoteSpan.java
public class MyQuoteSpan implements LeadingMarginSpan, ParcelableSpan {
    private int mStripWidth = 2;
    private int mGapWidth = 2;
    private final int mColor;
    public MyQuoteSpan() {
        super();
        mColor = 0xff0000ff;
    }
    public MyQuoteSpan(@ColorInt int color, int stripeWidth, int gapWidth) {
        super();
        mColor = color;
        mStripWidth = stripeWidth;
        mGapWidth = gapWidth;
    }
    public MyQuoteSpan(Parcel src) {
        mColor = src.readInt();
    }
    public int getSpanTypeId() {
        return getSpanTypeIdInternal();
    }
    /** @hide */
    public int getSpanTypeIdInternal() {
        //return TextUtils.QUOTE_SPAN;
        return 9;
    }
    public int describeContents() {
        return 0;
    }
    public void writeToParcel(Parcel dest, int flags) {
        writeToParcelInternal(dest, flags);
    }
    /** @hide */
    public void writeToParcelInternal(Parcel dest, int flags) {
        dest.writeInt(mColor);
    }
    @ColorInt
    public int getColor() {
        return mColor;
    }
    public int getLeadingMargin(boolean first) {
        return mStripWidth + mGapWidth;
    }
    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 * mStripWidth, bottom, p);
        p.setStyle(style);
        p.setColor(color);
    }
}

Finally use it

String html = "<blockquote>Html Content</blockquote>";
Spannable contentNative;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
   contentNative = (Spannable)Html.fromHtml(content, Html.FROM_HTML_MODE_COMPACT, null, null);
} else {
    contentNative = (Spannable)Html.fromHtml(content, null, null);
}
QuoteSpan[] quoteSpans = contentNative.getSpans(0, contentNative.length(), QuoteSpan.class);
int primaryColor = ResourcesCompat.getColor(getResources(), R.color.colorPrimary, null);
int quoteStripWidth = 2;
int quoteGapWidth = 8;
for (int i = 0, len = quoteSpans.length; i < len; i++) {
    MyQuoteSpan newSpan = new MyQuoteSpan(primaryColor, quoteStripWidth, quoteGapWidth);
    int start = contentNative.getSpanStart(quoteSpans[i]);
    int end = contentNative.getSpanEnd(quoteSpans[i]);
    contentNative.removeSpan(quoteSpans[i]);
    contentNative.setSpan(newSpan, start, end, 0);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM