android - 放大 SpannableString 中的单个字符会影响行间距(仅在 Marshmallow 中)

标签 android

我有以下方法,它放大了 TextView 中的第一个字符。

private void makeFirstLetterBig(TextView textView, String title) {
    final SpannableString spannableString = new SpannableString(title);
    int position = 0;
    spannableString.setSpan(new RelativeSizeSpan(2.0f), position, position + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    //textView.setText(spannableString.toString());
    textView.setText(spannableString, BufferType.SPANNABLE);
}

这是正在使用的 TextView

<TextView
    android:id="@+id/title_text_view"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textSize="16sp"
    android:textColor="?attr/newsTitleTextViewSelector"
    android:duplicateParentState="true"
    android:text="TextView" />

这是 Marshmallow 6 之前的结果。

enter image description here

看起来不错,因为当文本内容换行到第 2 行时,第一个大字符不会影响第 2 行。

但是,当在 Marshmallow 6 中运行相同的应用程序时,我得到以下结果。

enter image description here

看来,大字“我”正在为整个文本内容创建一个大填充。这导致第二行(亚马逊)与第一行有很大的行距。

我可以知道,我怎样才能避免棉花糖 6 中出现这样的问题?我希望得到与预棉花糖相同的结果。

p/s 我在https://code.google.com/p/android/issues/detail?id=191187提交了一份报告也是。

更新

2015 年 12 月 9 日,Google 已修复此问题,并将在 Android 6.0.1 中发布 - https://code.google.com/p/android/issues/detail?id=191187

最佳答案

TL;DR 此问题是由 StaticLayoutgenerate 方法中的错误引起的。

该错误与我最初的想法有点不同,它不会影响所有行,只会影响放大字符之后的行,如屏幕截图所示:

enter image description here

在 Marshmallow 中添加了一个 FontMetrics 缓存以避免重新计算,正如 source code 中的注释所解释的那样:

// measurement has to be done before performing line breaking
// but we don't want to recompute fontmetrics or span ranges the
// second time, so we cache those and then use those stored values

不幸的是,缓存中可用的 fm.descent 值如果低于之前的缓存值,就会被丢弃,如您在 snippet 中所见:

for (int spanStart = paraStart, spanEnd; spanStart < paraEnd; spanStart = spanEnd) {
    // retrieve end of span
    spanEnd = spanEndCache[spanEndCacheIndex++];

    // retrieve cached metrics, order matches above
    fm.top = fmCache[fmCacheIndex * 4 + 0];
    fm.bottom = fmCache[fmCacheIndex * 4 + 1];
    fm.ascent = fmCache[fmCacheIndex * 4 + 2];
    fm.descent = fmCache[fmCacheIndex * 4 + 3];
    fmCacheIndex++;

    if (fm.top < fmTop) {
        fmTop = fm.top;
    }
    if (fm.ascent < fmAscent) {
        fmAscent = fm.ascent;
    }
    if (fm.descent > fmDescent) {
        fmDescent = fm.descent;
    }
    if (fm.bottom > fmBottom) {
        fmBottom = fm.bottom;
    }

    ....

一旦该值达到最大值,它就永远不会减少,这就是为什么后面的每一行都有增加的行间距。

关于android - 放大 SpannableString 中的单个字符会影响行间距(仅在 Marshmallow 中),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33252090/

相关文章:

android - Sinch SDK - 如何注销用户?

java - 将数据从 Android 应用连接并插入到预先存在的 MS SQL 数据库

android - 从 android 联系人中检索名字和姓氏导致 '1' 和 'null'

java - Android 中按钮的最小高度是否有硬性限制?

java - 将方法返回类型设置为 'void' 。不太明白

android - Espresso 自动生成的测试失败

android - 在 "Theme.Holo.DialogWhenLarge"模式下启动新 Activity 时对话框变窄

android - 如何获取所有正在运行的 Activity 的列表并选择从暂停到开始状态的任何 Activity ?

java - 使用屏幕导航按钮移动位图对象

java - 在android中显示电子邮件(JavaMail Message)的最佳方式