在静态布局上设置最大行数


StaticLayout.Builder

是在API 23 中引入的,我想定位得更低。如何使用原始构造函数设置最大行数StaticLayout

引用上的属性似乎都是只读的。

在 API 22 之后的 StaticLayout 类中,仍然有一个隐藏的构造函数,它接受许多参数:

/**
* @hide
* @deprecated Use {@link Builder} instead.
*/
@Deprecated
public StaticLayout(CharSequence source, int bufstart, int bufend,
TextPaint paint, int outerwidth,
Alignment align, TextDirectionHeuristic textDir,
float spacingmult, float spacingadd,
boolean includepad,
TextUtils.TruncateAt ellipsize, int ellipsizedWidth,
int maxLines)

如您所见,最后一个参数是最大行数。

这个构造函数是隐藏的,似乎无法在较旧的 API 中使用它。我甚至尝试使用反射设置私人字段mMaximumVisibleLineCount,但没有成功。但是我找到了向后兼容的解决方案,可以省略字符串并创建StaticLayoutlineCount直到返回所需的值。

fun createStaticLayout(text: String, textWidth: Int, maxLines: Int, paint: TextPaint): StaticLayout =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
StaticLayout.Builder
.obtain(text, 0, text.length, paint, textWidth)
.setAlignment(Layout.Alignment.ALIGN_NORMAL)
.setMaxLines(maxLines)
.setEllipsize(TextUtils.TruncateAt.END)
.build()
} else {
var layout: StaticLayout? = null
var maxLength: Int = min(text.length, 200) // Could be adjusted
do {
layout = StaticLayout(
text.ellipsize(maxLength), paint, textWidth,
Layout.Alignment.ALIGN_NORMAL, 1f, 0f,
false
)
maxLength -= 10
} while (layout!!.lineCount > maxLines)
layout
}
///.....
fun String.ellipsize(
size: Int,
ending: Char? = '…'
): String = if (this.isEmpty() || size <= 0) {
""
} else if (length <= size) {
this
} else {
this.substring(0, max(size - 1, 0)).let {
if (ending == null) {
it
} else {
it + ending
}
}
}

我发现的唯一方法是使用 Reflection 访问第四个构造函数,该构造函数接受在最后一个参数中设置maxLines,它对我有用:

try {
Constructor<StaticLayout> constructor = StaticLayout.class.getConstructor(
CharSequence.class, int.class, int.class, TextPaint.class, int.class,
Layout.Alignment.class, TextDirectionHeuristic.class, float.class, float.class,
boolean.class, TextUtils.TruncateAt.class, int.class, int.class
);
constructor.setAccessible(true);
StaticLayout sl = constructor.newInstance(text, 0, text.length(), textPaint, width,
aligment, TextDirectionHeuristics.FIRSTSTRONG_LTR, spacingMult, spacingAdd,
includePad, TextUtils.TruncateAt.END, width, maxLines);
} catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException exception) {
Log.d("TAG_APP", Log.getStackTraceString(exception));
}

最新更新