9

来自官方文档:

Android 文档 - 查看

protected void onLayout (boolean changed, int left, int top, int right, int bottom)

Parameters
changed This is a new size or position for this view
left    Left position, relative to parent
top     Top position, relative to parent
right   Right position, relative to parent
bottom  Bottom position, relative to parent 

为什么我的自定义视图被重复调用changed=false?正常吗?

这是调用树:

Synoptic.onLayout(boolean, int, int, int, int) line: 130    
Synoptic(View).layout(int, int, int, int) line: 11282   
Synoptic(ViewGroup).layout(int, int, int, int) line: 4224   
RelativeLayout.onLayout(boolean, int, int, int, int) line: 925  
RelativeLayout(View).layout(int, int, int, int) line: 11282 
RelativeLayout(ViewGroup).layout(int, int, int, int) line: 4224 
LinearLayout.setChildFrame(View, int, int, int, int) line: 1628 
LinearLayout.layoutHorizontal() line: 1617  
LinearLayout.onLayout(boolean, int, int, int, int) line: 1401   
LinearLayout(View).layout(int, int, int, int) line: 11282   
LinearLayout(ViewGroup).layout(int, int, int, int) line: 4224   
SwipeView(FrameLayout).onLayout(boolean, int, int, int, int) line: 431  
SwipeView(HorizontalScrollView).onLayout(boolean, int, int, int, int) line: 1382    
SwipeView.onLayout(boolean, int, int, int, int) line: 154   
SwipeView(View).layout(int, int, int, int) line: 11282  
SwipeView(ViewGroup).layout(int, int, int, int) line: 4224  
LinearLayout.setChildFrame(View, int, int, int, int) line: 1628 
LinearLayout.layoutVertical() line: 1486    
LinearLayout.onLayout(boolean, int, int, int, int) line: 1399   
LinearLayout(View).layout(int, int, int, int) line: 11282   
LinearLayout(ViewGroup).layout(int, int, int, int) line: 4224   
FrameLayout.onLayout(boolean, int, int, int, int) line: 431 
FrameLayout(View).layout(int, int, int, int) line: 11282    
FrameLayout(ViewGroup).layout(int, int, int, int) line: 4224    
LinearLayout.setChildFrame(View, int, int, int, int) line: 1628 
LinearLayout.layoutVertical() line: 1486    
LinearLayout.onLayout(boolean, int, int, int, int) line: 1399   
LinearLayout(View).layout(int, int, int, int) line: 11282   
LinearLayout(ViewGroup).layout(int, int, int, int) line: 4224   
PhoneWindow$DecorView(FrameLayout).onLayout(boolean, int, int, int, int) line: 431  
PhoneWindow$DecorView(View).layout(int, int, int, int) line: 11282  
PhoneWindow$DecorView(ViewGroup).layout(int, int, int, int) line: 4224  
ViewRootImpl.performTraversals() line: 1514 
ViewRootImpl.handleMessage(Message) line: 2467  
ViewRootImpl(Handler).dispatchMessage(Message) line: 99 
Looper.loop() line: 137 
ActivityThread.main(String[]) line: 4424    
Method.invokeNative(Object, Object[], Class, Class[], Class, int, boolean) line: not available [native method]  
Method.invoke(Object, Object...) line: 511  
ZygoteInit$MethodAndArgsCaller.run() line: 784  
ZygoteInit.main(String[]) line: 551 
NativeStart.main(String[]) line: not available [native method]  
4

2 回答 2

12

文档中的关键部分是:

当此视图应为其每个子项分配大小和位置时,从布局中调用。

如果 ViewGroup 中的 View 设置为 wrap_content 并且它改变了它的大小(例如 TextView 中的文本更改为更长的字符串),那么 ViewGroup 中的 onLayout 将发生。这是因为视图在布局时被赋予了它们的大小,所以如果没有调用,视图将永远不会被赋予新的大小。

于 2013-10-07T17:42:48.287 回答
8

我发现了问题:对于像我这样的复合组件,它包含 a TextView,重复调用会.setText()导致调用父级的onLayout()

...即使新文本等于当前TextView文本!

所以我解决了:

public void setTextViewText(String text) {
    if (!this.textViewValue.getText().equals(text)) {
        this.textViewValue.setText(text);
    }
}
于 2013-10-17T15:00:11.473 回答