我有一个自定义视图,我很快学会了不进行对象分配,并将所有Paint分配移动到另一个方法中,很好。
我需要使用StaticLayout,但是对于某些应用了某些spannable'stuff'的文本。
layoutBpm = new StaticLayout(bpmValue,
textPaintBPM, arcRadius, Layout.Alignment.ALIGN_NORMAL, 0, 1,
false);
layoutBpm.draw(canvas);
这对我来说似乎对onDraw很有意义,但我当然会收到警告以避免这种情况。对我来说,尽我所能避免任何性能问题对我来说很重要,所以我正在努力做到这一点。
我似乎无法找到任何我能理解的文档,它解释了StaticLayout实际上做了哪些参数(float spacingmult?float spacingadd?),但我认为第三个是StaticLayout文本的最大宽度我只能从onMeasure获得,因为它与我的画布大小有关。这让我想把作业放在onMeasure或onDraw上,这似乎都不是我想做的。是否可以在onDraw中放置StaticLayout赋值,或者有更好的方法吗?
希望这是有道理的,我对此非常陌生。感谢您的任何帮助。
(编辑:我假设将这个赋值放在一个方法中并且从onDraw / onMeasure调用只是愚蠢而且会阻止Eclipse警告我但实际上不会有帮助吗?)
答案 0 :(得分:5)
警告的原因是,通常,您不需要在绘制操作中多次重新创建对象。与onDraw()
中的其他方法相比,View
可以被调用数百次。大多数情况下,正在使用精确参数重新创建正在重新创建的对象。其他时候,改变对象状态的开销比创建新对象的开销要少。
对于StaticLayout
,您只需在文本更改或调整填充,间距或最大宽度时创建新的。如果文本经常更改,那么您可能需要考虑每次都会重新测量的DynamicLayout
。重新计算成本比创建新对象的成本更高,但是它不会比onDraw()
调用更频繁地发生。
如果文本没有经常更改,并且您绝对必须使用StaticLayout,那么您可以使用类似这种结构的东西。
StaticLayout myLayout;
String textSource = defaultSource;
Paint textPaint = defaultPaint;
int textWidth = defaultWidth;
public CustomView(Context ctx) {
super(ctx);
createLayout();
}
public void setText(String text) {
textSource = text;
createLayout();
}
public void setWidth(int width) {
textWidth = width;
createLayout();
}
@Override
public void onDraw(Canvas canvas) {
myLayout.draw(canvas);
}
private void createLayout() {
myLayout = new StaticLayout(textSource, textPaint, textWidth, Layout.Alignment.ALIGN_NORMAL, 0, 1, false);
}
基本上,只有在发生变化时才会创建新的布局。否则,您只需重复使用您创建的最后一个对象。
EDIT:
跳过度量传递的一种方法是在新调整大小的视图本身上调用View#measure
。所以你的createLayout()
方法会是这样的。
private void createLayout() {
myLayout = new StaticLayout(textSource, textPaint, textWidth, Layout.Alignment.ALIGN_NORMAL, 0, 1, false);
int textWidthSpec = MeasureSpec.makeMeasureSpec(maxLayoutWidth, MeasureSpec.AT_MOST);
int textHeightSpec = MeasureSpec.makeMeasureSpec(maxLayoutHeight, MeasureSpec.AT_MOST);
myLayout.measure(textWidthSpec, textHeightSpec);
forceLayout();
}
基本上它的作用是告诉布局View的最大值。它将衡量自己和它的孩子。将在父(您的自定义视图)上调用forceLayout(),它将根据新测量值重新布局其他内容。
我应该注意到我从未使用StaticLayout做过这个,所以我不知道会发生什么。看起来这种类型的测量可能已经在创建视图时处理,但可能没有。
我希望这会有所帮助。