Merge "Fix for 5393156"

This commit is contained in:
Philip Milne
2011-09-29 15:01:27 -07:00
committed by Android (Google) Code Review
2 changed files with 102 additions and 63 deletions

View File

@@ -850,32 +850,65 @@ public class GridLayout extends ViewGroup {
return c.getVisibility() == View.GONE; return c.getVisibility() == View.GONE;
} }
private void measureChildWithMargins(View child, int widthMeasureSpec, int heightMeasureSpec) { private void measureChildWithMargins2(View child, int parentWidthSpec, int parentHeightSpec,
LayoutParams lp = getLayoutParams(child); int childWidth, int childHeight) {
int childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec, int childWidthSpec = getChildMeasureSpec(parentWidthSpec,
mPaddingLeft + mPaddingRight + getTotalMargin(child, true), lp.width); mPaddingLeft + mPaddingRight + getTotalMargin(child, true), childWidth);
int childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec, int childHeightSpec = getChildMeasureSpec(parentHeightSpec,
mPaddingTop + mPaddingBottom + getTotalMargin(child, false), lp.height); mPaddingTop + mPaddingBottom + getTotalMargin(child, false), childHeight);
child.measure(childWidthMeasureSpec, childHeightMeasureSpec); child.measure(childWidthSpec, childHeightSpec);
} }
private void measureChildrenWithMargins(int widthMeasureSpec, int heightMeasureSpec) { private void measureChildrenWithMargins(int widthSpec, int heightSpec, boolean firstPass) {
for (int i = 0, N = getChildCount(); i < N; i++) { for (int i = 0, N = getChildCount(); i < N; i++) {
View c = getChildAt(i); View c = getChildAt(i);
if (isGone(c)) continue; if (isGone(c)) continue;
measureChildWithMargins(c, widthMeasureSpec, heightMeasureSpec); LayoutParams lp = getLayoutParams(c);
if (firstPass) {
measureChildWithMargins2(c, widthSpec, heightSpec, lp.width, lp.height);
} else {
Spec spec = (orientation == HORIZONTAL) ? lp.columnSpec : lp.rowSpec;
if (spec.alignment == FILL) {
Interval span = spec.span;
Axis axis = (orientation == HORIZONTAL) ? horizontalAxis : verticalAxis;
int[] locations = axis.getLocations();
int size = locations[span.max] - locations[span.min];
if (orientation == HORIZONTAL) {
measureChildWithMargins2(c, widthSpec, heightSpec, size, lp.height);
} else {
measureChildWithMargins2(c, widthSpec, heightSpec, lp.width, size);
}
}
}
} }
} }
@Override @Override
protected void onMeasure(int widthSpec, int heightSpec) { protected void onMeasure(int widthSpec, int heightSpec) {
measureChildrenWithMargins(widthSpec, heightSpec); /** If we have been called by {@link View#measure(int, int)}, one of width or height
* is likely to have changed. We must invalidate if so. */
invalidateValues();
int width = getPaddingLeft() + horizontalAxis.getMeasure(widthSpec) + getPaddingRight(); measureChildrenWithMargins(widthSpec, heightSpec, true);
int height = getPaddingTop() + verticalAxis.getMeasure(heightSpec) + getPaddingBottom();
int measuredWidth = Math.max(width, getSuggestedMinimumWidth()); int width, height;
int measuredHeight = Math.max(height, getSuggestedMinimumHeight());
// Use the orientation property to decide which axis should be laid out first.
if (orientation == HORIZONTAL) {
width = horizontalAxis.getMeasure(widthSpec);
measureChildrenWithMargins(widthSpec, heightSpec, false);
height = verticalAxis.getMeasure(heightSpec);
} else {
height = verticalAxis.getMeasure(heightSpec);
measureChildrenWithMargins(widthSpec, heightSpec, false);
width = horizontalAxis.getMeasure(widthSpec);
}
int hPadding = getPaddingLeft() + getPaddingRight();
int vPadding = getPaddingTop() + getPaddingBottom();
int measuredWidth = Math.max(hPadding + width, getSuggestedMinimumWidth());
int measuredHeight = Math.max(vPadding + height, getSuggestedMinimumHeight());
setMeasuredDimension( setMeasuredDimension(
resolveSizeAndState(measuredWidth, widthSpec, 0), resolveSizeAndState(measuredWidth, widthSpec, 0),
@@ -1015,8 +1048,6 @@ public class GridLayout extends ViewGroup {
for the vertical one. for the vertical one.
*/ */
final class Axis { final class Axis {
private static final int MIN_VALUE = -1000000;
private static final int NEW = 0; private static final int NEW = 0;
private static final int PENDING = 1; private static final int PENDING = 1;
private static final int COMPLETE = 2; private static final int COMPLETE = 2;
@@ -1024,7 +1055,7 @@ public class GridLayout extends ViewGroup {
public final boolean horizontal; public final boolean horizontal;
public int definedCount = UNDEFINED; public int definedCount = UNDEFINED;
private int inferredCount = UNDEFINED; private int maxIndex = UNDEFINED;
PackedMap<Spec, Bounds> groupBounds; PackedMap<Spec, Bounds> groupBounds;
public boolean groupBoundsValid = false; public boolean groupBoundsValid = false;
@@ -1056,28 +1087,29 @@ public class GridLayout extends ViewGroup {
this.horizontal = horizontal; this.horizontal = horizontal;
} }
private int maxIndex() { private int calculateMaxIndex() {
// note the number Integer.MIN_VALUE + 1 comes up in undefined cells // the number Integer.MIN_VALUE + 1 comes up in undefined cells
int count = -1; int result = -1;
for (int i = 0, N = getChildCount(); i < N; i++) { for (int i = 0, N = getChildCount(); i < N; i++) {
View c = getChildAt(i); View c = getChildAt(i);
LayoutParams params = getLayoutParams(c); LayoutParams params = getLayoutParams(c);
Spec spec = horizontal ? params.columnSpec : params.rowSpec; Spec spec = horizontal ? params.columnSpec : params.rowSpec;
count = max(count, spec.span.min); Interval span = spec.span;
count = max(count, spec.span.max); result = max(result, span.min);
result = max(result, span.max);
} }
return count == -1 ? UNDEFINED : count; return result == -1 ? UNDEFINED : result;
} }
private int getInferredCount() { private int getMaxIndex() {
if (inferredCount == UNDEFINED) { if (maxIndex == UNDEFINED) {
inferredCount = max(0, maxIndex()); // if there are no cells, actual count is zero maxIndex = max(0, calculateMaxIndex()); // use zero when there are no children
} }
return inferredCount; return maxIndex;
} }
public int getCount() { public int getCount() {
return max(definedCount, getInferredCount()); return max(definedCount, getMaxIndex());
} }
public void setCount(int count) { public void setCount(int count) {
@@ -1179,7 +1211,7 @@ public class GridLayout extends ViewGroup {
} }
private void include(List<Arc> arcs, Interval key, MutableInt size, private void include(List<Arc> arcs, Interval key, MutableInt size,
boolean ignoreIfAlreadyPresent) { boolean ignoreIfAlreadyPresent) {
/* /*
Remove self referential links. Remove self referential links.
These appear: These appear:
@@ -1341,19 +1373,18 @@ public class GridLayout extends ViewGroup {
} }
private void init(int[] locations) { private void init(int[] locations) {
Arrays.fill(locations, MIN_VALUE); Arrays.fill(locations, 0);
locations[0] = 0;
} }
private String arcsToString(List<Arc> arcs) { private String arcsToString(List<Arc> arcs) {
String var = horizontal ? "c" : "r"; String var = horizontal ? "x" : "y";
StringBuilder result = new StringBuilder(); StringBuilder result = new StringBuilder();
boolean first = false; boolean first = true;
for(Arc arc : arcs) { for (Arc arc : arcs) {
if (!first) { if (first) {
first = true; first = false;
} else { } else {
result =result.append(", "); result = result.append(", ");
} }
int src = arc.span.min; int src = arc.span.min;
int dst = arc.span.max; int dst = arc.span.max;
@@ -1434,10 +1465,6 @@ public class GridLayout extends ViewGroup {
if (originalCulprits != null) { if (originalCulprits != null) {
logError(axisName, arcs, originalCulprits); logError(axisName, arcs, originalCulprits);
} }
if (DEBUG) {
Log.v(TAG, axisName + " iteration completed in " +
(1 + i) + " steps of " + N);
}
return; return;
} }
} }
@@ -1506,6 +1533,18 @@ public class GridLayout extends ViewGroup {
private void computeLocations(int[] a) { private void computeLocations(int[] a) {
solve(getArcs(), a); solve(getArcs(), a);
if (!orderPreserved) {
// Solve returns the smallest solution to the constraint system for which all
// values are positive. One value is therefore zero - though if the row/col
// order is not preserved this may not be the first vertex. For consistency,
// translate all the values so that they measure the distance from a[0]; the
// leading edge of the parent. After this transformation some values may be
// negative.
int a0 = a[0];
for (int i = 0, N = a.length; i < N; i++) {
a[i] = a[i] - a0;
}
}
} }
public int[] getLocations() { public int[] getLocations() {
@@ -1521,7 +1560,10 @@ public class GridLayout extends ViewGroup {
} }
private int size(int[] locations) { private int size(int[] locations) {
return max2(locations, 0) - locations[0]; // The parental edges are attached to vertices 0 and N - even when order is not
// being preserved and other vertices fall outside this range. Measure the distance
// between vertices 0 and N, assuming that locations[0] = 0.
return locations[getCount()];
} }
private void setParentConstraints(int min, int max) { private void setParentConstraints(int min, int max) {
@@ -1561,7 +1603,7 @@ public class GridLayout extends ViewGroup {
} }
public void invalidateStructure() { public void invalidateStructure() {
inferredCount = UNDEFINED; maxIndex = UNDEFINED;
groupBounds = null; groupBounds = null;
forwardLinks = null; forwardLinks = null;
@@ -2139,8 +2181,8 @@ public class GridLayout extends ViewGroup {
/** /**
* A Spec defines the horizontal or vertical characteristics of a group of * A Spec defines the horizontal or vertical characteristics of a group of
* cells. Each spec. defines the <em>grid indices</em>, <em>alignment</em> and * cells. Each spec. defines the <em>grid indices</em> and <em>alignment</em>
* <em>flexibility</em> along the appropriate axis. * along the appropriate axis.
* <p> * <p>
* The <em>grid indices</em> are the leading and trailing edges of this cell group. * The <em>grid indices</em> are the leading and trailing edges of this cell group.
* See {@link GridLayout} for a description of the conventions used by GridLayout * See {@link GridLayout} for a description of the conventions used by GridLayout
@@ -2149,6 +2191,15 @@ public class GridLayout extends ViewGroup {
* The <em>alignment</em> property specifies how cells should be aligned in this group. * The <em>alignment</em> property specifies how cells should be aligned in this group.
* For row groups, this specifies the vertical alignment. * For row groups, this specifies the vertical alignment.
* For column groups, this specifies the horizontal alignment. * For column groups, this specifies the horizontal alignment.
* <p>
* Use the following static methods to create specs:
* <ul>
* <li>{@link #spec(int)}</li>
* <li>{@link #spec(int, int)}</li>
* <li>{@link #spec(int, Alignment)}</li>
* <li>{@link #spec(int, int, Alignment)}</li>
* </ul>
*
*/ */
public static class Spec { public static class Spec {
static final Spec UNDEFINED = spec(GridLayout.UNDEFINED); static final Spec UNDEFINED = spec(GridLayout.UNDEFINED);

View File

@@ -32,20 +32,24 @@ public final class Space extends View {
*/ */
public Space(Context context, AttributeSet attrs, int defStyle) { public Space(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle); super(context, attrs, defStyle);
if (getVisibility() == VISIBLE) {
setVisibility(INVISIBLE);
}
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public Space(Context context, AttributeSet attrs) { public Space(Context context, AttributeSet attrs) {
super(context, attrs); this(context, attrs, 0);
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public Space(Context context) { public Space(Context context) {
super(context); //noinspection NullableProblems
this(context, null);
} }
/** /**
@@ -57,22 +61,6 @@ public final class Space extends View {
public void draw(Canvas canvas) { public void draw(Canvas canvas) {
} }
/**
* {@inheritDoc}
*/
@Override
public ViewGroup.LayoutParams getLayoutParams() {
return super.getLayoutParams();
}
/**
* {@inheritDoc}
*/
@Override
public void setLayoutParams(ViewGroup.LayoutParams params) {
super.setLayoutParams(params);
}
/** /**
* Compare to: {@link View#getDefaultSize(int, int)} * Compare to: {@link View#getDefaultSize(int, int)}
* If mode is AT_MOST, return the child size instead of the parent size * If mode is AT_MOST, return the child size instead of the parent size