升级到target35 StaticLayout的坑

152 阅读1分钟

问题

image.png

之前自定义view画出来的字,也就是这个电池百分比突然换行了。因为是使用的StaticLayout直接进行布局后绘制在Canvas上的,一直没出过问题感觉很奇怪所以调查了以下经过

StaticLayout

自定义view在做文本多行绘制的时候会使用StaticLayout来进行构建。可以自动换行等。

StaticLayout创建

老版本的时候StaticLayout创建是直接new出来的

mTextLayout = new StaticLayout(mText, mPaint, mTextWidth, Alignment.ALIGN_OPPOSITE,
        mSpacingMult, mSpacingAdd, false);

其中mText为显示文本,mPaint画笔,mTextWidth测量出来的文字宽度,右布局。

在需要绘制的地方直接绘制即可

mTextLayout.draw(c);

后来发现new的方式被废弃了改为使用Builder来创建

StaticLayout.Builder builder = StaticLayout.Builder.obtain(mText, 0, mText.length(), mPaint, mTextWidth)
        .setAlignment(Alignment.ALIGN_OPPOSITE)
        .setLineSpacing(mSpacingAdd, mSpacingMult)
        .setIncludePad(false);

这里本来还没什么问题,但是在后续我将target升级到35后发现,文字有时候会自动换行了,明明宽度字数都没有变化。调查后发现是35时候Builder新增了一个属性导致

/**
 * Set true for using width of bounding box as a source of automatic line breaking and
 * drawing.
 *
 * If this value is false, the Layout determines the drawing offset and automatic line
 * breaking based on total advances. By setting true, use all joined glyph's bounding boxes
 * as a source of text width.
 *
 * If the font has glyphs that have negative bearing X or its xMax is greater than advance,
 * the glyph clipping can happen because the drawing area may be bigger. By setting this to
 * true, the Layout will reserve more spaces for drawing.
 *
 * @param useBoundsForWidth True for using bounding box, false for advances.
 * @return this builder instance
 * @see Layout#getUseBoundsForWidth()
 * @see Layout.Builder#setUseBoundsForWidth(boolean)
 */
@NonNull
@FlaggedApi(FLAG_USE_BOUNDS_FOR_WIDTH)
public Builder setUseBoundsForWidth(boolean useBoundsForWidth) {
    mUseBoundsForWidth = useBoundsForWidth;
    return this;
}

将setUseBoundsForWidth设置为false解决