Skip to content

Commit 4a145d7

Browse files
author
Philip Milne
committed
Fix for 5393156
. Fix for the above. . Make instances of Space invisible by default. . Correctly accomodate parental constraints when row/col order is undefined. This fix allows GridLayout to accomodate simple dependencies between its axes. In the example given in bug 5393156, the presence of a multi-line TextView means that GridLayout can only compute its height after it has computed its width. This fix adds a second measurement pass to GridLayout that passes infomation betwen the axes, using the GridLayout's orientation property to indicate which axis should be examined first. Change-Id: I90761c6fcfe8edc7ef6d9a89076fd5cda3adc0a4
1 parent cc3fbb7 commit 4a145d7

File tree

2 files changed

+102
-63
lines changed

2 files changed

+102
-63
lines changed

core/java/android/widget/GridLayout.java

Lines changed: 96 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -850,32 +850,65 @@ final boolean isGone(View c) {
850850
return c.getVisibility() == View.GONE;
851851
}
852852

853-
private void measureChildWithMargins(View child, int widthMeasureSpec, int heightMeasureSpec) {
854-
LayoutParams lp = getLayoutParams(child);
855-
int childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec,
856-
mPaddingLeft + mPaddingRight + getTotalMargin(child, true), lp.width);
857-
int childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec,
858-
mPaddingTop + mPaddingBottom + getTotalMargin(child, false), lp.height);
859-
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
853+
private void measureChildWithMargins2(View child, int parentWidthSpec, int parentHeightSpec,
854+
int childWidth, int childHeight) {
855+
int childWidthSpec = getChildMeasureSpec(parentWidthSpec,
856+
mPaddingLeft + mPaddingRight + getTotalMargin(child, true), childWidth);
857+
int childHeightSpec = getChildMeasureSpec(parentHeightSpec,
858+
mPaddingTop + mPaddingBottom + getTotalMargin(child, false), childHeight);
859+
child.measure(childWidthSpec, childHeightSpec);
860860
}
861861

