summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorXavier Ducrohet <xav@android.com>2011-04-05 20:19:17 -0700
committerXavier Ducrohet <xav@android.com>2011-04-05 20:45:48 -0700
commitc5aeac7f157e3cb9e29ab8c126f74e26493501f5 (patch)
tree7767282c829748563f5dbb1026972395ec0a2052 /tools
parente4cafabbcc4b69479217d1a167926b79c37e5ded (diff)
downloadframeworks_base-c5aeac7f157e3cb9e29ab8c126f74e26493501f5.zip
frameworks_base-c5aeac7f157e3cb9e29ab8c126f74e26493501f5.tar.gz
frameworks_base-c5aeac7f157e3cb9e29ab8c126f74e26493501f5.tar.bz2
LayoutLib: Fix issue with rendering mode.
When the layout content is embedded inside a decor layout to emulate system bar (top or bottom) and title bar (or action bar) then the code computing the full required size based on the RenderingMode would fail because the decor layout would prevents the content layout to take as much room as possible. There is also an issue with the way we know render dialogs as the dialogs usually as a frame with some padding and the previous measurements would not take into account the dialog padding when increasing the screen size. This fix makes the code measure the size of the content layout in the normal rendering, and then separately from the root layout with the proper MeasureSpec to let the content grown. The difference in size is then added to the screen size. Bug: http://code.google.com/p/android/issues/detail?id=15892 Change-Id: Ibb9ca2a67c6c450d10d9f9a8050536e094650f8b
Diffstat (limited to 'tools')
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java98
1 files changed, 75 insertions, 23 deletions
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index 2fd58e4..c5eaef9 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -372,8 +372,6 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
if (mViewRoot == null) {
return ERROR_NOT_INFLATED.createResult();
}
- // measure the views
- int w_spec, h_spec;
RenderingMode renderingMode = params.getRenderingMode();
@@ -385,38 +383,64 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
mMeasuredScreenHeight = params.getScreenHeight();
if (renderingMode != RenderingMode.NORMAL) {
- // measure the full size needed by the layout.
- w_spec = MeasureSpec.makeMeasureSpec(mMeasuredScreenWidth,
- renderingMode.isHorizExpand() ?
- MeasureSpec.UNSPECIFIED // this lets us know the actual needed size
- : MeasureSpec.EXACTLY);
- h_spec = MeasureSpec.makeMeasureSpec(mMeasuredScreenHeight,
- renderingMode.isVertExpand() ?
- MeasureSpec.UNSPECIFIED // this lets us know the actual needed size
- : MeasureSpec.EXACTLY);
- mViewRoot.measure(w_spec, h_spec);
-
+ int widthMeasureSpecMode = renderingMode.isHorizExpand() ?
+ MeasureSpec.UNSPECIFIED // this lets us know the actual needed size
+ : MeasureSpec.EXACTLY;
+ int heightMeasureSpecMode = renderingMode.isVertExpand() ?
+ MeasureSpec.UNSPECIFIED // this lets us know the actual needed size
+ : MeasureSpec.EXACTLY;
+
+ // 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()) {
- int neededWidth = mViewRoot.getChildAt(0).getMeasuredWidth();
- if (neededWidth > mMeasuredScreenWidth) {
- mMeasuredScreenWidth = neededWidth;
+ int measuredWidth = exactMeasure.getFirst();
+ int neededWidth = result.getFirst();
+ if (neededWidth > measuredWidth) {
+ mMeasuredScreenWidth += neededWidth - measuredWidth;
}
}
if (renderingMode.isVertExpand()) {
- int neededHeight = mViewRoot.getChildAt(0).getMeasuredHeight();
- if (neededHeight > mMeasuredScreenHeight) {
- mMeasuredScreenHeight = neededHeight;
+ int measuredHeight = exactMeasure.getSecond();
+ int neededHeight = result.getSecond();
+ 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
- w_spec = MeasureSpec.makeMeasureSpec(mMeasuredScreenWidth, MeasureSpec.EXACTLY);
- h_spec = MeasureSpec.makeMeasureSpec(mMeasuredScreenHeight, MeasureSpec.EXACTLY);
- mViewRoot.measure(w_spec, h_spec);
+ measureView(mViewRoot, null /*measuredView*/,
+ mMeasuredScreenWidth, MeasureSpec.EXACTLY,
+ mMeasuredScreenHeight, MeasureSpec.EXACTLY);
// now do the layout.
mViewRoot.layout(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight);
@@ -494,6 +518,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
* <p>
* {@link #acquire(long)} must have been called before this.