in litho-core/src/main/java/com/facebook/litho/LithoView.java [497:600]
private void onMeasureInternal(int widthMeasureSpec, int heightMeasureSpec) {
widthMeasureSpec =
DoubleMeasureFixUtil.correctWidthSpecForAndroidDoubleMeasureBug(
getResources(), getContext().getPackageManager(), widthMeasureSpec);
// mAnimatedWidth/mAnimatedHeight >= 0 if something is driving a width/height animation.
final boolean animating = mAnimatedWidth != -1 || mAnimatedHeight != -1;
// up to date view sizes, taking into account running animations
final int upToDateWidth = (mAnimatedWidth != -1) ? mAnimatedWidth : getWidth();
final int upToDateHeight = (mAnimatedHeight != -1) ? mAnimatedHeight : getHeight();
mAnimatedWidth = -1;
mAnimatedHeight = -1;
if (animating) {
// If the mount state is dirty, we want to ignore the current animation and calculate the
// new LayoutState as normal below. That LayoutState has the opportunity to define its own
// transition to a new width/height from the current height of the LithoView, or if not we
// will jump straight to that width/height.
if (!isMountStateDirty()) {
setMeasuredDimension(upToDateWidth, upToDateHeight);
return;
}
}
LayoutParams layoutParams = getLayoutParams();
if (layoutParams instanceof LayoutManagerOverrideParams) {
LayoutManagerOverrideParams layoutManagerOverrideParams =
(LayoutManagerOverrideParams) layoutParams;
final int overrideWidthSpec = layoutManagerOverrideParams.getWidthMeasureSpec();
if (overrideWidthSpec != LayoutManagerOverrideParams.UNINITIALIZED) {
widthMeasureSpec = overrideWidthSpec;
}
final int overrideHeightSpec = layoutManagerOverrideParams.getHeightMeasureSpec();
if (overrideHeightSpec != LayoutManagerOverrideParams.UNINITIALIZED) {
heightMeasureSpec = overrideHeightSpec;
}
}
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
if (mTemporaryDetachedComponent != null && mComponentTree == null) {
setComponentTree(mTemporaryDetachedComponent);
mTemporaryDetachedComponent = null;
}
if (!mForceLayout
&& SizeSpec.getMode(widthMeasureSpec) == SizeSpec.EXACTLY
&& SizeSpec.getMode(heightMeasureSpec) == SizeSpec.EXACTLY) {
// If the measurements are exact, postpone LayoutState calculation from measure to layout.
// This is part of the fix for android's double measure bug. Doing this means that if we get
// remeasured with different exact measurements, we don't compute two layouts.
mDoMeasureInLayout = true;
setMeasuredDimension(width, height);
return;
}
mIsMeasuring = true;
if (mComponentTree != null && !mSuppressMeasureComponentTree) {
boolean forceRelayout = mForceLayout;
mForceLayout = false;
mComponentTree.measure(
adjustMeasureSpecForPadding(widthMeasureSpec, getPaddingRight() + getPaddingLeft()),
adjustMeasureSpecForPadding(heightMeasureSpec, getPaddingTop() + getPaddingBottom()),
sLayoutSize,
forceRelayout);
width = sLayoutSize[0];
height = sLayoutSize[1];
mDoMeasureInLayout = false;
}
if (height == 0) {
maybeLogInvalidZeroHeight();
}
final boolean canAnimateRootBounds =
!mSuppressMeasureComponentTree
&& mComponentTree != null
&& (!mHasNewComponentTree || !mComponentTree.hasMounted());
if (canAnimateRootBounds) {
// We might need to collect transitions before mount to know whether this LithoView has
// width or height animation.
mComponentTree.maybeCollectTransitions();
final int initialAnimatedWidth =
mComponentTree.getInitialAnimatedLithoViewWidth(upToDateWidth, mHasNewComponentTree);
if (initialAnimatedWidth != -1) {
width = initialAnimatedWidth;
}
final int initialAnimatedHeight =
mComponentTree.getInitialAnimatedLithoViewHeight(upToDateHeight, mHasNewComponentTree);
if (initialAnimatedHeight != -1) {
height = initialAnimatedHeight;
}
}
setMeasuredDimension(width, height);
mHasNewComponentTree = false;
mIsMeasuring = false;
}