diff --git a/lib/src/android/support/design/widget/CoordinatorLayout.java b/lib/src/android/support/design/widget/CoordinatorLayout.java index 0ab3c0ebe..e36229401 100644 --- a/lib/src/android/support/design/widget/CoordinatorLayout.java +++ b/lib/src/android/support/design/widget/CoordinatorLayout.java @@ -1189,11 +1189,18 @@ public class CoordinatorLayout extends ViewGroup implements NestedScrollingParen } /** - * Return the given gravity value or the default if the passed value is NO_GRAVITY. This should be - * used for children that are not anchored to another view or a keyline. + * Return the given gravity value, but if either or both of the axes doesn't have any gravity + * specified, the default value (start or top) is specified. This should be used for children that + * are not anchored to another view or a keyline. */ private static int resolveGravity(int gravity) { - return gravity == Gravity.NO_GRAVITY ? GravityCompat.START | Gravity.TOP : gravity; + if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.NO_GRAVITY) { + gravity |= GravityCompat.START; + } + if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.NO_GRAVITY) { + gravity |= Gravity.TOP; + } + return gravity; } /** @@ -2544,9 +2551,10 @@ public class CoordinatorLayout extends ViewGroup implements NestedScrollingParen boolean mBehaviorResolved = false; /** - * A {@link Gravity} value describing how this child view should lay out. If an {@link - * #setAnchorId(int) anchor} is also specified, the gravity describes how this child view should - * be positioned relative to its anchored position. + * A {@link Gravity} value describing how this child view should lay out. If either or both of + * the axes are not specified, they are treated by CoordinatorLayout as {@link Gravity#TOP} or + * {@link GravityCompat#START}. If an {@link #setAnchorId(int) anchor} is also specified, the + * gravity describes how this child view should be positioned relative to its anchored position. */ public int gravity = Gravity.NO_GRAVITY; diff --git a/tests/javatests/android/support/design/widget/CoordinatorLayoutTest.java b/tests/javatests/android/support/design/widget/CoordinatorLayoutTest.java index e0dabfe20..2493b2e95 100644 --- a/tests/javatests/android/support/design/widget/CoordinatorLayoutTest.java +++ b/tests/javatests/android/support/design/widget/CoordinatorLayoutTest.java @@ -46,6 +46,7 @@ import android.support.test.filters.MediumTest; import android.support.test.filters.SdkSuppress; import android.support.test.rule.ActivityTestRule; import android.support.test.runner.AndroidJUnit4; +import android.support.v4.view.GravityCompat; import android.support.v4.view.ViewCompat; import android.support.v4.view.WindowInsetsCompat; import android.view.Gravity; @@ -125,6 +126,60 @@ public class CoordinatorLayoutTest { .onApplyWindowInsets(same(col), same(view), any(WindowInsetsCompat.class)); } + @Test + public void testLayoutChildren() throws Throwable { + final CoordinatorLayout col = activityTestRule.getActivity().mCoordinatorLayout; + final View view = new View(col.getContext()); + activityTestRule.runOnUiThread( + new Runnable() { + @Override + public void run() { + col.addView(view, 100, 100); + } + }); + getInstrumentation().waitForIdleSync(); + int horizontallyCentered = (col.getWidth() - view.getWidth()) / 2; + int end = col.getWidth() - view.getWidth(); + int verticallyCentered = (col.getHeight() - view.getHeight()) / 2; + int bottom = col.getHeight() - view.getHeight(); + final int[][] testCases = { + // gravity, expected left, expected top + {Gravity.NO_GRAVITY, 0, 0}, + {Gravity.LEFT, 0, 0}, + {GravityCompat.START, 0, 0}, + {Gravity.TOP, 0, 0}, + {Gravity.CENTER, horizontallyCentered, verticallyCentered}, + {Gravity.CENTER_HORIZONTAL, horizontallyCentered, 0}, + {Gravity.CENTER_VERTICAL, 0, verticallyCentered}, + {Gravity.RIGHT, end, 0}, + {GravityCompat.END, end, 0}, + {Gravity.BOTTOM, 0, bottom}, + {Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM, horizontallyCentered, bottom}, + {Gravity.RIGHT | Gravity.CENTER_VERTICAL, end, verticallyCentered}, + }; + for (final int[] testCase : testCases) { + activityTestRule.runOnUiThread( + new Runnable() { + @Override + public void run() { + final CoordinatorLayout.LayoutParams lp = + (CoordinatorLayout.LayoutParams) view.getLayoutParams(); + lp.gravity = testCase[0]; + view.setLayoutParams(lp); + } + }); + getInstrumentation().waitForIdleSync(); + activityTestRule.runOnUiThread( + new Runnable() { + @Override + public void run() { + assertThat("Gravity: " + testCase[0], view.getLeft(), is(testCase[1])); + assertThat("Gravity: " + testCase[0], view.getTop(), is(testCase[2])); + } + }); + } + } + @Test public void testInsetDependency() { final CoordinatorLayout col = activityTestRule.getActivity().mCoordinatorLayout;