我有一个自定义 View ,我很快学会了不进行对象分配,并将所有Paint分配都移到了另一种方法中,很好。
但是,对于某些应用了一些跨度“填充”的文本,我需要使用StaticLayout。
layoutBpm = new StaticLayout(bpmValue,
textPaintBPM, arcRadius, Layout.Alignment.ALIGN_NORMAL, 0, 1,
false);
layoutBpm.draw(canvas);
在onDraw中,这对我来说似乎很有意义,但是我当然会被警告避免这种情况。对我来说,重要的是我会尽一切可能避免任何性能问题,因此我正在尝试正确地做到这一点。
我似乎找不到任何我能理解的文档,该文档解释了StaticLayout实际执行的某些参数(float intervalmult?float intervaladd?),但是我认为其中的第三个参数是StaticLayout文本的最大宽度,我只能从onMeasure获得,因为它与我的 Canvas 大小有关。这让我想将任务放在onMeasure或onDraw中,这似乎都不是我要做的。可以将StaticLayout分配放在onDraw上吗?或者有更好的方法吗?
希望这是有道理的,我对此很陌生。感谢您的任何帮助。
(编辑:我假设将这种分配放在一个方法中,并从onDraw/onMeasure调用只是愚蠢的,并且会停止Eclipse警告我,但实际上没有帮助吗?)
最佳答案
警告的原因是,通常,您不需要在绘制操作中多次重新创建对象。与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 本身上调用
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的最大数量。它会衡量自己,并且是 child 。将在父级(您的自定义 View )上调用forceLayout(),该父级将根据新的度量重新布局其他内容。
我应该注意,我从未使用StaticLayout做到这一点,所以我不知道会发生什么。似乎在创建 View 时可能已经处理了这种类型的测量,但也许没有。
我希望这有帮助。