* commit '73dc2602898a300306ad418ca5bec990f0de877f': LayoutLib: Fix issue with rendering mode.
This commit is contained in:
@@ -372,8 +372,6 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
|
|||||||
if (mViewRoot == null) {
|
if (mViewRoot == null) {
|
||||||
return ERROR_NOT_INFLATED.createResult();
|
return ERROR_NOT_INFLATED.createResult();
|
||||||
}
|
}
|
||||||
// measure the views
|
|
||||||
int w_spec, h_spec;
|
|
||||||
|
|
||||||
RenderingMode renderingMode = params.getRenderingMode();
|
RenderingMode renderingMode = params.getRenderingMode();
|
||||||
|
|
||||||
@@ -385,38 +383,64 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
|
|||||||
mMeasuredScreenHeight = params.getScreenHeight();
|
mMeasuredScreenHeight = params.getScreenHeight();
|
||||||
|
|
||||||
if (renderingMode != RenderingMode.NORMAL) {
|
if (renderingMode != RenderingMode.NORMAL) {
|
||||||
// measure the full size needed by the layout.
|
int widthMeasureSpecMode = renderingMode.isHorizExpand() ?
|
||||||
w_spec = MeasureSpec.makeMeasureSpec(mMeasuredScreenWidth,
|
MeasureSpec.UNSPECIFIED // this lets us know the actual needed size
|
||||||
renderingMode.isHorizExpand() ?
|
: MeasureSpec.EXACTLY;
|
||||||
MeasureSpec.UNSPECIFIED // this lets us know the actual needed size
|
int heightMeasureSpecMode = renderingMode.isVertExpand() ?
|
||||||
: MeasureSpec.EXACTLY);
|
MeasureSpec.UNSPECIFIED // this lets us know the actual needed size
|
||||||
h_spec = MeasureSpec.makeMeasureSpec(mMeasuredScreenHeight,
|
: MeasureSpec.EXACTLY;
|
||||||
renderingMode.isVertExpand() ?
|
|
||||||
MeasureSpec.UNSPECIFIED // this lets us know the actual needed size
|
|
||||||
: MeasureSpec.EXACTLY);
|
|
||||||
mViewRoot.measure(w_spec, h_spec);
|
|
||||||
|
|
||||||
|
// We used to compare the measured size of the content to the screen size but
|
||||||
|
// this does not work anymore due to the 2 following issues:
|
||||||
|
// - If the content is in a decor (system bar, title/action bar), the root view
|
||||||
|
// will not resize even with the UNSPECIFIED because of the embedded layout.
|
||||||
|
// - If there is no decor, but a dialog frame, then the dialog padding prevents
|
||||||
|
// comparing the size of the content to the screen frame (as it would not
|
||||||
|
// take into account the dialog padding).
|
||||||
|
|
||||||
|
// The solution is to first get the content size in a normal rendering, inside
|
||||||
|
// the decor or the dialog padding.
|
||||||
|
// Then measure only the content with UNSPECIFIED to see the size difference
|
||||||
|
// and apply this to the screen size.
|
||||||
|
|
||||||
|
// first measure the full layout, with EXACTLY to get the size of the
|
||||||
|
// content as it is inside the decor/dialog
|
||||||
|
Pair<Integer, Integer> exactMeasure = measureView(
|
||||||
|
mViewRoot, mContentRoot.getChildAt(0),
|
||||||
|
mMeasuredScreenWidth, MeasureSpec.EXACTLY,
|
||||||
|
mMeasuredScreenHeight, MeasureSpec.EXACTLY);
|
||||||
|
|
||||||
|
// now measure the content only using UNSPECIFIED (where applicable, based on
|
||||||
|
// the rendering mode). This will give us the size the content needs.
|
||||||
|
Pair<Integer, Integer> result = measureView(
|
||||||
|
mContentRoot, mContentRoot.getChildAt(0),
|
||||||
|
mMeasuredScreenWidth, widthMeasureSpecMode,
|
||||||
|
mMeasuredScreenHeight, heightMeasureSpecMode);
|
||||||
|
|
||||||
|
// now look at the difference and add what is needed.
|
||||||
if (renderingMode.isHorizExpand()) {
|
if (renderingMode.isHorizExpand()) {
|
||||||
int neededWidth = mViewRoot.getChildAt(0).getMeasuredWidth();
|
int measuredWidth = exactMeasure.getFirst();
|
||||||
if (neededWidth > mMeasuredScreenWidth) {
|
int neededWidth = result.getFirst();
|
||||||
mMeasuredScreenWidth = neededWidth;
|
if (neededWidth > measuredWidth) {
|
||||||
|
mMeasuredScreenWidth += neededWidth - measuredWidth;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (renderingMode.isVertExpand()) {
|
if (renderingMode.isVertExpand()) {
|
||||||
int neededHeight = mViewRoot.getChildAt(0).getMeasuredHeight();
|
int measuredHeight = exactMeasure.getSecond();
|
||||||
if (neededHeight > mMeasuredScreenHeight) {
|
int neededHeight = result.getSecond();
|
||||||
mMeasuredScreenHeight = neededHeight;
|
if (neededHeight > measuredHeight) {
|
||||||
|
mMeasuredScreenHeight += neededHeight - measuredHeight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// remeasure with the size we need
|
// measure again with the size we need
|
||||||
// This must always be done before the call to layout
|
// This must always be done before the call to layout
|
||||||
w_spec = MeasureSpec.makeMeasureSpec(mMeasuredScreenWidth, MeasureSpec.EXACTLY);
|
measureView(mViewRoot, null /*measuredView*/,
|
||||||
h_spec = MeasureSpec.makeMeasureSpec(mMeasuredScreenHeight, MeasureSpec.EXACTLY);
|
mMeasuredScreenWidth, MeasureSpec.EXACTLY,
|
||||||
mViewRoot.measure(w_spec, h_spec);
|
mMeasuredScreenHeight, MeasureSpec.EXACTLY);
|
||||||
|
|
||||||
// now do the layout.
|
// now do the layout.
|
||||||
mViewRoot.layout(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight);
|
mViewRoot.layout(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight);
|
||||||
@@ -493,6 +517,34 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes {@link View#measure(int, int)} on a given view with the given parameters (used
|
||||||
|
* to create measure specs with {@link MeasureSpec#makeMeasureSpec(int, int)}.
|
||||||
|
*
|
||||||
|
* if <var>measuredView</var> is non null, the method returns a {@link Pair} of (width, height)
|
||||||
|
* for the view (using {@link View#getMeasuredWidth()} and {@link View#getMeasuredHeight()}).
|
||||||
|
*
|
||||||
|
* @param viewToMeasure the view on which to execute measure().
|
||||||
|
* @param measuredView if non null, the view to query for its measured width/height.
|
||||||
|
* @param width the width to use in the MeasureSpec.
|
||||||
|
* @param widthMode the MeasureSpec mode to use for the width.
|
||||||
|
* @param height the height to use in the MeasureSpec.
|
||||||
|
* @param heightMode the MeasureSpec mode to use for the height.
|
||||||
|
* @return the measured width/height if measuredView is non-null, null otherwise.
|
||||||
|
*/
|
||||||
|
private Pair<Integer, Integer> measureView(ViewGroup viewToMeasure, View measuredView,
|
||||||
|
int width, int widthMode, int height, int heightMode) {
|
||||||
|
int w_spec = MeasureSpec.makeMeasureSpec(width, widthMode);
|
||||||
|
int h_spec = MeasureSpec.makeMeasureSpec(height, heightMode);
|
||||||
|
viewToMeasure.measure(w_spec, h_spec);
|
||||||
|
|
||||||
|
if (measuredView != null) {
|
||||||
|
return Pair.of(measuredView.getMeasuredWidth(), measuredView.getMeasuredHeight());
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Animate an object
|
* Animate an object
|
||||||
* <p>
|
* <p>
|
||||||
|
|||||||
Reference in New Issue
Block a user