Android-使用ReplacementSpan为SpannableStringBuilder添加保证金 [英] Android - Add Margin for SpannableStringBuilder using ReplacementSpan

查看:283
本文介绍了Android-使用ReplacementSpan为SpannableStringBuilder添加保证金的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在TextView/EditText内设置标签格式(例如,在材料设计规范中提到的芯片).我可以使用 ReplacementSpan 格式化背景.但是问题是我无法增加TextView/EditText中的行距.见下图

I'm trying to format Hashtags inside a TextView/EditText (Say like Chips mentioned in the Material Design Specs). I'm able to format the background using ReplacementSpan. But the problem is that I'm not able to increase the line spacing in the TextView/EditText. See the image below

问题是如何为主题标签添加顶部和底部边距?

The question is how do I add top and bottom margin for the hashtags?

这是我在文本中添加背景的代码:

Here is the code where I add the background to the text:

   /**
     * First draw a rectangle
     * Then draw text on top
     */
    @Override
    public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) {
        RectF rect = new RectF(x, top, x + measureText(paint, text, start, end), bottom);
        paint.setColor(backgroundColor);
        canvas.drawRoundRect(rect, CORNER_RADIUS, CORNER_RADIUS, paint);
        paint.setColor(textColor);
        canvas.drawText(text, start, end, x, y, paint);
    }

推荐答案

我前段时间遇到了类似的问题,这是我想出的解决方案:

I had a similar problem a while ago and this is the solution I've come up with:

以xml托管的TextView:

The hosting TextView in xml:

<TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingTop="18dp"
        android:paddingBottom="18dp"
        android:paddingLeft="8dp"
        android:paddingRight="8dp"
        android:gravity="fill"
        android:textSize="12sp"
        android:lineSpacingExtra="10sp"
        android:textStyle="bold"
        android:text="@{viewModel.renderedTagBadges}">

ReplacementSpan

public class TagBadgeSpannable extends ReplacementSpan implements LineHeightSpan {

    private static int CORNER_RADIUS = 30;
    private final int textColor;
    private final int backgroundColor;
    private final int lineHeight;

    public TagBadgeSpannable(int lineHeight, int textColor, int backgroundColor) {
        super();
        this.textColor = textColor;
        this.backgroundColor = backgroundColor;
        this.lineHeight = lineHeight;
    }

    @Override
    public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) {
        final float textSize = paint.getTextSize();
        final float textLength = x + measureText(paint, text, start, end);
        final float badgeHeight = textSize * 2.25f;
        final float textOffsetVertical = textSize * 1.45f;

        RectF badge = new RectF(x, y, textLength, y + badgeHeight);
        paint.setColor(backgroundColor);
        canvas.drawRoundRect(badge, CORNER_RADIUS, CORNER_RADIUS, paint);

        paint.setColor(textColor);
        canvas.drawText(text, start, end, x, y + textOffsetVertical, paint);
    }

    @Override
    public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) {
        return Math.round(paint.measureText(text, start, end));
    }

    private float measureText(Paint paint, CharSequence text, int start, int end) {
        return paint.measureText(text, start, end);
    }

    @Override
    public void chooseHeight(CharSequence charSequence, int i, int i1, int i2, int i3, Paint.FontMetricsInt fontMetricsInt) {
        fontMetricsInt.bottom += lineHeight;
        fontMetricsInt.descent += lineHeight;
    }
}

最后是一个创建Spannable的构建器

And finally a builder that creates the Spannable

public class AndroidTagBadgeBuilder implements TagBadgeBuilder {

    private final SpannableStringBuilder stringBuilder;
    private final String textColor;
    private final int lineHeight;

    public AndroidTagBadgeBuilder(SpannableStringBuilder stringBuilder, int lineHeight, String textColor) {
        this.stringBuilder = stringBuilder;
        this.lineHeight = lineHeight;
        this.textColor = textColor;
    }

    @Override
    public void appendTag(String tagName, String badgeColor) {
        final String nbspSpacing = "\u202F\u202F"; // none-breaking spaces

        String badgeText = nbspSpacing + tagName + nbspSpacing;
        stringBuilder.append(badgeText);
        stringBuilder.setSpan(
            new TagBadgeSpannable(lineHeight, Color.parseColor(textColor), Color.parseColor(badgeColor)),
            stringBuilder.length() - badgeText.length(),
            stringBuilder.length()- badgeText.length() + badgeText.length(),
            Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
        );
        stringBuilder.append("  ");
    }

    @Override
    public CharSequence getTags() {
        return stringBuilder;
    }

    @Override
    public void clear() {
        stringBuilder.clear();
        stringBuilder.clearSpans();
    }
}

结果将如下所示:

根据自己的喜好调整 TagBadgeSpannable 中的度量.

Tweak the measures in TagBadgeSpannable to your liking.

我已经使用此代码将一个非常小的示例项目上传到 github 免费查看.

I've uploaded a very minimal sample project using this code to github so feel free to check it out.

注意::该示例使用Android数据绑定并编写为MVVM风格

NOTE: The sample uses Android Databinding and is written MVVM style

这篇关于Android-使用ReplacementSpan为SpannableStringBuilder添加保证金的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