Add positioning to material DropdownMenu
Bug: 135741815
Test: MenuTest
Change-Id: I3bbe5b3fe851a8713b07c31a37f74dd1315ae0c5
diff --git a/ui/ui-core/api/0.1.0-dev12.txt b/ui/ui-core/api/0.1.0-dev12.txt
index 8e1d102..e4a85b3 100644
--- a/ui/ui-core/api/0.1.0-dev12.txt
+++ b/ui/ui-core/api/0.1.0-dev12.txt
@@ -771,9 +771,14 @@
public final class PopupKt {
method public static void DropdownPopup(androidx.ui.core.DropDownAlignment dropDownAlignment = androidx.ui.core.DropDownAlignment.Start, androidx.ui.unit.IntPxPosition offset = IntPxPosition(IntPx.Zero, IntPx.Zero), boolean isFocusable = false, kotlin.jvm.functions.Function0<kotlin.Unit>? kotlin.jvm.functions.Function0<kotlin.Unit> children);
method public static void Popup(androidx.ui.core.Alignment alignment = Alignment.TopStart, androidx.ui.unit.IntPxPosition offset = IntPxPosition(IntPx.Zero, IntPx.Zero), boolean isFocusable = false, kotlin.jvm.functions.Function0<kotlin.Unit>? kotlin.jvm.functions.Function0<kotlin.Unit> children);
+ method public static void Popup(androidx.ui.core.PopupPositionProvider popupPositionProvider, boolean isFocusable = false, kotlin.jvm.functions.Function0<kotlin.Unit>? kotlin.jvm.functions.Function0<kotlin.Unit> children);
method public static boolean isPopupLayout(android.view.View view, String? testTag = null);
}
+ public interface PopupPositionProvider {
+ method public androidx.ui.unit.IntPxPosition calculatePosition(androidx.ui.unit.IntPxPosition parentLayoutPosition, androidx.ui.unit.IntPxSize parentLayoutSize, androidx.ui.core.LayoutDirection layoutDirection, androidx.ui.unit.IntPxSize popupSize);
+ }
+
public final class Ref<T> {
ctor public Ref();
method public T? getValue();
diff --git a/ui/ui-core/api/current.txt b/ui/ui-core/api/current.txt
index 8e1d102..e4a85b3 100644
--- a/ui/ui-core/api/current.txt
+++ b/ui/ui-core/api/current.txt
@@ -771,9 +771,14 @@
public final class PopupKt {
method public static void DropdownPopup(androidx.ui.core.DropDownAlignment dropDownAlignment = androidx.ui.core.DropDownAlignment.Start, androidx.ui.unit.IntPxPosition offset = IntPxPosition(IntPx.Zero, IntPx.Zero), boolean isFocusable = false, kotlin.jvm.functions.Function0<kotlin.Unit>? kotlin.jvm.functions.Function0<kotlin.Unit> children);
method public static void Popup(androidx.ui.core.Alignment alignment = Alignment.TopStart, androidx.ui.unit.IntPxPosition offset = IntPxPosition(IntPx.Zero, IntPx.Zero), boolean isFocusable = false, kotlin.jvm.functions.Function0<kotlin.Unit>? kotlin.jvm.functions.Function0<kotlin.Unit> children);
+ method public static void Popup(androidx.ui.core.PopupPositionProvider popupPositionProvider, boolean isFocusable = false, kotlin.jvm.functions.Function0<kotlin.Unit>? kotlin.jvm.functions.Function0<kotlin.Unit> children);
method public static boolean isPopupLayout(android.view.View view, String? testTag = null);
}
+ public interface PopupPositionProvider {
+ method public androidx.ui.unit.IntPxPosition calculatePosition(androidx.ui.unit.IntPxPosition parentLayoutPosition, androidx.ui.unit.IntPxSize parentLayoutSize, androidx.ui.core.LayoutDirection layoutDirection, androidx.ui.unit.IntPxSize popupSize);
+ }
+
public final class Ref<T> {
ctor public Ref();
method public T? getValue();
diff --git a/ui/ui-core/api/public_plus_experimental_0.1.0-dev12.txt b/ui/ui-core/api/public_plus_experimental_0.1.0-dev12.txt
index 379ecc8..2086675 100644
--- a/ui/ui-core/api/public_plus_experimental_0.1.0-dev12.txt
+++ b/ui/ui-core/api/public_plus_experimental_0.1.0-dev12.txt
@@ -773,9 +773,14 @@
public final class PopupKt {
method public static void DropdownPopup(androidx.ui.core.DropDownAlignment dropDownAlignment = androidx.ui.core.DropDownAlignment.Start, androidx.ui.unit.IntPxPosition offset = IntPxPosition(IntPx.Zero, IntPx.Zero), boolean isFocusable = false, kotlin.jvm.functions.Function0<kotlin.Unit>? kotlin.jvm.functions.Function0<kotlin.Unit> children);
method public static void Popup(androidx.ui.core.Alignment alignment = Alignment.TopStart, androidx.ui.unit.IntPxPosition offset = IntPxPosition(IntPx.Zero, IntPx.Zero), boolean isFocusable = false, kotlin.jvm.functions.Function0<kotlin.Unit>? kotlin.jvm.functions.Function0<kotlin.Unit> children);
+ method public static void Popup(androidx.ui.core.PopupPositionProvider popupPositionProvider, boolean isFocusable = false, kotlin.jvm.functions.Function0<kotlin.Unit>? kotlin.jvm.functions.Function0<kotlin.Unit> children);
method public static boolean isPopupLayout(android.view.View view, String? testTag = null);
}
+ public interface PopupPositionProvider {
+ method public androidx.ui.unit.IntPxPosition calculatePosition(androidx.ui.unit.IntPxPosition parentLayoutPosition, androidx.ui.unit.IntPxSize parentLayoutSize, androidx.ui.core.LayoutDirection layoutDirection, androidx.ui.unit.IntPxSize popupSize);
+ }
+
public final class Ref<T> {
ctor public Ref();
method public T? getValue();
diff --git a/ui/ui-core/api/public_plus_experimental_current.txt b/ui/ui-core/api/public_plus_experimental_current.txt
index 379ecc8..2086675 100644
--- a/ui/ui-core/api/public_plus_experimental_current.txt
+++ b/ui/ui-core/api/public_plus_experimental_current.txt
@@ -773,9 +773,14 @@
public final class PopupKt {
method public static void DropdownPopup(androidx.ui.core.DropDownAlignment dropDownAlignment = androidx.ui.core.DropDownAlignment.Start, androidx.ui.unit.IntPxPosition offset = IntPxPosition(IntPx.Zero, IntPx.Zero), boolean isFocusable = false, kotlin.jvm.functions.Function0<kotlin.Unit>? kotlin.jvm.functions.Function0<kotlin.Unit> children);
method public static void Popup(androidx.ui.core.Alignment alignment = Alignment.TopStart, androidx.ui.unit.IntPxPosition offset = IntPxPosition(IntPx.Zero, IntPx.Zero), boolean isFocusable = false, kotlin.jvm.functions.Function0<kotlin.Unit>? kotlin.jvm.functions.Function0<kotlin.Unit> children);
+ method public static void Popup(androidx.ui.core.PopupPositionProvider popupPositionProvider, boolean isFocusable = false, kotlin.jvm.functions.Function0<kotlin.Unit>? kotlin.jvm.functions.Function0<kotlin.Unit> children);
method public static boolean isPopupLayout(android.view.View view, String? testTag = null);
}
+ public interface PopupPositionProvider {
+ method public androidx.ui.unit.IntPxPosition calculatePosition(androidx.ui.unit.IntPxPosition parentLayoutPosition, androidx.ui.unit.IntPxSize parentLayoutSize, androidx.ui.core.LayoutDirection layoutDirection, androidx.ui.unit.IntPxSize popupSize);
+ }
+
public final class Ref<T> {
ctor public Ref();
method public T? getValue();
diff --git a/ui/ui-core/api/restricted_0.1.0-dev12.txt b/ui/ui-core/api/restricted_0.1.0-dev12.txt
index 47967f7..93112c3 100644
--- a/ui/ui-core/api/restricted_0.1.0-dev12.txt
+++ b/ui/ui-core/api/restricted_0.1.0-dev12.txt
@@ -827,9 +827,14 @@
public final class PopupKt {
method public static void DropdownPopup(androidx.ui.core.DropDownAlignment dropDownAlignment = androidx.ui.core.DropDownAlignment.Start, androidx.ui.unit.IntPxPosition offset = IntPxPosition(IntPx.Zero, IntPx.Zero), boolean isFocusable = false, kotlin.jvm.functions.Function0<kotlin.Unit>? kotlin.jvm.functions.Function0<kotlin.Unit> children);
method public static void Popup(androidx.ui.core.Alignment alignment = Alignment.TopStart, androidx.ui.unit.IntPxPosition offset = IntPxPosition(IntPx.Zero, IntPx.Zero), boolean isFocusable = false, kotlin.jvm.functions.Function0<kotlin.Unit>? kotlin.jvm.functions.Function0<kotlin.Unit> children);
+ method public static void Popup(androidx.ui.core.PopupPositionProvider popupPositionProvider, boolean isFocusable = false, kotlin.jvm.functions.Function0<kotlin.Unit>? kotlin.jvm.functions.Function0<kotlin.Unit> children);
method public static boolean isPopupLayout(android.view.View view, String? testTag = null);
}
+ public interface PopupPositionProvider {
+ method public androidx.ui.unit.IntPxPosition calculatePosition(androidx.ui.unit.IntPxPosition parentLayoutPosition, androidx.ui.unit.IntPxSize parentLayoutSize, androidx.ui.core.LayoutDirection layoutDirection, androidx.ui.unit.IntPxSize popupSize);
+ }
+
public final class Ref<T> {
ctor public Ref();
method public T? getValue();
diff --git a/ui/ui-core/api/restricted_current.txt b/ui/ui-core/api/restricted_current.txt
index 47967f7..93112c3 100644
--- a/ui/ui-core/api/restricted_current.txt
+++ b/ui/ui-core/api/restricted_current.txt
@@ -827,9 +827,14 @@
public final class PopupKt {
method public static void DropdownPopup(androidx.ui.core.DropDownAlignment dropDownAlignment = androidx.ui.core.DropDownAlignment.Start, androidx.ui.unit.IntPxPosition offset = IntPxPosition(IntPx.Zero, IntPx.Zero), boolean isFocusable = false, kotlin.jvm.functions.Function0<kotlin.Unit>? kotlin.jvm.functions.Function0<kotlin.Unit> children);
method public static void Popup(androidx.ui.core.Alignment alignment = Alignment.TopStart, androidx.ui.unit.IntPxPosition offset = IntPxPosition(IntPx.Zero, IntPx.Zero), boolean isFocusable = false, kotlin.jvm.functions.Function0<kotlin.Unit>? kotlin.jvm.functions.Function0<kotlin.Unit> children);
+ method public static void Popup(androidx.ui.core.PopupPositionProvider popupPositionProvider, boolean isFocusable = false, kotlin.jvm.functions.Function0<kotlin.Unit>? kotlin.jvm.functions.Function0<kotlin.Unit> children);
method public static boolean isPopupLayout(android.view.View view, String? testTag = null);
}
+ public interface PopupPositionProvider {
+ method public androidx.ui.unit.IntPxPosition calculatePosition(androidx.ui.unit.IntPxPosition parentLayoutPosition, androidx.ui.unit.IntPxSize parentLayoutSize, androidx.ui.core.LayoutDirection layoutDirection, androidx.ui.unit.IntPxSize popupSize);
+ }
+
public final class Ref<T> {
ctor public Ref();
method public T? getValue();
diff --git a/ui/ui-core/src/androidTest/java/androidx/ui/core/PopupTest.kt b/ui/ui-core/src/androidTest/java/androidx/ui/core/PopupTest.kt
index b0114c9..b2714d1 100644
--- a/ui/ui-core/src/androidTest/java/androidx/ui/core/PopupTest.kt
+++ b/ui/ui-core/src/androidTest/java/androidx/ui/core/PopupTest.kt
@@ -37,8 +37,6 @@
import androidx.ui.unit.dp
import androidx.ui.unit.ipx
import androidx.ui.unit.isFinite
-import androidx.ui.unit.toPxPosition
-import androidx.ui.unit.toPxSize
import com.google.common.truth.Truth
import org.hamcrest.CoreMatchers.instanceOf
import org.hamcrest.Description
@@ -493,17 +491,14 @@
y = parentGlobalPosition.y + offset.y
*/
val expectedPositionTopStart = IntPxPosition(IntPx(60), IntPx(60))
- val popupPositionProperties = PopupPositionProperties(
- offset = offset
- )
- popupPositionProperties.parentPosition = parentGlobalPosition.toPxPosition()
- popupPositionProperties.parentSize = parentSize.toPxSize()
- popupPositionProperties.childrenSize = popupSize.toPxSize()
- val positionTopStart = calculatePopupGlobalPosition(
- popupPositionProperties,
- Alignment.TopStart
- )
+ val positionTopStart =
+ AlignmentOffsetPositionProvider(Alignment.TopStart, offset).calculatePosition(
+ parentGlobalPosition,
+ parentSize,
+ LayoutDirection.Ltr,
+ popupSize
+ )
Truth.assertThat(positionTopStart).isEqualTo(expectedPositionTopStart)
}
@@ -515,18 +510,14 @@
y = parentGlobalPosition.y + offset.y
*/
val expectedPositionTopStart = IntPxPosition(IntPx(100), IntPx(60))
- val popupPositionProperties = PopupPositionProperties(
- offset = offset
- )
- popupPositionProperties.parentPosition = parentGlobalPosition.toPxPosition()
- popupPositionProperties.parentSize = parentSize.toPxSize()
- popupPositionProperties.childrenSize = popupSize.toPxSize()
- popupPositionProperties.parentLayoutDirection = LayoutDirection.Rtl
- val positionTopStart = calculatePopupGlobalPosition(
- popupPositionProperties,
- Alignment.TopStart
- )
+ val positionTopStart =
+ AlignmentOffsetPositionProvider(Alignment.TopStart, offset).calculatePosition(
+ parentGlobalPosition,
+ parentSize,
+ LayoutDirection.Rtl,
+ popupSize
+ )
Truth.assertThat(positionTopStart).isEqualTo(expectedPositionTopStart)
}
@@ -538,17 +529,14 @@
y = parentGlobalPosition.y + offset.y
*/
val expectedPositionTopCenter = IntPxPosition(IntPx(90), IntPx(60))
- val popupPositionProperties = PopupPositionProperties(
- offset = offset
- )
- popupPositionProperties.parentPosition = parentGlobalPosition.toPxPosition()
- popupPositionProperties.parentSize = parentSize.toPxSize()
- popupPositionProperties.childrenSize = popupSize.toPxSize()
- val positionTopCenter = calculatePopupGlobalPosition(
- popupPositionProperties,
- Alignment.TopCenter
- )
+ val positionTopCenter =
+ AlignmentOffsetPositionProvider(Alignment.TopCenter, offset).calculatePosition(
+ parentGlobalPosition,
+ parentSize,
+ LayoutDirection.Ltr,
+ popupSize
+ )
Truth.assertThat(positionTopCenter).isEqualTo(expectedPositionTopCenter)
}
@@ -560,18 +548,14 @@
y = parentGlobalPosition.y + offset.y
*/
val expectedPositionTopCenter = IntPxPosition(IntPx(70), IntPx(60))
- val popupPositionProperties = PopupPositionProperties(
- offset = offset
- )
- popupPositionProperties.parentPosition = parentGlobalPosition.toPxPosition()
- popupPositionProperties.parentSize = parentSize.toPxSize()
- popupPositionProperties.childrenSize = popupSize.toPxSize()
- popupPositionProperties.parentLayoutDirection = LayoutDirection.Rtl
- val positionTopCenter = calculatePopupGlobalPosition(
- popupPositionProperties,
- Alignment.TopCenter
- )
+ val positionTopCenter =
+ AlignmentOffsetPositionProvider(Alignment.TopCenter, offset).calculatePosition(
+ parentGlobalPosition,
+ parentSize,
+ LayoutDirection.Rtl,
+ popupSize
+ )
Truth.assertThat(positionTopCenter).isEqualTo(expectedPositionTopCenter)
}
@@ -583,17 +567,14 @@
y = parentGlobalPosition.y + offset.y
*/
val expectedPositionTopEnd = IntPxPosition(IntPx(120), IntPx(60))
- val popupPositionProperties = PopupPositionProperties(
- offset = offset
- )
- popupPositionProperties.parentPosition = parentGlobalPosition.toPxPosition()
- popupPositionProperties.parentSize = parentSize.toPxSize()
- popupPositionProperties.childrenSize = popupSize.toPxSize()
- val positionTopEnd = calculatePopupGlobalPosition(
- popupPositionProperties,
- Alignment.TopEnd
- )
+ val positionTopEnd =
+ AlignmentOffsetPositionProvider(Alignment.TopEnd, offset).calculatePosition(
+ parentGlobalPosition,
+ parentSize,
+ LayoutDirection.Ltr,
+ popupSize
+ )
Truth.assertThat(positionTopEnd).isEqualTo(expectedPositionTopEnd)
}
@@ -605,18 +586,14 @@
y = parentGlobalPosition.y + offset.y
*/
val expectedPositionTopEnd = IntPxPosition(IntPx(40), IntPx(60))
- val popupPositionProperties = PopupPositionProperties(
- offset = offset
- )
- popupPositionProperties.parentPosition = parentGlobalPosition.toPxPosition()
- popupPositionProperties.parentSize = parentSize.toPxSize()
- popupPositionProperties.childrenSize = popupSize.toPxSize()
- popupPositionProperties.parentLayoutDirection = LayoutDirection.Rtl
- val positionTopEnd = calculatePopupGlobalPosition(
- popupPositionProperties,
- Alignment.TopEnd
- )
+ val positionTopEnd =
+ AlignmentOffsetPositionProvider(Alignment.TopEnd, offset).calculatePosition(
+ parentGlobalPosition,
+ parentSize,
+ LayoutDirection.Rtl,
+ popupSize
+ )
Truth.assertThat(positionTopEnd).isEqualTo(expectedPositionTopEnd)
}
@@ -628,19 +605,16 @@
y = parentGlobalPosition.y + offset.y + parentSize.y / 2 - popupSize.y / 2
*/
val expectedPositionCenterEnd = IntPxPosition(IntPx(120), IntPx(100))
- val popupPositionProperties = PopupPositionProperties(
- offset = offset
- )
- popupPositionProperties.parentPosition = parentGlobalPosition.toPxPosition()
- popupPositionProperties.parentSize = parentSize.toPxSize()
- popupPositionProperties.childrenSize = popupSize.toPxSize()
- val positionBottomEnd = calculatePopupGlobalPosition(
- popupPositionProperties,
- Alignment.CenterEnd
- )
+ val positionCenterEnd =
+ AlignmentOffsetPositionProvider(Alignment.CenterEnd, offset).calculatePosition(
+ parentGlobalPosition,
+ parentSize,
+ LayoutDirection.Ltr,
+ popupSize
+ )
- Truth.assertThat(positionBottomEnd).isEqualTo(expectedPositionCenterEnd)
+ Truth.assertThat(positionCenterEnd).isEqualTo(expectedPositionCenterEnd)
}
@Test
@@ -650,20 +624,16 @@
y = parentGlobalPosition.y + offset.y + parentSize.y / 2 - popupSize.y / 2
*/
val expectedPositionCenterEnd = IntPxPosition(IntPx(40), IntPx(100))
- val popupPositionProperties = PopupPositionProperties(
- offset = offset
- )
- popupPositionProperties.parentPosition = parentGlobalPosition.toPxPosition()
- popupPositionProperties.parentSize = parentSize.toPxSize()
- popupPositionProperties.childrenSize = popupSize.toPxSize()
- popupPositionProperties.parentLayoutDirection = LayoutDirection.Rtl
- val positionBottomEnd = calculatePopupGlobalPosition(
- popupPositionProperties,
- Alignment.CenterEnd
- )
+ val positionCenterEnd =
+ AlignmentOffsetPositionProvider(Alignment.CenterEnd, offset).calculatePosition(
+ parentGlobalPosition,
+ parentSize,
+ LayoutDirection.Rtl,
+ popupSize
+ )
- Truth.assertThat(positionBottomEnd).isEqualTo(expectedPositionCenterEnd)
+ Truth.assertThat(positionCenterEnd).isEqualTo(expectedPositionCenterEnd)
}
@Test
@@ -673,19 +643,16 @@
y = parentGlobalPosition.y + offset.y + parentSize.y - popupSize.y
*/
val expectedPositionBottomEnd = IntPxPosition(IntPx(120), IntPx(140))
- val popupPositionProperties = PopupPositionProperties(
- offset = offset
- )
- popupPositionProperties.parentPosition = parentGlobalPosition.toPxPosition()
- popupPositionProperties.parentSize = parentSize.toPxSize()
- popupPositionProperties.childrenSize = popupSize.toPxSize()
- val positionBottomCenter = calculatePopupGlobalPosition(
- popupPositionProperties,
- Alignment.BottomEnd
- )
+ val positionBottomEnd =
+ AlignmentOffsetPositionProvider(Alignment.BottomEnd, offset).calculatePosition(
+ parentGlobalPosition,
+ parentSize,
+ LayoutDirection.Ltr,
+ popupSize
+ )
- Truth.assertThat(positionBottomCenter).isEqualTo(expectedPositionBottomEnd)
+ Truth.assertThat(positionBottomEnd).isEqualTo(expectedPositionBottomEnd)
}
@Test
@@ -694,20 +661,17 @@
x = parentGlobalPosition.x + parentSize.x - popupSize.x + offset.x
y = parentGlobalPosition.y + offset.y + parentSize.y - popupSize.y
*/
- val expectedPositionBottomEnd = IntPxPosition(IntPx(120), IntPx(140))
- val popupPositionProperties = PopupPositionProperties(
- offset = offset
- )
- popupPositionProperties.parentPosition = parentGlobalPosition.toPxPosition()
- popupPositionProperties.parentSize = parentSize.toPxSize()
- popupPositionProperties.childrenSize = popupSize.toPxSize()
+ val expectedPositionBottomEnd = IntPxPosition(IntPx(40), IntPx(140))
- val positionBottomCenter = calculatePopupGlobalPosition(
- popupPositionProperties,
- Alignment.BottomEnd
- )
+ val positionBottomEnd =
+ AlignmentOffsetPositionProvider(Alignment.BottomEnd, offset).calculatePosition(
+ parentGlobalPosition,
+ parentSize,
+ LayoutDirection.Rtl,
+ popupSize
+ )
- Truth.assertThat(positionBottomCenter).isEqualTo(expectedPositionBottomEnd)
+ Truth.assertThat(positionBottomEnd).isEqualTo(expectedPositionBottomEnd)
}
@Test
@@ -717,17 +681,14 @@
y = parentGlobalPosition.y + offset.y + parentSize.y - popupSize.y
*/
val expectedPositionBottomCenter = IntPxPosition(IntPx(90), IntPx(140))
- val popupPositionProperties = PopupPositionProperties(
- offset = offset
- )
- popupPositionProperties.parentPosition = parentGlobalPosition.toPxPosition()
- popupPositionProperties.parentSize = parentSize.toPxSize()
- popupPositionProperties.childrenSize = popupSize.toPxSize()
- val positionBottomCenter = calculatePopupGlobalPosition(
- popupPositionProperties,
- Alignment.BottomCenter
- )
+ val positionBottomCenter =
+ AlignmentOffsetPositionProvider(Alignment.BottomCenter, offset).calculatePosition(
+ parentGlobalPosition,
+ parentSize,
+ LayoutDirection.Ltr,
+ popupSize
+ )
Truth.assertThat(positionBottomCenter).isEqualTo(expectedPositionBottomCenter)
}
@@ -739,18 +700,14 @@
y = parentGlobalPosition.y + offset.y + parentSize.y - popupSize.y
*/
val expectedPositionBottomCenter = IntPxPosition(IntPx(70), IntPx(140))
- val popupPositionProperties = PopupPositionProperties(
- offset = offset
- )
- popupPositionProperties.parentPosition = parentGlobalPosition.toPxPosition()
- popupPositionProperties.parentSize = parentSize.toPxSize()
- popupPositionProperties.childrenSize = popupSize.toPxSize()
- popupPositionProperties.parentLayoutDirection = LayoutDirection.Rtl
- val positionBottomCenter = calculatePopupGlobalPosition(
- popupPositionProperties,
- Alignment.BottomCenter
- )
+ val positionBottomCenter =
+ AlignmentOffsetPositionProvider(Alignment.BottomCenter, offset).calculatePosition(
+ parentGlobalPosition,
+ parentSize,
+ LayoutDirection.Rtl,
+ popupSize
+ )
Truth.assertThat(positionBottomCenter).isEqualTo(expectedPositionBottomCenter)
}
@@ -762,17 +719,14 @@
y = parentGlobalPosition.y + offset.y + parentSize.y - popupSize.y
*/
val expectedPositionBottomStart = IntPxPosition(IntPx(60), IntPx(140))
- val popupPositionProperties = PopupPositionProperties(
- offset = offset
- )
- popupPositionProperties.parentPosition = parentGlobalPosition.toPxPosition()
- popupPositionProperties.parentSize = parentSize.toPxSize()
- popupPositionProperties.childrenSize = popupSize.toPxSize()
- val positionBottomStart = calculatePopupGlobalPosition(
- popupPositionProperties,
- Alignment.BottomStart
- )
+ val positionBottomStart =
+ AlignmentOffsetPositionProvider(Alignment.BottomStart, offset).calculatePosition(
+ parentGlobalPosition,
+ parentSize,
+ LayoutDirection.Ltr,
+ popupSize
+ )
Truth.assertThat(positionBottomStart).isEqualTo(expectedPositionBottomStart)
}
@@ -784,18 +738,14 @@
y = parentGlobalPosition.y + offset.y + parentSize.y - popupSize.y
*/
val expectedPositionBottomStart = IntPxPosition(IntPx(100), IntPx(140))
- val popupPositionProperties = PopupPositionProperties(
- offset = offset
- )
- popupPositionProperties.parentPosition = parentGlobalPosition.toPxPosition()
- popupPositionProperties.parentSize = parentSize.toPxSize()
- popupPositionProperties.childrenSize = popupSize.toPxSize()
- popupPositionProperties.parentLayoutDirection = LayoutDirection.Rtl
- val positionBottomStart = calculatePopupGlobalPosition(
- popupPositionProperties,
- Alignment.BottomStart
- )
+ val positionBottomStart =
+ AlignmentOffsetPositionProvider(Alignment.BottomStart, offset).calculatePosition(
+ parentGlobalPosition,
+ parentSize,
+ LayoutDirection.Rtl,
+ popupSize
+ )
Truth.assertThat(positionBottomStart).isEqualTo(expectedPositionBottomStart)
}
@@ -807,17 +757,14 @@
y = parentGlobalPosition.y + offset.y + parentSize.y / 2 - popupSize.y / 2
*/
val expectedPositionCenterStart = IntPxPosition(IntPx(60), IntPx(100))
- val popupPositionProperties = PopupPositionProperties(
- offset = offset
- )
- popupPositionProperties.parentPosition = parentGlobalPosition.toPxPosition()
- popupPositionProperties.parentSize = parentSize.toPxSize()
- popupPositionProperties.childrenSize = popupSize.toPxSize()
- val positionCenterStart = calculatePopupGlobalPosition(
- popupPositionProperties,
- Alignment.CenterStart
- )
+ val positionCenterStart =
+ AlignmentOffsetPositionProvider(Alignment.CenterStart, offset).calculatePosition(
+ parentGlobalPosition,
+ parentSize,
+ LayoutDirection.Ltr,
+ popupSize
+ )
Truth.assertThat(positionCenterStart).isEqualTo(expectedPositionCenterStart)
}
@@ -829,18 +776,14 @@
y = parentGlobalPosition.y + offset.y + parentSize.y / 2 - popupSize.y / 2
*/
val expectedPositionCenterStart = IntPxPosition(IntPx(100), IntPx(100))
- val popupPositionProperties = PopupPositionProperties(
- offset = offset
- )
- popupPositionProperties.parentPosition = parentGlobalPosition.toPxPosition()
- popupPositionProperties.parentSize = parentSize.toPxSize()
- popupPositionProperties.childrenSize = popupSize.toPxSize()
- popupPositionProperties.parentLayoutDirection = LayoutDirection.Rtl
- val positionCenterStart = calculatePopupGlobalPosition(
- popupPositionProperties,
- Alignment.CenterStart
- )
+ val positionCenterStart =
+ AlignmentOffsetPositionProvider(Alignment.CenterStart, offset).calculatePosition(
+ parentGlobalPosition,
+ parentSize,
+ LayoutDirection.Rtl,
+ popupSize
+ )
Truth.assertThat(positionCenterStart).isEqualTo(expectedPositionCenterStart)
}
@@ -852,17 +795,14 @@
y = parentGlobalPosition.y + offset.y + parentSize.y / 2 - popupSize.y / 2
*/
val expectedPositionCenter = IntPxPosition(IntPx(90), IntPx(100))
- val popupPositionProperties = PopupPositionProperties(
- offset = offset
- )
- popupPositionProperties.parentPosition = parentGlobalPosition.toPxPosition()
- popupPositionProperties.parentSize = parentSize.toPxSize()
- popupPositionProperties.childrenSize = popupSize.toPxSize()
- val positionCenter = calculatePopupGlobalPosition(
- popupPositionProperties,
- Alignment.Center
- )
+ val positionCenter =
+ AlignmentOffsetPositionProvider(Alignment.Center, offset).calculatePosition(
+ parentGlobalPosition,
+ parentSize,
+ LayoutDirection.Ltr,
+ popupSize
+ )
Truth.assertThat(positionCenter).isEqualTo(expectedPositionCenter)
}
@@ -874,18 +814,14 @@
y = parentGlobalPosition.y + offset.y + parentSize.y / 2 - popupSize.y / 2
*/
val expectedPositionCenter = IntPxPosition(IntPx(70), IntPx(100))
- val popupPositionProperties = PopupPositionProperties(
- offset = offset
- )
- popupPositionProperties.parentPosition = parentGlobalPosition.toPxPosition()
- popupPositionProperties.parentSize = parentSize.toPxSize()
- popupPositionProperties.childrenSize = popupSize.toPxSize()
- popupPositionProperties.parentLayoutDirection = LayoutDirection.Rtl
- val positionCenter = calculatePopupGlobalPosition(
- popupPositionProperties,
- Alignment.Center
- )
+ val positionCenter =
+ AlignmentOffsetPositionProvider(Alignment.Center, offset).calculatePosition(
+ parentGlobalPosition,
+ parentSize,
+ LayoutDirection.Rtl,
+ popupSize
+ )
Truth.assertThat(positionCenter).isEqualTo(expectedPositionCenter)
}
@@ -918,15 +854,14 @@
y = parentGlobalPosition.y + offset.y + parentSize.y
*/
val expectedPositionLeft = IntPxPosition(IntPx(60), IntPx(160))
- val popupPositionProperties = PopupPositionProperties(offset = offset)
- popupPositionProperties.parentPosition = parentGlobalPosition.toPxPosition()
- popupPositionProperties.parentSize = parentSize.toPxSize()
- popupPositionProperties.childrenSize = popupSize.toPxSize()
- val positionLeft = calculateDropdownPopupPosition(
- popupPositionProperties,
- DropDownAlignment.Start
- )
+ val positionLeft =
+ DropdownPositionProvider(DropDownAlignment.Start, offset).calculatePosition(
+ parentGlobalPosition,
+ parentSize,
+ LayoutDirection.Ltr,
+ popupSize
+ )
Truth.assertThat(positionLeft).isEqualTo(expectedPositionLeft)
}
@@ -938,16 +873,14 @@
y = parentGlobalPosition.y + offset.y + parentSize.y
*/
val expectedPosition = IntPxPosition(IntPx(100), IntPx(160))
- val popupPositionProperties = PopupPositionProperties(offset = offset)
- popupPositionProperties.parentPosition = parentGlobalPosition.toPxPosition()
- popupPositionProperties.parentSize = parentSize.toPxSize()
- popupPositionProperties.childrenSize = popupSize.toPxSize()
- popupPositionProperties.parentLayoutDirection = LayoutDirection.Rtl
- val positionLeft = calculateDropdownPopupPosition(
- popupPositionProperties,
- DropDownAlignment.Start
- )
+ val positionLeft =
+ DropdownPositionProvider(DropDownAlignment.Start, offset).calculatePosition(
+ parentGlobalPosition,
+ parentSize,
+ LayoutDirection.Rtl,
+ popupSize
+ )
Truth.assertThat(positionLeft).isEqualTo(expectedPosition)
}
@@ -959,15 +892,14 @@
y = parentGlobalPosition.y + offset.y + parentSize.y
*/
val expectedPositionRight = IntPxPosition(IntPx(160), IntPx(160))
- val popupPositionProperties = PopupPositionProperties(offset = offset)
- popupPositionProperties.parentPosition = parentGlobalPosition.toPxPosition()
- popupPositionProperties.parentSize = parentSize.toPxSize()
- popupPositionProperties.childrenSize = popupSize.toPxSize()
- val positionRight = calculateDropdownPopupPosition(
- popupPositionProperties,
- DropDownAlignment.End
- )
+ val positionRight =
+ DropdownPositionProvider(DropDownAlignment.End, offset).calculatePosition(
+ parentGlobalPosition,
+ parentSize,
+ LayoutDirection.Ltr,
+ popupSize
+ )
Truth.assertThat(positionRight).isEqualTo(expectedPositionRight)
}
@@ -979,16 +911,14 @@
y = parentGlobalPosition.y + offset.y + parentSize.y
*/
val expectedPositionRight = IntPxPosition(IntPx(0), IntPx(160))
- val popupPositionProperties = PopupPositionProperties(offset = offset)
- popupPositionProperties.parentPosition = parentGlobalPosition.toPxPosition()
- popupPositionProperties.parentSize = parentSize.toPxSize()
- popupPositionProperties.childrenSize = popupSize.toPxSize()
- popupPositionProperties.parentLayoutDirection = LayoutDirection.Rtl
- val positionRight = calculateDropdownPopupPosition(
- popupPositionProperties,
- DropDownAlignment.End
- )
+ val positionRight =
+ DropdownPositionProvider(DropDownAlignment.End, offset).calculatePosition(
+ parentGlobalPosition,
+ parentSize,
+ LayoutDirection.Rtl,
+ popupSize
+ )
Truth.assertThat(positionRight).isEqualTo(expectedPositionRight)
}
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/Popup.kt b/ui/ui-core/src/main/java/androidx/ui/core/Popup.kt
index 9f598bc..b46f0f9 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/Popup.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/Popup.kt
@@ -26,6 +26,7 @@
import android.widget.FrameLayout
import androidx.compose.Composable
import androidx.compose.Composition
+import androidx.compose.Immutable
import androidx.compose.Providers
import androidx.compose.ambientOf
import androidx.compose.currentComposer
@@ -41,11 +42,9 @@
import androidx.ui.unit.IntPxPosition
import androidx.ui.unit.IntPxSize
import androidx.ui.unit.PxPosition
-import androidx.ui.unit.PxSize
import androidx.ui.unit.ipx
import androidx.ui.unit.max
import androidx.ui.unit.round
-import androidx.ui.unit.toPxSize
import org.jetbrains.annotations.TestOnly
/**
@@ -73,19 +72,14 @@
onDismissRequest: (() -> Unit)? = null,
children: @Composable () -> Unit
) {
- // Memoize the object, but change the value of the properties if a recomposition happens
- val popupPositionProperties = remember {
- PopupPositionProperties(
- offset = offset
- )
+ val popupPositioner = remember(alignment, offset) {
+ AlignmentOffsetPositionProvider(alignment, offset)
}
- popupPositionProperties.offset = offset
Popup(
+ popupPositionProvider = popupPositioner,
isFocusable = isFocusable,
>
- popupPositionProperties = popupPositionProperties,
- calculatePopupPosition = { calculatePopupGlobalPosition(it, alignment) },
children = children
)
}
@@ -113,19 +107,14 @@
onDismissRequest: (() -> Unit)? = null,
children: @Composable () -> Unit
) {
- // Memoize the object, but change the value of the properties if a recomposition happens
- val popupPositionProperties = remember {
- PopupPositionProperties(
- offset = offset
- )
+ val popupPositioner = remember(dropDownAlignment, offset) {
+ DropdownPositionProvider(dropDownAlignment, offset)
}
- popupPositionProperties.offset = offset
Popup(
+ popupPositionProvider = popupPositioner,
isFocusable = isFocusable,
>
- popupPositionProperties = popupPositionProperties,
- calculatePopupPosition = { calculateDropdownPopupPosition(it, dropDownAlignment) },
children = children
)
}
@@ -140,12 +129,31 @@
Providers(PopupTestTagAmbient provides tag, children = children)
}
+internal class PopupPositionProperties {
+ var parentPosition = IntPxPosition.Origin
+ var parentSize = IntPxSize.Zero
+ var childrenSize = IntPxSize.Zero
+ var parentLayoutDirection: LayoutDirection = LayoutDirection.Ltr
+}
+
+/**
+ * Opens a popup with the given content.
+ *
+ * The popup is positioned using a custom [popupPositionProvider].
+ *
+ * @sample androidx.ui.core.samples.PopupSample
+ *
+ * @param popupPositionProvider Provides the screen position of the popup.
+ * @param isFocusable Indicates if the popup can grab the focus.
+ * @param onDismissRequest Executes when the popup tries to dismiss itself. This happens when
+ * the popup is focusable and the user clicks outside.
+ * @param children The content to be displayed inside the popup.
+ */
@Composable
-private fun Popup(
- isFocusable: Boolean,
+fun Popup(
+ popupPositionProvider: PopupPositionProvider,
+ isFocusable: Boolean = false,
onDismissRequest: (() -> Unit)? = null,
- popupPositionProperties: PopupPositionProperties,
- calculatePopupPosition: ((PopupPositionProperties) -> IntPxPosition),
children: @Composable () -> Unit
) {
val context = ContextAmbient.current
@@ -154,6 +162,7 @@
val owner = OwnerAmbient.current
val providedTestTag = PopupTestTagAmbient.current
+ val popupPositionProperties = remember { PopupPositionProperties() }
val popupLayout = remember(isFocusable) {
escapeCompose {
PopupLayout(
@@ -162,12 +171,12 @@
popupIsFocusable = isFocusable,
>
popupPositionProperties = popupPositionProperties,
- calculatePopupPosition = calculatePopupPosition,
+ popupPositionProvider = popupPositionProvider,
testTag = providedTestTag
)
}
}
- popupLayout.calculatePopupPosition = calculatePopupPosition
+ popupLayout.popupPositionProvider = popupPositionProvider
var composition: Composition? = null
@@ -177,11 +186,11 @@
Layout(children = emptyContent(), modifier = Modifier.onPositioned { childCoordinates ->
val coordinates = childCoordinates.parentCoordinates!!
// Get the global position of the parent
- val layoutPosition = coordinates.localToGlobal(PxPosition.Origin)
+ val layoutPosition = coordinates.localToGlobal(PxPosition.Origin).round()
val layoutSize = coordinates.size
popupLayout.popupPositionProperties.parentPosition = layoutPosition
- popupLayout.popupPositionProperties.parentSize = layoutSize.toPxSize()
+ popupLayout.popupPositionProperties.parentSize = layoutSize
// Update the popup's position
popupLayout.updatePosition()
@@ -196,7 +205,7 @@
Semantics(container = true, properties = { this.popup = true }) {
SimpleStack(Modifier.onPositioned {
// Get the size of the content
- popupLayout.popupPositionProperties.childrenSize = it.size.toPxSize()
+ popupLayout.popupPositionProperties.childrenSize = it.size
// Update the popup's position
popupLayout.updatePosition()
@@ -253,7 +262,7 @@
* @param composeView The parent view of the popup which is the AndroidComposeView.
* @param popupIsFocusable Indicates if the popup can grab the focus.
* @param onDismissRequest Executed when the popup tries to dismiss itself.
- * @param calculatePopupPosition The logic of positioning the popup relative to its parent.
+ * @param popupPositionProvider The logic of positioning the popup relative to its parent.
*/
@SuppressLint("ViewConstructor")
private class PopupLayout(
@@ -262,7 +271,7 @@
val popupIsFocusable: Boolean,
val onDismissRequest: (() -> Unit)? = null,
var popupPositionProperties: PopupPositionProperties,
- var calculatePopupPosition: ((PopupPositionProperties) -> IntPxPosition),
+ var popupPositionProvider: PopupPositionProvider,
var testTag: String
) : FrameLayout(context) {
val windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
@@ -279,7 +288,12 @@
* relative to its parent.
*/
fun updatePosition() {
- val popupGlobalPosition = calculatePopupPosition(popupPositionProperties)
+ val popupGlobalPosition = popupPositionProvider.calculatePosition(
+ popupPositionProperties.parentPosition,
+ popupPositionProperties.parentSize,
+ popupPositionProperties.parentLayoutDirection,
+ popupPositionProperties.childrenSize
+ )
params.x = popupGlobalPosition.x.value
params.y = popupGlobalPosition.y.value
@@ -360,13 +374,25 @@
}
}
-internal data class PopupPositionProperties(
- var offset: IntPxPosition
-) {
- var parentPosition = PxPosition.Origin
- var parentSize = PxSize.Zero
- var childrenSize = PxSize.Zero
- var parentLayoutDirection: LayoutDirection = LayoutDirection.Ltr
+/**
+ * Calculates the position of a [Popup] on screen.
+ */
+@Immutable
+interface PopupPositionProvider {
+ /**
+ * Calculates the position of a [Popup] on screen.
+ *
+ * @param parentLayoutPosition The position of the parent wrapper layout on screen.
+ * @param parentLayoutSize The size of the parent wrapper layout.
+ * @param layoutDirection The layout direction of the parent wrapper layout.
+ * @param popupSize The size of the popup to be positioned.
+ */
+ fun calculatePosition(
+ parentLayoutPosition: IntPxPosition,
+ parentLayoutSize: IntPxSize,
+ layoutDirection: LayoutDirection,
+ popupSize: IntPxSize
+ ): IntPxPosition
}
/**
@@ -378,106 +404,100 @@
End
}
-internal fun calculatePopupGlobalPosition(
- popupPositionProperties: PopupPositionProperties,
- alignment: Alignment
-): IntPxPosition {
- val layoutDirection = popupPositionProperties.parentLayoutDirection
+internal class AlignmentOffsetPositionProvider(
+ val alignment: Alignment,
+ val offset: IntPxPosition
+) : PopupPositionProvider {
+ override fun calculatePosition(
+ parentLayoutPosition: IntPxPosition,
+ parentLayoutSize: IntPxSize,
+ layoutDirection: LayoutDirection,
+ popupSize: IntPxSize
+ ): IntPxPosition {
+ // TODO: Decide which is the best way to round to result without reimplementing Alignment.align
+ var popupGlobalPosition = IntPxPosition(IntPx.Zero, IntPx.Zero)
- // TODO: Decide which is the best way to round to result without reimplementing Alignment.align
- var popupGlobalPosition = IntPxPosition(IntPx.Zero, IntPx.Zero)
+ // Get the aligned point inside the parent
+ val parentAlignmentPoint = alignment.align(
+ IntPxSize(parentLayoutSize.width, parentLayoutSize.height),
+ layoutDirection
+ )
+ // Get the aligned point inside the child
+ val relativePopupPos = alignment.align(
+ IntPxSize(popupSize.width, popupSize.height),
+ layoutDirection
+ )
- // Get the aligned point inside the parent
- val parentAlignmentPoint = alignment.align(
- IntPxSize(
- popupPositionProperties.parentSize.width.round(),
- popupPositionProperties.parentSize.height.round()
- ),
- layoutDirection
- )
- // Get the aligned point inside the child
- val relativePopupPos = alignment.align(
- IntPxSize(
- popupPositionProperties.childrenSize.width.round(),
- popupPositionProperties.childrenSize.height.round()
- ),
- layoutDirection
- )
+ // Add the global position of the parent
+ popupGlobalPosition += IntPxPosition(parentLayoutPosition.x, parentLayoutPosition.y)
- // Add the global position of the parent
- popupGlobalPosition += IntPxPosition(
- popupPositionProperties.parentPosition.x.round(),
- popupPositionProperties.parentPosition.y.round()
- )
+ // Add the distance between the parent's top left corner and the alignment point
+ popupGlobalPosition += parentAlignmentPoint
- // Add the distance between the parent's top left corner and the alignment point
- popupGlobalPosition += parentAlignmentPoint
+ // Subtract the distance between the children's top left corner and the alignment point
+ popupGlobalPosition -= IntPxPosition(relativePopupPos.x, relativePopupPos.y)
- // Subtract the distance between the children's top left corner and the alignment point
- popupGlobalPosition -= IntPxPosition(relativePopupPos.x, relativePopupPos.y)
+ // Add the user offset
+ val resolvedOffset = IntPxPosition(
+ offset.x * (if (layoutDirection == LayoutDirection.Ltr) 1 else -1),
+ offset.y
+ )
+ popupGlobalPosition += resolvedOffset
- // Add the user offset
- val offset = IntPxPosition(
- popupPositionProperties.offset.x * (if (layoutDirection == LayoutDirection.Ltr) 1 else -1),
- popupPositionProperties.offset.y
- )
- popupGlobalPosition += offset
-
- return popupGlobalPosition
+ return popupGlobalPosition
+ }
}
-internal fun calculateDropdownPopupPosition(
- popupPositionProperties: PopupPositionProperties,
- dropDownAlignment: DropDownAlignment
-): IntPxPosition {
- val layoutDirection = popupPositionProperties.parentLayoutDirection
+internal class DropdownPositionProvider(
+ val dropDownAlignment: DropDownAlignment,
+ val offset: IntPxPosition
+) : PopupPositionProvider {
+ override fun calculatePosition(
+ parentLayoutPosition: IntPxPosition,
+ parentLayoutSize: IntPxSize,
+ layoutDirection: LayoutDirection,
+ popupSize: IntPxSize
+ ): IntPxPosition {
+ var popupGlobalPosition = IntPxPosition(IntPx.Zero, IntPx.Zero)
- var popupGlobalPosition = IntPxPosition(IntPx.Zero, IntPx.Zero)
+ // Add the global position of the parent
+ popupGlobalPosition += IntPxPosition(parentLayoutPosition.x, parentLayoutPosition.y)
- // Add the global position of the parent
- popupGlobalPosition += IntPxPosition(
- popupPositionProperties.parentPosition.x.round(),
- popupPositionProperties.parentPosition.y.round()
- )
-
- /*
- * In LTR context aligns popup's left edge with the parent's left edge for Start alignment and
- * parent's right edge for End alignment.
- * In RTL context aligns popup's right edge with the parent's right edge for Start alignment and
- * parent's left edge for End alignment.
- */
- val alignmentPositionX =
- if (dropDownAlignment == DropDownAlignment.Start) {
- if (layoutDirection == LayoutDirection.Ltr) {
- 0.ipx
+ /*
+ * In LTR context aligns popup's left edge with the parent's left edge for Start alignment and
+ * parent's right edge for End alignment.
+ * In RTL context aligns popup's right edge with the parent's right edge for Start alignment and
+ * parent's left edge for End alignment.
+ */
+ val alignmentPositionX =
+ if (dropDownAlignment == DropDownAlignment.Start) {
+ if (layoutDirection == LayoutDirection.Ltr) {
+ 0.ipx
+ } else {
+ parentLayoutSize.width - popupSize.width
+ }
} else {
- popupPositionProperties.parentSize.width.round() -
- popupPositionProperties.childrenSize.width.round()
+ if (layoutDirection == LayoutDirection.Ltr) {
+ parentLayoutSize.width
+ } else {
+ -popupSize.width
+ }
}
- } else {
- if (layoutDirection == LayoutDirection.Ltr) {
- popupPositionProperties.parentSize.width.round()
- } else {
- -popupPositionProperties.childrenSize.width.round()
- }
+
+ // The popup's position relative to the parent's top left corner
+ val dropdownAlignmentPosition = IntPxPosition(alignmentPositionX, parentLayoutSize.height)
+
+ popupGlobalPosition += dropdownAlignmentPosition
+
+ // Add the user offset
+ val resolvedOffset = IntPxPosition(
+ offset.x * (if (layoutDirection == LayoutDirection.Ltr) 1 else -1),
+ offset.y
+ )
+ popupGlobalPosition += resolvedOffset
+
+ return popupGlobalPosition
}
-
- // The popup's position relative to the parent's top left corner
- val dropdownAlignmentPosition = IntPxPosition(
- alignmentPositionX,
- popupPositionProperties.parentSize.height.round()
- )
-
- popupGlobalPosition += dropdownAlignmentPosition
-
- // Add the user offset
- val offset = IntPxPosition(
- popupPositionProperties.offset.x * (if (layoutDirection == LayoutDirection.Ltr) 1 else -1),
- popupPositionProperties.offset.y
- )
- popupGlobalPosition += offset
-
- return popupGlobalPosition
}
/**
diff --git a/ui/ui-material/api/0.1.0-dev12.txt b/ui/ui-material/api/0.1.0-dev12.txt
index 6862a59..95144f1 100644
--- a/ui/ui-material/api/0.1.0-dev12.txt
+++ b/ui/ui-material/api/0.1.0-dev12.txt
@@ -165,7 +165,7 @@
}
public final class MenuKt {
- method public static void DropdownMenu(kotlin.jvm.functions.Function0<kotlin.Unit> toggle, boolean expanded, kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, androidx.ui.core.Modifier toggleModifier = Modifier, androidx.ui.core.Modifier dropdownModifier = Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.layout.ColumnScope,kotlin.Unit> dropdownContent);
+ method public static void DropdownMenu-1DTJxuk(kotlin.jvm.functions.Function0<kotlin.Unit> toggle, boolean expanded, kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, androidx.ui.core.Modifier toggleModifier = Modifier, long dropdownOffset = Position(0.dp, 0.dp), androidx.ui.core.Modifier dropdownModifier = Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.layout.ColumnScope,kotlin.Unit> dropdownContent);
method public static void DropdownMenuItem(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.ui.core.Modifier modifier = Modifier, boolean enabled = true, kotlin.jvm.functions.Function0<kotlin.Unit> content);
}
diff --git a/ui/ui-material/api/current.txt b/ui/ui-material/api/current.txt
index 6862a59..95144f1 100644
--- a/ui/ui-material/api/current.txt
+++ b/ui/ui-material/api/current.txt
@@ -165,7 +165,7 @@
}
public final class MenuKt {
- method public static void DropdownMenu(kotlin.jvm.functions.Function0<kotlin.Unit> toggle, boolean expanded, kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, androidx.ui.core.Modifier toggleModifier = Modifier, androidx.ui.core.Modifier dropdownModifier = Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.layout.ColumnScope,kotlin.Unit> dropdownContent);
+ method public static void DropdownMenu-1DTJxuk(kotlin.jvm.functions.Function0<kotlin.Unit> toggle, boolean expanded, kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, androidx.ui.core.Modifier toggleModifier = Modifier, long dropdownOffset = Position(0.dp, 0.dp), androidx.ui.core.Modifier dropdownModifier = Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.layout.ColumnScope,kotlin.Unit> dropdownContent);
method public static void DropdownMenuItem(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.ui.core.Modifier modifier = Modifier, boolean enabled = true, kotlin.jvm.functions.Function0<kotlin.Unit> content);
}
diff --git a/ui/ui-material/api/public_plus_experimental_0.1.0-dev12.txt b/ui/ui-material/api/public_plus_experimental_0.1.0-dev12.txt
index 6862a59..95144f1 100644
--- a/ui/ui-material/api/public_plus_experimental_0.1.0-dev12.txt
+++ b/ui/ui-material/api/public_plus_experimental_0.1.0-dev12.txt
@@ -165,7 +165,7 @@
}
public final class MenuKt {
- method public static void DropdownMenu(kotlin.jvm.functions.Function0<kotlin.Unit> toggle, boolean expanded, kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, androidx.ui.core.Modifier toggleModifier = Modifier, androidx.ui.core.Modifier dropdownModifier = Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.layout.ColumnScope,kotlin.Unit> dropdownContent);
+ method public static void DropdownMenu-1DTJxuk(kotlin.jvm.functions.Function0<kotlin.Unit> toggle, boolean expanded, kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, androidx.ui.core.Modifier toggleModifier = Modifier, long dropdownOffset = Position(0.dp, 0.dp), androidx.ui.core.Modifier dropdownModifier = Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.layout.ColumnScope,kotlin.Unit> dropdownContent);
method public static void DropdownMenuItem(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.ui.core.Modifier modifier = Modifier, boolean enabled = true, kotlin.jvm.functions.Function0<kotlin.Unit> content);
}
diff --git a/ui/ui-material/api/public_plus_experimental_current.txt b/ui/ui-material/api/public_plus_experimental_current.txt
index 6862a59..95144f1 100644
--- a/ui/ui-material/api/public_plus_experimental_current.txt
+++ b/ui/ui-material/api/public_plus_experimental_current.txt
@@ -165,7 +165,7 @@
}
public final class MenuKt {
- method public static void DropdownMenu(kotlin.jvm.functions.Function0<kotlin.Unit> toggle, boolean expanded, kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, androidx.ui.core.Modifier toggleModifier = Modifier, androidx.ui.core.Modifier dropdownModifier = Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.layout.ColumnScope,kotlin.Unit> dropdownContent);
+ method public static void DropdownMenu-1DTJxuk(kotlin.jvm.functions.Function0<kotlin.Unit> toggle, boolean expanded, kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, androidx.ui.core.Modifier toggleModifier = Modifier, long dropdownOffset = Position(0.dp, 0.dp), androidx.ui.core.Modifier dropdownModifier = Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.layout.ColumnScope,kotlin.Unit> dropdownContent);
method public static void DropdownMenuItem(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.ui.core.Modifier modifier = Modifier, boolean enabled = true, kotlin.jvm.functions.Function0<kotlin.Unit> content);
}
diff --git a/ui/ui-material/api/restricted_0.1.0-dev12.txt b/ui/ui-material/api/restricted_0.1.0-dev12.txt
index 1548f01..a766d05 100644
--- a/ui/ui-material/api/restricted_0.1.0-dev12.txt
+++ b/ui/ui-material/api/restricted_0.1.0-dev12.txt
@@ -166,7 +166,7 @@
}
public final class MenuKt {
- method public static void DropdownMenu(kotlin.jvm.functions.Function0<kotlin.Unit> toggle, boolean expanded, kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, androidx.ui.core.Modifier toggleModifier = Modifier, androidx.ui.core.Modifier dropdownModifier = Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.layout.ColumnScope,kotlin.Unit> dropdownContent);
+ method public static void DropdownMenu-1DTJxuk(kotlin.jvm.functions.Function0<kotlin.Unit> toggle, boolean expanded, kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, androidx.ui.core.Modifier toggleModifier = Modifier, long dropdownOffset = Position(0.dp, 0.dp), androidx.ui.core.Modifier dropdownModifier = Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.layout.ColumnScope,kotlin.Unit> dropdownContent);
method public static void DropdownMenuItem(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.ui.core.Modifier modifier = Modifier, boolean enabled = true, kotlin.jvm.functions.Function0<kotlin.Unit> content);
}
diff --git a/ui/ui-material/api/restricted_current.txt b/ui/ui-material/api/restricted_current.txt
index 1548f01..a766d05 100644
--- a/ui/ui-material/api/restricted_current.txt
+++ b/ui/ui-material/api/restricted_current.txt
@@ -166,7 +166,7 @@
}
public final class MenuKt {
- method public static void DropdownMenu(kotlin.jvm.functions.Function0<kotlin.Unit> toggle, boolean expanded, kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, androidx.ui.core.Modifier toggleModifier = Modifier, androidx.ui.core.Modifier dropdownModifier = Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.layout.ColumnScope,kotlin.Unit> dropdownContent);
+ method public static void DropdownMenu-1DTJxuk(kotlin.jvm.functions.Function0<kotlin.Unit> toggle, boolean expanded, kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, androidx.ui.core.Modifier toggleModifier = Modifier, long dropdownOffset = Position(0.dp, 0.dp), androidx.ui.core.Modifier dropdownModifier = Modifier, kotlin.jvm.functions.Function1<? super androidx.ui.layout.ColumnScope,kotlin.Unit> dropdownContent);
method public static void DropdownMenuItem(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, androidx.ui.core.Modifier modifier = Modifier, boolean enabled = true, kotlin.jvm.functions.Function0<kotlin.Unit> content);
}
diff --git a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/MenuDemo.kt b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/MenuDemo.kt
index 3c12512..2bf97f1 100644
--- a/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/MenuDemo.kt
+++ b/ui/ui-material/integration-tests/material-demos/src/main/java/androidx/ui/material/demos/MenuDemo.kt
@@ -26,15 +26,49 @@
import androidx.ui.foundation.Text
import androidx.ui.layout.fillMaxSize
import androidx.ui.layout.wrapContentSize
-import androidx.ui.material.Divider
+import androidx.ui.core.LayoutDirection
+import androidx.ui.layout.Stack
+import androidx.ui.layout.ltr
import androidx.ui.material.DropdownMenu
import androidx.ui.material.DropdownMenuItem
import androidx.ui.material.IconButton
import androidx.ui.material.icons.Icons
import androidx.ui.material.icons.filled.MoreVert
+import androidx.ui.unit.IntPxPosition
+import androidx.ui.unit.IntPxSize
+import androidx.ui.unit.Position
+import androidx.ui.unit.dp
@Composable
fun MenuDemo() {
+ Stack(Modifier.ltr) {
+ for (i in 0..10) {
+ for (j in 0..10) {
+ MenuInstance(
+ Modifier.fillMaxSize().wrapContentSize(
+ object : Alignment {
+ override fun align(
+ size: IntPxSize,
+ layoutDirection: LayoutDirection
+ ) = IntPxPosition(size.width * i / 10f, size.height * j / 10f)
+ }
+ )
+ )
+ }
+ }
+ }
+}
+
+@Composable
+fun MenuInstance(modifier: Modifier = Modifier) {
+ val options = listOf(
+ "Refresh",
+ "Settings",
+ "Send Feedback",
+ "Help",
+ "Signout"
+ )
+
var expanded by state { false }
val iconButton = @Composable {
@@ -46,17 +80,13 @@
expanded = expanded,
expanded = false },
toggle = iconButton,
- toggleModifier = Modifier.fillMaxSize().wrapContentSize(Alignment.TopStart)
+ dropdownOffset = Position(-12.dp, -12.dp),
+ toggleModifier = modifier
) {
- DropdownMenuItem( /* Handle refresh! */ }) {
- Text("Refresh")
- }
- DropdownMenuItem( /* Handle settings! */ }) {
- Text("Settings")
- }
- Divider()
- DropdownMenuItem( /* Handle send feedback! */ }) {
- Text("Send Feedback")
+ options.forEach {
+ DropdownMenuItem( {
+ Text(it)
+ }
}
}
}
\ No newline at end of file
diff --git a/ui/ui-material/src/androidTest/java/androidx/ui/material/MenuTest.kt b/ui/ui-material/src/androidTest/java/androidx/ui/material/MenuTest.kt
index 9fd340d3..c62e3fa 100644
--- a/ui/ui-material/src/androidTest/java/androidx/ui/material/MenuTest.kt
+++ b/ui/ui-material/src/androidTest/java/androidx/ui/material/MenuTest.kt
@@ -16,10 +16,12 @@
package androidx.ui.material
+import android.util.DisplayMetrics
import androidx.compose.getValue
import androidx.compose.mutableStateOf
import androidx.compose.setValue
import androidx.test.filters.MediumTest
+import androidx.ui.core.LayoutDirection
import androidx.ui.core.Modifier
import androidx.ui.core.TestTag
import androidx.ui.foundation.Box
@@ -38,7 +40,12 @@
import androidx.ui.test.isPopup
import androidx.ui.test.runOnIdleCompose
import androidx.ui.test.waitForIdle
+import androidx.ui.unit.Density
+import androidx.ui.unit.IntPxPosition
+import androidx.ui.unit.IntPxSize
+import androidx.ui.unit.Position
import androidx.ui.unit.dp
+import androidx.ui.unit.ipx
import com.google.common.truth.Truth.assertThat
import org.junit.Rule
import org.junit.Test
@@ -121,4 +128,111 @@
)
}
}
+
+ @Test
+ fun menu_positioning_bottomEnd() {
+ val screenWidth = 500
+ val screenHeight = 1000
+ val density = Density(1f)
+ val displayMetrics = DisplayMetrics().apply {
+ widthPixels = screenWidth
+ heightPixels = screenHeight
+ }
+ val anchorPosition = IntPxPosition(100.ipx, 200.ipx)
+ val anchorSize = IntPxSize(10.ipx, 20.ipx)
+ val inset = with(density) { MenuElevation.toIntPx() }
+ val offsetX = 20
+ val offsetY = 40
+ val popupSize = IntPxSize(50.ipx, 80.ipx)
+
+ val ltrPosition = DropdownMenuPositionProvider(
+ Position(offsetX.dp, offsetY.dp),
+ density,
+ displayMetrics
+ ).calculatePosition(
+ anchorPosition,
+ anchorSize,
+ LayoutDirection.Ltr,
+ popupSize
+ )
+
+ assertThat(ltrPosition.x).isEqualTo(
+ anchorPosition.x + anchorSize.width - inset + offsetX.ipx
+ )
+ assertThat(ltrPosition.y).isEqualTo(
+ anchorPosition.y + anchorSize.height - inset + offsetY.ipx
+ )
+
+ val rtlPosition = DropdownMenuPositionProvider(
+ Position(offsetX.dp, offsetY.dp),
+ density,
+ displayMetrics
+ ).calculatePosition(
+ anchorPosition,
+ anchorSize,
+ LayoutDirection.Rtl,
+ popupSize
+ )
+
+ assertThat(rtlPosition.x).isEqualTo(
+ anchorPosition.x - popupSize.width + inset - offsetX.ipx
+ )
+ assertThat(rtlPosition.y).isEqualTo(
+ anchorPosition.y + anchorSize.height - inset + offsetY.ipx
+ )
+ }
+
+ @Test
+ fun menu_positioning_topStart() {
+ val screenWidth = 500
+ val screenHeight = 1000
+ val density = Density(1f)
+ val displayMetrics = DisplayMetrics().apply {
+ widthPixels = screenWidth
+ heightPixels = screenHeight
+ }
+ val anchorPosition = IntPxPosition(450.ipx, 950.ipx)
+ val anchorPositionRtl = IntPxPosition(50.ipx, 950.ipx)
+ val anchorSize = IntPxSize(10.ipx, 20.ipx)
+ val inset = with(density) { MenuElevation.toIntPx() }
+ val offsetX = 20
+ val offsetY = 40
+ val popupSize = IntPxSize(150.ipx, 80.ipx)
+
+ val ltrPosition = DropdownMenuPositionProvider(
+ Position(offsetX.dp, offsetY.dp),
+ density,
+ displayMetrics
+ ).calculatePosition(
+ anchorPosition,
+ anchorSize,
+ LayoutDirection.Ltr,
+ popupSize
+ )
+
+ assertThat(ltrPosition.x).isEqualTo(
+ anchorPosition.x - popupSize.width + inset - offsetX.ipx
+ )
+ assertThat(ltrPosition.y).isEqualTo(
+ anchorPosition.y - popupSize.height + inset - offsetY.ipx
+ )
+
+ val rtlPosition = DropdownMenuPositionProvider(
+ Position(offsetX.dp, offsetY.dp),
+ density,
+ displayMetrics
+ ).calculatePosition(
+ anchorPositionRtl,
+ anchorSize,
+ LayoutDirection.Rtl,
+ popupSize
+ )
+
+ assertThat(rtlPosition.x).isEqualTo(
+ anchorPositionRtl.x + anchorSize.width - inset + offsetX.ipx
+ )
+ assertThat(rtlPosition.y).isEqualTo(
+ anchorPositionRtl.y - popupSize.height + inset - offsetY.ipx
+ )
+ }
}
diff --git a/ui/ui-material/src/main/java/androidx/ui/material/Menu.kt b/ui/ui-material/src/main/java/androidx/ui/material/Menu.kt
index a0715098..d5d4dd7 100644
--- a/ui/ui-material/src/main/java/androidx/ui/material/Menu.kt
+++ b/ui/ui-material/src/main/java/androidx/ui/material/Menu.kt
@@ -16,17 +16,23 @@
package androidx.ui.material
+import android.util.DisplayMetrics
import androidx.animation.FloatPropKey
import androidx.animation.LinearOutSlowInEasing
import androidx.animation.transitionDefinition
import androidx.compose.Composable
+import androidx.compose.Immutable
import androidx.compose.getValue
import androidx.compose.setValue
import androidx.compose.state
import androidx.ui.animation.Transition
+import androidx.ui.core.ContextAmbient
import androidx.ui.core.DensityAmbient
-import androidx.ui.core.DropdownPopup
+import androidx.ui.core.LayoutDirection
import androidx.ui.core.Modifier
+import androidx.ui.core.Popup
+import androidx.ui.core.PopupPositionProvider
+import androidx.ui.unit.Position
import androidx.ui.core.drawLayer
import androidx.ui.foundation.Box
import androidx.ui.foundation.ContentGravity
@@ -40,8 +46,11 @@
import androidx.ui.layout.preferredSizeIn
import androidx.ui.layout.preferredWidth
import androidx.ui.material.ripple.ripple
+import androidx.ui.unit.Density
import androidx.ui.unit.IntPxPosition
+import androidx.ui.unit.IntPxSize
import androidx.ui.unit.dp
+import androidx.ui.unit.ipx
/**
* A Material Design [dropdown menu](https://material.io/components/menus#dropdown-menu).
@@ -52,6 +61,12 @@
* [DropdownMenuItem] can be used to achieve items as defined by the Material Design spec.
* [onDismissRequest] will be called when the menu should close - for example when there is a
* tap outside the menu, or when the back key is pressed.
+ * The menu will do a best effort to be fully visible on screen. It will try to expand
+ * horizontally, depending on layout direction, to the end of the [toggle], then to the start of
+ * the [toggle], and then screen end-aligned. Vertically, it will try to expand to the bottom
+ * of the [toggle], then from the top of the [toggle], and then screen top-aligned. A
+ * [dropdownOffset] can be provided to adjust the positioning of the menu for cases when the
+ * layout bounds of the [toggle] do not coincide with its visual bounds.
*
* Example usage:
* @sample androidx.ui.material.samples.MenuSample
@@ -60,6 +75,7 @@
* @param expanded Whether the menu is currently open or dismissed
* @param onDismissRequest Called when the menu should be dismiss
* @param toggleModifier The modifier to be applied to the toggle
+ * @param dropdownOffset Offset to be added to the position of the menu
* @param dropdownModifier Modifier to be applied to the menu content
*/
@Composable
@@ -68,6 +84,7 @@
expanded: Boolean,
onDismissRequest: () -> Unit,
toggleModifier: Modifier = Modifier,
+ dropdownOffset: Position = Position(0.dp, 0.dp),
dropdownModifier: Modifier = Modifier,
dropdownContent: @Composable ColumnScope.() -> Unit
) {
@@ -78,14 +95,16 @@
toggle()
if (visibleMenu) {
- DropdownPopup(
+ val popupPositionProvider = DropdownMenuPositionProvider(
+ dropdownOffset,
+ DensityAmbient.current,
+ ContextAmbient.current.resources.displayMetrics
+ )
+
+ Popup(
isFocusable = true,
>
- offset = with(DensityAmbient.current) {
- // Compensate for the padding added below.
- // TODO(popam, b/156890315): add elevation to Popup
- IntPxPosition(-MenuElevation.toIntPx(), -MenuElevation.toIntPx())
- }
+ popupPositionProvider = popupPositionProvider
) {
Transition(
definition = DropdownMenuOpenCloseTransition,
@@ -159,6 +178,7 @@
}
}
+// Size constants.
internal val MenuElevation = 8.dp
internal val DropdownMenuHorizontalPadding = 16.dp
internal val DropdownMenuVerticalPadding = 8.dp
@@ -166,6 +186,7 @@
internal val DropdownMenuItemDefaultMaxWidth = 280.dp
internal val DropdownMenuItemDefaultMinHeight = 48.dp
+// Menu open/close animation.
private val Scale = FloatPropKey()
private val Alpha = FloatPropKey()
internal val InTransitionDuration = 120
@@ -203,3 +224,56 @@
}
}
}
+
+// Menu positioning.
+
+/**
+ * Calculates the position of a Material [DropdownMenu].
+ */
+// TODO(popam): Investigate if this can/should consider the app window size rather than screen size
+@Immutable
+internal data class DropdownMenuPositionProvider(
+ val contentOffset: Position,
+ val density: Density,
+ val displayMetrics: DisplayMetrics
+) : PopupPositionProvider {
+ override fun calculatePosition(
+ parentLayoutPosition: IntPxPosition,
+ parentLayoutSize: IntPxSize,
+ layoutDirection: LayoutDirection,
+ popupSize: IntPxSize
+ ): IntPxPosition {
+ // The padding inset that accommodates elevation, needs to be taken into account.
+ val inset = with(density) { MenuElevation.toIntPx() }
+ val realPopupWidth = popupSize.width - inset * 2
+ val realPopupHeight = popupSize.height - inset * 2
+ val contentOffsetX = with(density) { contentOffset.x.toIntPx() }
+ val contentOffsetY = with(density) { contentOffset.y.toIntPx() }
+ val parentRight = parentLayoutPosition.x + parentLayoutSize.width
+ val parentBottom = parentLayoutPosition.y + parentLayoutSize.height
+
+ // Compute horizontal position.
+ val toRight = parentRight + contentOffsetX
+ val toLeft = parentLayoutPosition.x - contentOffsetX - realPopupWidth
+ val toDisplayRight = displayMetrics.widthPixels.ipx - realPopupWidth
+ val toDisplayLeft = 0.ipx
+ val x = if (layoutDirection == LayoutDirection.Ltr) {
+ sequenceOf(toRight, toLeft, toDisplayRight)
+ } else {
+ sequenceOf(toLeft, toRight, toDisplayLeft)
+ }.firstOrNull {
+ it >= 0.ipx && it + realPopupWidth <= displayMetrics.widthPixels.ipx
+ } ?: toLeft
+
+ // Compute vertical position.
+ val toBottom = parentBottom + contentOffsetY
+ val toTop = parentLayoutPosition.y - contentOffsetY - realPopupHeight
+ val toCenter = parentLayoutPosition.y - realPopupHeight / 2
+ val toDisplayBottom = displayMetrics.heightPixels.ipx - realPopupHeight
+ val y = sequenceOf(toBottom, toTop, toCenter, toDisplayBottom).firstOrNull {
+ it >= 0.ipx && it + realPopupHeight <= displayMetrics.heightPixels.ipx
+ } ?: toTop
+
+ return IntPxPosition(x - inset, y - inset)
+ }
+}
diff --git a/ui/ui-unit/api/0.1.0-dev12.txt b/ui/ui-unit/api/0.1.0-dev12.txt
index a66bda0..05a1680 100644
--- a/ui/ui-unit/api/0.1.0-dev12.txt
+++ b/ui/ui-unit/api/0.1.0-dev12.txt
@@ -386,6 +386,12 @@
method public inline operator androidx.ui.unit.IntPxSize times(int other);
property public final inline int height;
property public final inline int width;
+ field public static final androidx.ui.unit.IntPxSize.Companion! Companion;
+ }
+
+ public static final class IntPxSize.Companion {
+ method public androidx.ui.unit.IntPxSize getZero();
+ property public final androidx.ui.unit.IntPxSize Zero;
}
public final inline class IntSize {
diff --git a/ui/ui-unit/api/current.txt b/ui/ui-unit/api/current.txt
index a66bda0..05a1680 100644
--- a/ui/ui-unit/api/current.txt
+++ b/ui/ui-unit/api/current.txt
@@ -386,6 +386,12 @@
method public inline operator androidx.ui.unit.IntPxSize times(int other);
property public final inline int height;
property public final inline int width;
+ field public static final androidx.ui.unit.IntPxSize.Companion! Companion;
+ }
+
+ public static final class IntPxSize.Companion {
+ method public androidx.ui.unit.IntPxSize getZero();
+ property public final androidx.ui.unit.IntPxSize Zero;
}
public final inline class IntSize {
diff --git a/ui/ui-unit/api/public_plus_experimental_0.1.0-dev12.txt b/ui/ui-unit/api/public_plus_experimental_0.1.0-dev12.txt
index a66bda0..05a1680 100644
--- a/ui/ui-unit/api/public_plus_experimental_0.1.0-dev12.txt
+++ b/ui/ui-unit/api/public_plus_experimental_0.1.0-dev12.txt
@@ -386,6 +386,12 @@
method public inline operator androidx.ui.unit.IntPxSize times(int other);
property public final inline int height;
property public final inline int width;
+ field public static final androidx.ui.unit.IntPxSize.Companion! Companion;
+ }
+
+ public static final class IntPxSize.Companion {
+ method public androidx.ui.unit.IntPxSize getZero();
+ property public final androidx.ui.unit.IntPxSize Zero;
}
public final inline class IntSize {
diff --git a/ui/ui-unit/api/public_plus_experimental_current.txt b/ui/ui-unit/api/public_plus_experimental_current.txt
index a66bda0..05a1680 100644
--- a/ui/ui-unit/api/public_plus_experimental_current.txt
+++ b/ui/ui-unit/api/public_plus_experimental_current.txt
@@ -386,6 +386,12 @@
method public inline operator androidx.ui.unit.IntPxSize times(int other);
property public final inline int height;
property public final inline int width;
+ field public static final androidx.ui.unit.IntPxSize.Companion! Companion;
+ }
+
+ public static final class IntPxSize.Companion {
+ method public androidx.ui.unit.IntPxSize getZero();
+ property public final androidx.ui.unit.IntPxSize Zero;
}
public final inline class IntSize {
diff --git a/ui/ui-unit/api/restricted_0.1.0-dev12.txt b/ui/ui-unit/api/restricted_0.1.0-dev12.txt
index a01b3de..71cbf10 100644
--- a/ui/ui-unit/api/restricted_0.1.0-dev12.txt
+++ b/ui/ui-unit/api/restricted_0.1.0-dev12.txt
@@ -390,6 +390,12 @@
method public inline operator androidx.ui.unit.IntPxSize times(int other);
property public final inline int height;
property public final inline int width;
+ field public static final androidx.ui.unit.IntPxSize.Companion! Companion;
+ }
+
+ public static final class IntPxSize.Companion {
+ method public androidx.ui.unit.IntPxSize getZero();
+ property public final androidx.ui.unit.IntPxSize Zero;
}
public final inline class IntSize {
diff --git a/ui/ui-unit/api/restricted_current.txt b/ui/ui-unit/api/restricted_current.txt
index a01b3de..71cbf10 100644
--- a/ui/ui-unit/api/restricted_current.txt
+++ b/ui/ui-unit/api/restricted_current.txt
@@ -390,6 +390,12 @@
method public inline operator androidx.ui.unit.IntPxSize times(int other);
property public final inline int height;
property public final inline int width;
+ field public static final androidx.ui.unit.IntPxSize.Companion! Companion;
+ }
+
+ public static final class IntPxSize.Companion {
+ method public androidx.ui.unit.IntPxSize getZero();
+ property public final androidx.ui.unit.IntPxSize Zero;
}
public final inline class IntSize {
diff --git a/ui/ui-unit/src/commonMain/kotlin/androidx/ui/unit/IntPx.kt b/ui/ui-unit/src/commonMain/kotlin/androidx/ui/unit/IntPx.kt
index b85bb37..8e773cb0 100644
--- a/ui/ui-unit/src/commonMain/kotlin/androidx/ui/unit/IntPx.kt
+++ b/ui/ui-unit/src/commonMain/kotlin/androidx/ui/unit/IntPx.kt
@@ -279,6 +279,13 @@
IntPxSize(width = width / other, height = height / other)
override fun toString(): String = "$width x $height"
+
+ companion object {
+ /**
+ * [IntPxSize] with zero values.
+ */
+ val Zero = IntPxSize(0.ipx, 0.ipx)
+ }
}
/**