From the official docs:
Android Docs - View
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
Why my custom view is called repetitively with changed=false
? Is it normal?
Here's the call tree:
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]
The key part here from the docs is:
Called from layout when this view should assign a size and position to each of its children.
If a View inside a ViewGroup is set to wrap_content and it changes its size (e.g. the text inside a TextView changes to a longer string) then an onLayout in the ViewGroup will occur. This is because Views are given their size when laid out, so without the call the View will never be given a new size.
I found the problem: for a compound component like mine, that contains a TextView
, the repetitive call to .setText()
causes a call to the parent's onLayout()
...even if the new text is equal to the current TextView
text!
so I solved:
public void setTextViewText(String text) {
if (!this.textViewValue.getText().equals(text)) {
this.textViewValue.setText(text);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With