设置TextView的不同字体和颜色

10

我尝试了这个:

String s = "Some big string"
SpannableStringBuilder sb = new SpannableStringBuilder(s);
//normal font for 1st 9 chars
sb.setSpan(robotoRegular, 0,9,Spannable.SPAN_INCLUSIVE_INCLUSIVE);
//bold font for rest of the chars
sb.setSpan(robotoBold, 9,s.length(),Spannable.SPAN_INCLUSIVE_INCLUSIVE);
//also change color for rest of the chars
sb.setSpan(new ForegroundColorSpan(Color.BLACK), 9,s.length(),Spannable.SPAN_INCLUSIVE_INCLUSIVE);
textView.setText(sb);

但这并不起作用。

它只会采用最新的setSpan,也就是说文字颜色会改变,但字体不会改变。


你如何定义 robotoRegularrobotoBold - Benito Bertoli
类变量:robotoRegular = Typeface.createFromAsset(getAssets(), "fonts/Roboto-Regular.ttf"); - Archie.bpgc
4个回答

37

你需要使用 TypefaceSpan 而不是 Typeface

但由于你正在使用自定义字体,因此您需要扩展 TypefaceSpan

查看这个 答案 并创建一个名为 CustomTypefaceSpan 的类。

现在,请执行以下操作:

Typeface robotoRegular = Typeface.createFromAsset(getAssets(), "fonts/Roboto-Regular.ttf");
Typeface robotoBold = Typeface.createFromAsset(getAssets(), "fonts/Roboto-Bold.ttf");

TypefaceSpan robotoRegularSpan = new CustomTypefaceSpan("", robotoRegular);
TypefaceSpan robotoBoldSpan = new CustomTypefaceSpan("", robotoBold);

// normal font for 1st 9 chars
sb.setSpan(robotoRegularSpan, 0, 9, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
// bold font for rest of the chars
sb.setSpan(robotoBoldSpan, 9, s.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
// also change color for rest of the chars
sb.setSpan(new ForegroundColorSpan(Color.BLUE), 9, s.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
textView.setText(sb);

2

对于喜欢编写工具类的人:

public static SpannableStringBuilder makeTextBold (Activity activity, String string, int fromCharIndex, int toCharIndex) {
    return makeTextBold(activity, new SpannableStringBuilder(string), fromCharIndex, toCharIndex);
}

public static SpannableStringBuilder makeTextBold (Activity activity, SpannableStringBuilder string, int fromCharIndex, int toCharIndex) {
    SpannableStringBuilder sb = new SpannableStringBuilder(string);
    Typeface bold = Typeface.createFromAsset(activity.getAssets(), "fonts/NexaBold.ttf");
    TypefaceSpan robotoBoldSpan = new CustomTypefaceSpan("", bold);
    sb.setSpan(robotoBoldSpan, fromCharIndex, toCharIndex, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
    return sb;
}

public static SpannableStringBuilder colorText (int resourceId, String string, Activity activity, int fromCharIndex, int toCharIndex) {
    return colorText(resourceId, new SpannableStringBuilder(string), activity, fromCharIndex, toCharIndex);
}

public static SpannableStringBuilder colorText (int resourceId, SpannableStringBuilder sb, Activity activity, int fromCharIndex, int toCharIndex) {
    sb.setSpan(new ForegroundColorSpan(activity.getResources().getColor(resourceId)), fromCharIndex, toCharIndex, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
    return sb;
}

0

检查这段代码:-

protected void onDraw(Canvas canvas) {

        Paint circlePaint = new Paint();
        Typeface mType = Typeface.create(Typeface.SANS_SERIF, Typeface.ITALIC);
        circlePaint.setTextSize(25);
        circlePaint.setColor(Color.RED);
        circlePaint.setTypeface(mType);
        canvas.drawText("Default Typeface", 50, 100, circlePaint);
        //
        circlePaint.setFlags(Paint.UNDERLINE_TEXT_FLAG);
        circlePaint.setColor(Color.YELLOW);
        canvas.drawText("Underline Text Flag", 50, 120, circlePaint);
        //
        circlePaint.setFlags(Paint.STRIKE_THRU_TEXT_FLAG);
        circlePaint.setColor(Color.GREEN);
        canvas.drawText("Strike Thru Text Flag", 50, 140, circlePaint);
        //
        circlePaint.setFlags(Paint.ANTI_ALIAS_FLAG);
        circlePaint.setColor(Color.WHITE);
        canvas.drawText("Anti Alias Flag", 50, 160, circlePaint);
        //
        circlePaint.setFlags(Paint.DEV_KERN_TEXT_FLAG);
        circlePaint.setColor(Color.WHITE);
        canvas.drawText("Dev Kern Text Flag", 50, 180, circlePaint);
        //
        circlePaint.setFlags(Paint.FAKE_BOLD_TEXT_FLAG);
        circlePaint.setColor(Color.CYAN);
        canvas.drawText("Fake Bold Text Flag", 50, 200, circlePaint);
    }

0

关于这个问题,Google实际上在这个视频中给出了官方答案:

您也可以查看文档进行了解

请注意,这种方法仅适用于Android P+版本,并且字符串不能使用%1$s参数进行格式化。

strings.xml

    <string name="test">Hello <annotation font="sans-serif-medium">World!</annotation></string>

而在代码中:

val spanned = context.getText(R.string.title) as SpannedString
val spannable = SpannableString(spanned)
spanned.getSpans(0, spanned.length, Annotation::class.java).filter { annotation ->
  annotation.key == "font"
}.forEach { annotation ->
  val typeface = Typeface.create(annotation.value, Typeface.NORMAL)
  spannable.setSpan(TypefaceSpan(typeface),
    spanned.getSpanStart(annotation),
    spanned.getSpanEnd(annotation),
    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
}
textView.text = spannable

我正在寻找一种编程方式,可以使用注释程序化地标记字符串的部分。如果您能帮忙,将不胜感激。 - Zain
1
@Zain 如果你以编程方式实现,就不需要注释。你只需根据所需的位置设置跨度即可。 - android developer
谢谢您的即时反馈。我需要做一些定制化的东西,必须在其中使用自定义的“ReplacementSpan”。问题是,它不支持多行文本,除非使用注释。 - Zain
@Zain 抱歉,我没有多少使用它。如果您愿意,我已经在这里编程制作了一个字符串内文本高亮的示例:https://stackoverflow.com/a/57534078/878126。 - android developer
1
我已经编辑了你的答案,填补了原始答案中的空缺。 - Rubén Viguera

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接