在字符级别更改 EditText 中的前导/行高

Change leading / line height in EditText at a character level

我在我的 EditText 的开头和结尾实现了加粗、大、不可编辑的 "smart quotes":

引号是文本中不可选择的部分,我在其上设置了RelativeSizeSpan(2f)。结果跟我想要的差不多

s.setSpan(spanLeft, 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
s.setSpan(spanRight, s.length() - 1, s.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

然而,正如您所看到的,较大的字体会导致较大的高度影响整行。这在某种程度上在第一行是无关紧要的,但在最后一行却令人不快。我想知道是否有可能,对于这两个字符,保持字体大小但降低行高。

我想减少 leading 部分,以便第一行和最后一行与段落的其余部分具有一致的高度。我最大的愿望是让引语在保持其外观的同时转化为基线。

你有什么建议吗?这可能通过一些 Span 在那里吗?我该放弃吗?您看到任何解决方法了吗?

我知道我可以创建两个带有引号的 png 并使用 ImageSpan(虽然我从未使用过它并且不知道它是如何工作的),但这对我来说有点烦人(我不是很喜欢图形)。

我在我的一个应用程序中创建了类似的效果,其中我有一个跨度,使跨度文本变小,并使其坚持主文本的 x 高度,偏离基线。我创建了一个扩展 MetricAffectingSpan 并实现基线偏移的自定义跨度。我使用 Android SDK 中的 SuperscriptSpan.java 作为示例。

本例的想法是拉低大端引用的基线,使总行高降低。我不是 100% 确定这会起作用,因为我不知道如何 "clever" 行高计算。

如果有效,请务必在多种屏幕密度下进行测试。我必须在其中某处制作 float 适合 int,这引入了舍入误差,该误差在某些密度上非常明显,我们必须对其进行校正。

我认为您必须实施自定义 Span,只需将 updateMeasureState 留空即可:)
尝试

import android.text.TextPaint;
import android.text.style.MetricAffectingSpan;

public class TestSubScriptSpan extends MetricAffectingSpan {

    private final float mProportion;

    public TestSubScriptSpan(float proportion) {
        mProportion = proportion;
    }

    @Override
    public void updateMeasureState(TextPaint p) {
        // DO NOTHING!
    }

    @Override
    public void updateDrawState(TextPaint tp) {
        tp.setTextSize(tp.getTextSize() * mProportion);
        tp.baselineShift -= (int) (tp.ascent() / 2);
    }
}

然后

TestSubScriptSpan tss = new TestSubScriptSpan(2.0f);
s.setSpan(tss, 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
s.setSpan(tss, s.length() - 1, s.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

注意您在 updateDrawState() 中执行的操作的顺序,因为它很重要。