862-
private void measureChildrenWithMargins(int widthMeasureSpec, int heightMeasureSpec) {
862+
private void measureChildrenWithMargins(int widthSpec, int heightSpec, boolean firstPass) {
863863
for (int i = 0, N = getChildCount(); i < N; i++) {
864864
View c = getChildAt(i);
865865
if (isGone(c)) continue;
866-
measureChildWithMargins(c, widthMeasureSpec, heightMeasureSpec);
866+
LayoutParams lp = getLayoutParams(c);
867+
if (firstPass) {
868+
measureChildWithMargins2(c, widthSpec, heightSpec, lp.width, lp.height);
869+
} else {
870+
Spec spec = (orientation == HORIZONTAL) ? lp.columnSpec : lp.rowSpec;
871+
if (spec.alignment == FILL) {
872+
Interval span = spec.span;
873+
Axis axis = (orientation == HORIZONTAL) ? horizontalAxis : verticalAxis;
874+
int[] locations = axis.getLocations();
875+
int size = locations[span.max] - locations[span.min];
876+
if (orientation == HORIZONTAL) {
877+
measureChildWithMargins2(c, widthSpec, heightSpec, size, lp.height);
878+
} else {
879+
measureChildWithMargins2(c, widthSpec, heightSpec, lp.width, size);
880+
}
881+
}
882+
}
867883
}
868884
}
869885

870886
@Override
871887
protected void onMeasure(int widthSpec, int heightSpec) {
872-
measureChildrenWithMargins(widthSpec, heightSpec);
888+
/** If we have been called by {@link View#measure(int, int)}, one of width or height
889+
* is likely to have changed. We must invalidate if so. */
890+
invalidateValues();
891+
892+
measureChildrenWithMargins(widthSpec, heightSpec, true);
893+
894+
int width, height;
895+
896+
// Use the orientation property to decide which axis should be laid out first.
897+
if (orientation == HORIZONTAL) {
898+
width = horizontalAxis.getMeasure(widthSpec);
899+
measureChildrenWithMargins(widthSpec, heightSpec, false);
900+
height = verticalAxis.getMeasure(heightSpec);
901+
} else {
902+
height = verticalAxis.getMeasure(heightSpec);
903+
measureChildrenWithMargins(widthSpec, heightSpec, false);
904+
width = horizontalAxis.getMeasure(widthSpec);
905+
}
873906

874-
int width = getPaddingLeft() + horizontalAxis.getMeasure(widthSpec) + getPaddingRight();
875-
int height = getPaddingTop() + verticalAxis.getMeasure(heightSpec) + getPaddingBottom();
907+
int hPadding = getPaddingLeft() + getPaddingRight();
908+
int vPadding = getPaddingTop() + getPaddingBottom();
876909

877-
int measuredWidth = Math.max(width, getSuggestedMinimumWidth());
878-
int measuredHeight = Math.max(height, getSuggestedMinimumHeight());
910+
int measuredWidth = Math.max(hPadding + width, getSuggestedMinimumWidth());
911+
int measuredHeight = Math.max(vPadding + height, getSuggestedMinimumHeight());
879912

880913
setMeasuredDimension(
881914
resolveSizeAndState(measuredWidth, widthSpec, 0),
@@ -1015,16 +1048,14 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto
10151048
for the vertical one.
10161049
*/
10171050
final class Axis {
1018-
private static final int MIN_VALUE = -1000000;
1019-
10201051
private static final int NEW = 0;
10211052
private static final int PENDING = 1;
10221053
private static final int COMPLETE = 2;
10231054

10241055
public final boolean horizontal;
10251056

10261057
public int definedCount = UNDEFINED;
1027-
private int inferredCount = UNDEFINED;
1058+
private int maxIndex = UNDEFINED;
10281059

10291060
PackedMap<Spec, Bounds> groupBounds;
10301061
public boolean groupBoundsValid = false;
@@ -1056,28 +1087,29 @@ private Axis(boolean horizontal) {
10561087
this.horizontal = horizontal;
10571088
}
10581089

1059-
private int maxIndex() {
1060-
// note the number Integer.MIN_VALUE + 1 comes up in undefined cells
1061-
int count = -1;
1090+
private int calculateMaxIndex() {
1091+
// the number Integer.MIN_VALUE + 1 comes up in undefined cells
1092+
int result = -1;
10621093
for (int i = 0, N = getChildCount(); i < N; i++) {
10631094
View c = getChildAt(i);
10641095
LayoutParams params = getLayoutParams(c);
10651096
Spec spec = horizontal ? params.columnSpec : params.rowSpec;
1066-
count = max(count, spec.span.min);
1067-
count = max(count, spec.span.max);
1097+
Interval span = spec.span;
1098+
result = max(result, span.min);
1099+
result = max(result, span.max);
10681100
}
1069-
return count == -1 ? UNDEFINED : count;
1101+
return result == -1 ? UNDEFINED : result;
10701102
}
10711103

1072-
private int getInferredCount() {
1073-
if (inferredCount == UNDEFINED) {
1074-
inferredCount = max(0, maxIndex()); // if there are no cells, actual count is zero
1104+
private int getMaxIndex() {
1105+
if (maxIndex == UNDEFINED) {
1106+
maxIndex = max(0, calculateMaxIndex()); // use zero when there are no children
10751107
}
1076-
return inferredCount;
1108+
return maxIndex;
10771109
}
10781110

10791111
public int getCount() {
1080-
return max(definedCount, getInferredCount());
1112+
return max(definedCount, getMaxIndex());
10811113
}
10821114

10831115
public void setCount(int count) {
@@ -1179,7 +1211,7 @@ private PackedMap<Interval, MutableInt> getBackwardLinks() {
11791211
}
11801212

11811213
private void include(List<Arc> arcs, Interval key, MutableInt size,
1182-
boolean ignoreIfAlreadyPresent) {
1214+
boolean ignoreIfAlreadyPresent) {
11831215
/*
11841216
Remove self referential links.
11851217
These appear:
@@ -1341,19 +1373,18 @@ private boolean relax(int[] locations, Arc entry) {
13411373
}
13421374

13431375
private void init(int[] locations) {
1344-
Arrays.fill(locations, MIN_VALUE);
1345-
locations[0] = 0;
1376+
Arrays.fill(locations, 0);
13461377
}
13471378

13481379
private String arcsToString(List<Arc> arcs) {
1349-
String var = horizontal ? "c" : "r";
1380+
String var = horizontal ? "x" : "y";
13501381
StringBuilder result = new StringBuilder();
1351-
boolean first = false;
1352-
for(Arc arc : arcs) {
1353-
if (!first) {
1354-
first = true;
1382+
boolean first = true;
1383+
for (Arc arc : arcs) {
1384+
if (first) {
1385+
first = false;
13551386
} else {
1356-
result =result.append(", ");
1387+
result = result.append(", ");
13571388
}
13581389
int src = arc.span.min;
13591390
int dst = arc.span.max;
@@ -1434,10 +1465,6 @@ private void solve(Arc[] arcs, int[] locations) {
14341465
if (originalCulprits != null) {
14351466
logError(axisName, arcs, originalCulprits);
14361467
}
1437-
if (DEBUG) {
1438-
Log.v(TAG, axisName + " iteration completed in " +
1439-
(1 + i) + " steps of " + N);
1440-
}
14411468
return;
14421469
}
14431470
}
@@ -1506,6 +1533,18 @@ public int[] getTrailingMargins() {
15061533

15071534
private void computeLocations(int[] a) {
15081535
solve(getArcs(), a);
1536+
if (!orderPreserved) {
1537+
// Solve returns the smallest solution to the constraint system for which all
1538+
// values are positive. One value is therefore zero - though if the row/col
1539+
// order is not preserved this may not be the first vertex. For consistency,
1540+
// translate all the values so that they measure the distance from a[0]; the
1541+
// leading edge of the parent. After this transformation some values may be
1542+
// negative.
1543+
int a0 = a[0];
1544+
for (int i = 0, N = a.length; i < N; i++) {
1545+
a[i] = a[i] - a0;
1546+
}
1547+
}
15091548
}
15101549

15111550
public int[] getLocations() {
@@ -1521,7 +1560,10 @@ public int[] getLocations() {
15211560
}
15221561

15231562
private int size(int[] locations) {
1524-
return max2(locations, 0) - locations[0];
1563+
// The parental edges are attached to vertices 0 and N - even when order is not
1564+
// being preserved and other vertices fall outside this range. Measure the distance
1565+
// between vertices 0 and N, assuming that locations[0] = 0.
1566+
return locations[getCount()];
15251567
}
15261568

15271569
private void setParentConstraints(int min, int max) {
@@ -1561,7 +1603,7 @@ public void layout(int size) {
15611603
}
15621604

15631605
public void invalidateStructure() {
1564-
inferredCount = UNDEFINED;
1606+
maxIndex = UNDEFINED;
15651607

15661608
groupBounds = null;
15671609
forwardLinks = null;
@@ -2139,8 +2181,8 @@ public String toString() {
21392181

21402182
/**
21412183
* A Spec defines the horizontal or vertical characteristics of a group of
2142-
* cells. Each spec. defines the <em>grid indices</em>, <em>alignment</em> and
2143-
* <em>flexibility</em> along the appropriate axis.
2184+
* cells. Each spec. defines the <em>grid indices</em> and <em>alignment</em>
2185+
* along the appropriate axis.
21442186
* <p>
21452187
* The <em>grid indices</em> are the leading and trailing edges of this cell group.
21462188
* See {@link GridLayout} for a description of the conventions used by GridLayout
@@ -2149,6 +2191,15 @@ public String toString() {
21492191
* The <em>alignment</em> property specifies how cells should be aligned in this group.
21502192
* For row groups, this specifies the vertical alignment.
21512193
* For column groups, this specifies the horizontal alignment.
2194+
* <p>
2195+
* Use the following static methods to create specs:
2196+
* <ul>
2197+
* <li>{@link #spec(int)}</li>
2198+
* <li>{@link #spec(int, int)}</li>
2199+
* <li>{@link #spec(int, Alignment)}</li>
2200+
* <li>{@link #spec(int, int, Alignment)}</li>
2201+
* </ul>
2202+
*
21522203
*/
21532204
public static class Spec {
21542205
static final Spec UNDEFINED = spec(GridLayout.UNDEFINED);

core/java/android/widget/Space.java

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -32,20 +32,24 @@ public final class Space extends View {
3232
*/
3333
public Space(Context context, AttributeSet attrs, int defStyle) {
3434
super(context, attrs, defStyle);
35+
if (getVisibility() == VISIBLE) {
36+
setVisibility(INVISIBLE);
37+
}
3538
}
3639

3740
/**
3841
* {@inheritDoc}
3942
*/
4043
public Space(Context context, AttributeSet attrs) {
41-
super(context, attrs);
44+
this(context, attrs, 0);
4245
}
4346

4447
/**
4548
* {@inheritDoc}
4649
*/
4750
public Space(Context context) {
48-
super(context);
51+
//noinspection NullableProblems
52+
this(context, null);
4953
}
5054

5155
/**
@@ -57,22 +61,6 @@ public Space(Context context) {
5761
public void draw(Canvas canvas) {
5862
}
5963

60-
/**
61-
* {@inheritDoc}
62-
*/
63-
@Override
64-
public ViewGroup.LayoutParams getLayoutParams() {
65-
return super.getLayoutParams();
66-
}
67-
68-
/**
69-
* {@inheritDoc}
70-
*/
71-
@Override
72-
public void setLayoutParams(ViewGroup.LayoutParams params) {
73-
super.setLayoutParams(params);
74-
}
75-
7664
/**
7765
* Compare to: {@link View#getDefaultSize(int, int)}
7866
* If mode is AT_MOST, return the child size instead of the parent size

0 commit comments

Comments
 (0)