Merge "remeasure when overlay views change size"
diff --git a/src/com/android/mail/browse/ConversationContainer.java b/src/com/android/mail/browse/ConversationContainer.java
index 1aeb4c6..e563bdd 100644
--- a/src/com/android/mail/browse/ConversationContainer.java
+++ b/src/com/android/mail/browse/ConversationContainer.java
@@ -17,8 +17,6 @@
package com.android.mail.browse;
-import com.google.common.collect.Sets;
-
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
@@ -35,6 +33,7 @@
import com.android.mail.browse.ScrollNotifier.ScrollListener;
import com.android.mail.utils.DequeMap;
import com.android.mail.utils.LogUtils;
+import com.google.common.collect.Sets;
import java.util.Set;
@@ -338,13 +337,22 @@
}
/**
+ * Executes a measure pass over the specified child overlay view and returns the measured
+ * height. The measurement uses whatever the current container's width measure spec is.
+ * This method ignores view visibility and returns the height that the view would be if visible.
+ *
+ * @param overlayView an overlay view to measure. does not actually have to be attached yet.
+ * @return height that the view would be if it was visible
+ */
+ public int measureOverlay(View overlayView) {
+ measureOverlayView(overlayView);
+ return overlayView.getMeasuredHeight();
+ }
+
+ /**
* Copied/stolen from {@link ListView}.
*/
- private void measureItem(View child) {
- if (child.getVisibility() == GONE) {
- return;
- }
-
+ private void measureOverlayView(View child) {
ViewGroup.LayoutParams p = child.getLayoutParams();
if (p == null) {
p = new ViewGroup.LayoutParams(
@@ -429,14 +437,8 @@
}
mWidthMeasureSpec = widthMeasureSpec;
- // Need to measure children in case this layout pass was triggered by a child layout change.
- // TODO: restrict child measurement to just that case.
- for (int i = 0, overlayCount = getOverlayCount(); i < overlayCount; i++) {
- final View overlayView = getOverlayAt(i);
- if (overlayView.getVisibility() != GONE) {
- measureItem(overlayView);
- }
- }
+ // onLayout will re-measure and re-position overlays for the new container size, but the
+ // spacer offsets would still need to be updated to have them draw at their new locations.
}
@Override
@@ -447,6 +449,12 @@
positionOverlays(0, mOffsetY);
}
+ @Override
+ public void requestLayout() {
+ // Suppress layouts requested by children. Overlays don't push on each other, and WebView
+ // doesn't change its layout.
+ }
+
private int getOverlayBottom(int spacerIndex) {
// TODO: round or truncate?
return (int) (mOverlayBottoms[spacerIndex] * mScale);
@@ -454,24 +462,34 @@
private void positionOverlay(int adapterIndex, int overlayTopY, int overlayBottomY) {
View overlayView = findExistingOverlayView(adapterIndex);
- final int itemType = mOverlayAdapter.getItemViewType(adapterIndex);
+ final ConversationItem item = mOverlayAdapter.getItem(adapterIndex);
+
// is the overlay visible and does it have non-zero height?
if (overlayTopY != overlayBottomY && overlayBottomY > mOffsetY
&& overlayTopY < mOffsetY + getHeight()) {
// show and/or move overlay
if (overlayView == null) {
overlayView = addOverlayView(adapterIndex);
- measureItem(overlayView);
- traceLayout("show overlay %d", adapterIndex);
+ measureOverlayView(overlayView);
+ item.markMeasurementValid();
+ traceLayout("show/measure overlay %d", adapterIndex);
} else {
traceLayout("move overlay %d", adapterIndex);
+ if (!item.isMeasurementValid()) {
+ measureOverlayView(overlayView);
+ item.markMeasurementValid();
+ traceLayout("and (re)measure overlay %d, old/new heights=%d/%d", adapterIndex,
+ overlayView.getHeight(), overlayView.getMeasuredHeight());
+ }
}
+ traceLayout("laying out overlay %d with h=%d", adapterIndex,
+ overlayView.getMeasuredHeight());
layoutOverlay(overlayView, overlayTopY);
} else {
// hide overlay
if (overlayView != null) {
traceLayout("hide overlay %d", adapterIndex);
- onOverlayScrolledOff(overlayView, itemType, overlayTopY, overlayBottomY);
+ onOverlayScrolledOff(overlayView, item.getType(), overlayTopY, overlayBottomY);
} else {
traceLayout("ignore non-visible overlay %d", adapterIndex);
}
@@ -485,10 +503,6 @@
// layout an existing view
// need its top offset into the conversation, its height, and the scroll offset
private void layoutOverlay(View child, int childTop, int childBottom) {
- if (child.getVisibility() == GONE) {
- return;
- }
-
final int top = childTop - mOffsetY;
final int bottom = childBottom - mOffsetY;
child.layout(0, top, child.getMeasuredWidth(), bottom);
diff --git a/src/com/android/mail/browse/ConversationViewAdapter.java b/src/com/android/mail/browse/ConversationViewAdapter.java
index 282e39e..2d09d22 100644
--- a/src/com/android/mail/browse/ConversationViewAdapter.java
+++ b/src/com/android/mail/browse/ConversationViewAdapter.java
@@ -35,7 +35,6 @@
import com.android.mail.providers.Message;
import com.android.mail.providers.UIProvider;
import com.android.mail.utils.LogUtils;
-import com.android.mail.utils.Utils;
import com.google.common.collect.Lists;
import java.util.List;
@@ -73,6 +72,7 @@
public static abstract class ConversationItem {
private int mHeight; // in px
+ private boolean mNeedsMeasure;
/**
* @see Adapter#getItemViewType(int)
@@ -96,15 +96,6 @@
public abstract boolean isContiguous();
/**
- * Measure the expected visible height of the overlay view. Even if the view is initially
- * GONE, this method must return whatever height the view is going to be when it is later
- * made VISIBLE.
- */
- public int measureHeight(View v, ViewGroup parent) {
- return Utils.measureViewHeight(v, parent);
- }
-
- /**
* This method's behavior is critical and requires some 'splainin.
* <p>
* Subclasses that return a zero-size height to the {@link ConversationContainer} will
@@ -120,7 +111,22 @@
public void setHeight(int h) {
LogUtils.i(LOG_TAG, "IN setHeight=%dpx of overlay item: %s", h, this);
- mHeight = h;
+ if (mHeight != h) {
+ mHeight = h;
+ mNeedsMeasure = true;
+ }
+ }
+
+ public boolean isMeasurementValid() {
+ return !mNeedsMeasure;
+ }
+
+ public void markMeasurementValid() {
+ mNeedsMeasure = false;
+ }
+
+ public void invalidateMeasurement() {
+ mNeedsMeasure = true;
}
}
diff --git a/src/com/android/mail/browse/ConversationViewHeader.java b/src/com/android/mail/browse/ConversationViewHeader.java
index 1ff04ba..1fdf732 100644
--- a/src/com/android/mail/browse/ConversationViewHeader.java
+++ b/src/com/android/mail/browse/ConversationViewHeader.java
@@ -169,11 +169,6 @@
}
}
- public int getPremeasuredHeight() {
- ViewGroup parent = (ViewGroup) getParent();
- return Utils.measureViewHeight(this, parent);
- }
-
@Override
public void onClick(View v) {
if (R.id.folders == v.getId()) {
diff --git a/src/com/android/mail/ui/ConversationViewFragment.java b/src/com/android/mail/ui/ConversationViewFragment.java
index 1f3ba50..aa2a1be 100644
--- a/src/com/android/mail/ui/ConversationViewFragment.java
+++ b/src/com/android/mail/ui/ConversationViewFragment.java
@@ -405,8 +405,9 @@
mConversationContainer.addScrapView(type, hostView);
}
- final int heightPx = convItem.measureHeight(hostView, mConversationContainer);
+ final int heightPx = mConversationContainer.measureOverlay(hostView);
convItem.setHeight(heightPx);
+ convItem.markMeasurementValid();
return (int) (heightPx / mDensity);
}