Replace EdgeContentLayout2 with setter that updates EdgeContentLayout
As per API feedback, instead of creating a new class and deprecating
the existing one, we are adding setResponsiveContentInsetEnabled
setter to override the current look of the layout to the new one
that is more responsive and matches the UX guidelines.
Bug: 324092213
Test: Existing ones for ECL2 are updated to call this new setter, so there's not diff in goldens.
Relnote: "EdgeContentLayout has been updated with new setResponsiveContentInsetEnabled setter to achieve better alignment with the UX guidelines, consistency in Tiles by having primary label at the fixed place on top and reponsive inset for labels."
Change-Id: I601758f8aded4afd9fd40ce0df4f54d5b4176416
diff --git a/wear/protolayout/protolayout-material/api/current.txt b/wear/protolayout/protolayout-material/api/current.txt
index bd5e676..38c33fb 100644
--- a/wear/protolayout/protolayout-material/api/current.txt
+++ b/wear/protolayout/protolayout-material/api/current.txt
@@ -233,51 +233,35 @@
package androidx.wear.protolayout.material.layouts {
- @Deprecated public class EdgeContentLayout implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
- method @Deprecated public static androidx.wear.protolayout.material.layouts.EdgeContentLayout? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
- method @Deprecated public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getContent();
- method @Deprecated public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getEdgeContent();
- method @Deprecated public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getPrimaryLabelTextContent();
- method @Deprecated public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getSecondaryLabelTextContent();
- method @Deprecated public boolean isEdgeContentBehindAllOtherContent();
- }
-
- @Deprecated public static final class EdgeContentLayout.Builder {
- ctor @Deprecated public EdgeContentLayout.Builder(androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
- method @Deprecated public androidx.wear.protolayout.material.layouts.EdgeContentLayout build();
- method @Deprecated public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
- method @Deprecated public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setEdgeContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
- method @Deprecated public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setEdgeContentBehindAllOtherContent(boolean);
- method @Deprecated public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setPrimaryLabelTextContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
- method @Deprecated public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setSecondaryLabelTextContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
- }
-
- public final class EdgeContentLayout2 implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
- method public static androidx.wear.protolayout.material.layouts.EdgeContentLayout2? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+ public class EdgeContentLayout implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+ method public static androidx.wear.protolayout.material.layouts.EdgeContentLayout? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getContent();
method @Dimension(unit=androidx.annotation.Dimension.DP) public float getContentAndSecondaryLabelSpacing();
method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getEdgeContent();
method public float getEdgeContentThickness();
- method public androidx.wear.protolayout.expression.Fingerprint? getFingerprint();
- method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getPrimaryLabelContent();
- method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getSecondaryLabelContent();
+ method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getPrimaryLabelTextContent();
+ method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getSecondaryLabelTextContent();
+ method public boolean isEdgeContentBehindAllOtherContent();
+ method public boolean isResponsiveContentInsetEnabled();
}
- public static final class EdgeContentLayout2.Builder {
- ctor public EdgeContentLayout2.Builder(androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
- method public androidx.wear.protolayout.material.layouts.EdgeContentLayout2 build();
- method public androidx.wear.protolayout.material.layouts.EdgeContentLayout2.Builder setContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
- method public androidx.wear.protolayout.material.layouts.EdgeContentLayout2.Builder setContentAndSecondaryLabelSpacing(androidx.wear.protolayout.DimensionBuilders.DpProp);
- method public androidx.wear.protolayout.material.layouts.EdgeContentLayout2.Builder setEdgeContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
- method public androidx.wear.protolayout.material.layouts.EdgeContentLayout2.Builder setEdgeContentThickness(@Dimension(unit=androidx.annotation.Dimension.DP) float);
- method public androidx.wear.protolayout.material.layouts.EdgeContentLayout2.Builder setPrimaryLabelContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
- method public androidx.wear.protolayout.material.layouts.EdgeContentLayout2.Builder setSecondaryLabelContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+ public static final class EdgeContentLayout.Builder {
+ ctor public EdgeContentLayout.Builder(androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+ method public androidx.wear.protolayout.material.layouts.EdgeContentLayout build();
+ method public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+ method public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setContentAndSecondaryLabelSpacing(androidx.wear.protolayout.DimensionBuilders.DpProp);
+ method public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setEdgeContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+ method public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setEdgeContentBehindAllOtherContent(boolean);
+ method public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setEdgeContentThickness(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+ method public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setPrimaryLabelTextContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+ method public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setResponsiveContentInsetEnabled(boolean);
+ method public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setSecondaryLabelTextContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
}
public class LayoutDefaults {
field public static final androidx.wear.protolayout.DimensionBuilders.DpProp DEFAULT_VERTICAL_SPACER_HEIGHT;
- field public static final androidx.wear.protolayout.DimensionBuilders.DpProp EDGE_CONTENT_LAYOUT2_CONTENT_AND_SECONDARY_LABEL_SPACING_DP;
- field public static final androidx.wear.protolayout.DimensionBuilders.DpProp EDGE_CONTENT_LAYOUT2_LARGE_CONTENT_AND_SECONDARY_LABEL_SPACING_DP;
+ field public static final androidx.wear.protolayout.DimensionBuilders.DpProp EDGE_CONTENT_LAYOUT_CONTENT_AND_SECONDARY_LABEL_SPACING_DP;
+ field public static final androidx.wear.protolayout.DimensionBuilders.DpProp EDGE_CONTENT_LAYOUT_LARGE_CONTENT_AND_SECONDARY_LABEL_SPACING_DP;
field public static final float EDGE_CONTENT_LAYOUT_PADDING_ABOVE_MAIN_CONTENT_DP = 6.0f;
field public static final float EDGE_CONTENT_LAYOUT_PADDING_BELOW_MAIN_CONTENT_DP = 8.0f;
field @Deprecated public static final int MULTI_BUTTON_MAX_NUMBER = 7; // 0x7
diff --git a/wear/protolayout/protolayout-material/api/restricted_current.txt b/wear/protolayout/protolayout-material/api/restricted_current.txt
index bd5e676..38c33fb 100644
--- a/wear/protolayout/protolayout-material/api/restricted_current.txt
+++ b/wear/protolayout/protolayout-material/api/restricted_current.txt
@@ -233,51 +233,35 @@
package androidx.wear.protolayout.material.layouts {
- @Deprecated public class EdgeContentLayout implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
- method @Deprecated public static androidx.wear.protolayout.material.layouts.EdgeContentLayout? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
- method @Deprecated public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getContent();
- method @Deprecated public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getEdgeContent();
- method @Deprecated public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getPrimaryLabelTextContent();
- method @Deprecated public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getSecondaryLabelTextContent();
- method @Deprecated public boolean isEdgeContentBehindAllOtherContent();
- }
-
- @Deprecated public static final class EdgeContentLayout.Builder {
- ctor @Deprecated public EdgeContentLayout.Builder(androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
- method @Deprecated public androidx.wear.protolayout.material.layouts.EdgeContentLayout build();
- method @Deprecated public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
- method @Deprecated public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setEdgeContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
- method @Deprecated public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setEdgeContentBehindAllOtherContent(boolean);
- method @Deprecated public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setPrimaryLabelTextContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
- method @Deprecated public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setSecondaryLabelTextContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
- }
-
- public final class EdgeContentLayout2 implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
- method public static androidx.wear.protolayout.material.layouts.EdgeContentLayout2? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+ public class EdgeContentLayout implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement {
+ method public static androidx.wear.protolayout.material.layouts.EdgeContentLayout? fromLayoutElement(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getContent();
method @Dimension(unit=androidx.annotation.Dimension.DP) public float getContentAndSecondaryLabelSpacing();
method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getEdgeContent();
method public float getEdgeContentThickness();
- method public androidx.wear.protolayout.expression.Fingerprint? getFingerprint();
- method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getPrimaryLabelContent();
- method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getSecondaryLabelContent();
+ method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getPrimaryLabelTextContent();
+ method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getSecondaryLabelTextContent();
+ method public boolean isEdgeContentBehindAllOtherContent();
+ method public boolean isResponsiveContentInsetEnabled();
}
- public static final class EdgeContentLayout2.Builder {
- ctor public EdgeContentLayout2.Builder(androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
- method public androidx.wear.protolayout.material.layouts.EdgeContentLayout2 build();
- method public androidx.wear.protolayout.material.layouts.EdgeContentLayout2.Builder setContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
- method public androidx.wear.protolayout.material.layouts.EdgeContentLayout2.Builder setContentAndSecondaryLabelSpacing(androidx.wear.protolayout.DimensionBuilders.DpProp);
- method public androidx.wear.protolayout.material.layouts.EdgeContentLayout2.Builder setEdgeContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
- method public androidx.wear.protolayout.material.layouts.EdgeContentLayout2.Builder setEdgeContentThickness(@Dimension(unit=androidx.annotation.Dimension.DP) float);
- method public androidx.wear.protolayout.material.layouts.EdgeContentLayout2.Builder setPrimaryLabelContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
- method public androidx.wear.protolayout.material.layouts.EdgeContentLayout2.Builder setSecondaryLabelContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+ public static final class EdgeContentLayout.Builder {
+ ctor public EdgeContentLayout.Builder(androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters);
+ method public androidx.wear.protolayout.material.layouts.EdgeContentLayout build();
+ method public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+ method public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setContentAndSecondaryLabelSpacing(androidx.wear.protolayout.DimensionBuilders.DpProp);
+ method public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setEdgeContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+ method public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setEdgeContentBehindAllOtherContent(boolean);
+ method public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setEdgeContentThickness(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+ method public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setPrimaryLabelTextContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+ method public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setResponsiveContentInsetEnabled(boolean);
+ method public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setSecondaryLabelTextContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
}
public class LayoutDefaults {
field public static final androidx.wear.protolayout.DimensionBuilders.DpProp DEFAULT_VERTICAL_SPACER_HEIGHT;
- field public static final androidx.wear.protolayout.DimensionBuilders.DpProp EDGE_CONTENT_LAYOUT2_CONTENT_AND_SECONDARY_LABEL_SPACING_DP;
- field public static final androidx.wear.protolayout.DimensionBuilders.DpProp EDGE_CONTENT_LAYOUT2_LARGE_CONTENT_AND_SECONDARY_LABEL_SPACING_DP;
+ field public static final androidx.wear.protolayout.DimensionBuilders.DpProp EDGE_CONTENT_LAYOUT_CONTENT_AND_SECONDARY_LABEL_SPACING_DP;
+ field public static final androidx.wear.protolayout.DimensionBuilders.DpProp EDGE_CONTENT_LAYOUT_LARGE_CONTENT_AND_SECONDARY_LABEL_SPACING_DP;
field public static final float EDGE_CONTENT_LAYOUT_PADDING_ABOVE_MAIN_CONTENT_DP = 6.0f;
field public static final float EDGE_CONTENT_LAYOUT_PADDING_BELOW_MAIN_CONTENT_DP = 8.0f;
field @Deprecated public static final int MULTI_BUTTON_MAX_NUMBER = 7; // 0x7
diff --git a/wear/protolayout/protolayout-material/src/androidTest/java/androidx/wear/protolayout/material/layouts/TestCasesGenerator.java b/wear/protolayout/protolayout-material/src/androidTest/java/androidx/wear/protolayout/material/layouts/TestCasesGenerator.java
index f726ebd..78cb89a 100644
--- a/wear/protolayout/protolayout-material/src/androidTest/java/androidx/wear/protolayout/material/layouts/TestCasesGenerator.java
+++ b/wear/protolayout/protolayout-material/src/androidTest/java/androidx/wear/protolayout/material/layouts/TestCasesGenerator.java
@@ -69,7 +69,6 @@
* different for different user font sizes. Note that some of the golden will have the same name
* as it should point on the same size independent image.
*/
- @SuppressWarnings("deprecation")
@NonNull
static Map<String, Layout> generateTestCases(
@NonNull Context context,
@@ -524,15 +523,16 @@
.build();
testCases.put(
"edgecontentlayout2_all_present_golden" + goldenSuffix,
- new EdgeContentLayout2.Builder(deviceParameters)
+ new EdgeContentLayout.Builder(deviceParameters)
+ .setResponsiveContentInsetEnabled(true)
.setEdgeContent(progressIndicatorBuilder.build())
- .setPrimaryLabelContent(
+ .setPrimaryLabelTextContent(
new Text.Builder(context, "Primary label")
.setTypography(Typography.TYPOGRAPHY_CAPTION1)
.setColor(argb(Colors.PRIMARY))
.build())
.setContent(mainContentText)
- .setSecondaryLabelContent(
+ .setSecondaryLabelTextContent(
new Text.Builder(context, "Secondary label")
.setTypography(Typography.TYPOGRAPHY_CAPTION1)
.setColor(argb(Colors.ON_SURFACE))
@@ -540,7 +540,8 @@
.build());
testCases.put(
"edgecontentlayout2_all_present_other_edgecontent_golden" + goldenSuffix,
- new EdgeContentLayout2.Builder(deviceParameters)
+ new EdgeContentLayout.Builder(deviceParameters)
+ .setResponsiveContentInsetEnabled(true)
.setEdgeContent(
new Arc.Builder()
.addContent(
@@ -554,13 +555,13 @@
.build())
.build())
.setEdgeContentThickness(12)
- .setPrimaryLabelContent(
+ .setPrimaryLabelTextContent(
new Text.Builder(context, "Primary label")
.setTypography(Typography.TYPOGRAPHY_CAPTION1)
.setColor(argb(Colors.PRIMARY))
.build())
.setContent(mainContentText)
- .setSecondaryLabelContent(
+ .setSecondaryLabelTextContent(
new Text.Builder(context, "Secondary label")
.setTypography(Typography.TYPOGRAPHY_CAPTION1)
.setColor(argb(Colors.ON_SURFACE))
@@ -568,12 +569,14 @@
.build());
testCases.put(
"edgecontentlayout2_only_edgecontent_golden" + NORMAL_SCALE_SUFFIX,
- new EdgeContentLayout2.Builder(deviceParameters)
+ new EdgeContentLayout.Builder(deviceParameters)
+ .setResponsiveContentInsetEnabled(true)
.setEdgeContent(progressIndicatorBuilder.build())
.build());
testCases.put(
"edgecontentlayout2_all_present_bigger_thickness_golden" + goldenSuffix,
- new EdgeContentLayout2.Builder(deviceParameters)
+ new EdgeContentLayout.Builder(deviceParameters)
+ .setResponsiveContentInsetEnabled(true)
.setEdgeContent(
new CircularProgressIndicator.Builder()
.setProgress(0.3f)
@@ -581,14 +584,14 @@
.build())
.setEdgeContentThickness(16
+ ProgressIndicatorDefaults.DEFAULT_PADDING.getValue())
- .setPrimaryLabelContent(
+ .setPrimaryLabelTextContent(
new Text.Builder(context, "Primary label that overflows")
.setTypography(Typography.TYPOGRAPHY_CAPTION1)
.setColor(argb(Colors.PRIMARY))
.setOverflow(LayoutElementBuilders.TEXT_OVERFLOW_ELLIPSIZE)
.build())
.setContent(mainContentText)
- .setSecondaryLabelContent(
+ .setSecondaryLabelTextContent(
new Text.Builder(context, "Secondary label")
.setTypography(Typography.TYPOGRAPHY_CAPTION1)
.setColor(argb(Colors.ON_SURFACE))
@@ -597,14 +600,15 @@
testCases.put(
"edgecontentlayout2_all_present_smaller_thickness_custom_spacer_golden"
+ goldenSuffix,
- new EdgeContentLayout2.Builder(deviceParameters)
+ new EdgeContentLayout.Builder(deviceParameters)
+ .setResponsiveContentInsetEnabled(true)
.setEdgeContent(
new CircularProgressIndicator.Builder()
.setProgress(0.3f)
.setStrokeWidth(2).build())
.setEdgeContentThickness(2
+ ProgressIndicatorDefaults.DEFAULT_PADDING.getValue())
- .setPrimaryLabelContent(
+ .setPrimaryLabelTextContent(
new Text.Builder(context, "Primary label that overflows")
.setTypography(Typography.TYPOGRAPHY_CAPTION1)
.setColor(argb(Colors.PRIMARY))
@@ -612,7 +616,7 @@
.build())
.setContent(mainContentText)
.setContentAndSecondaryLabelSpacing(dp(11))
- .setSecondaryLabelContent(
+ .setSecondaryLabelTextContent(
new Text.Builder(context, "Secondary label")
.setTypography(Typography.TYPOGRAPHY_CAPTION1)
.setColor(argb(Colors.ON_SURFACE))
@@ -620,9 +624,10 @@
.build());
testCases.put(
"edgecontentlayout2_all_present_overflows_golden" + goldenSuffix,
- new EdgeContentLayout2.Builder(deviceParameters)
+ new EdgeContentLayout.Builder(deviceParameters)
+ .setResponsiveContentInsetEnabled(true)
.setEdgeContent(progressIndicatorBuilder.build())
- .setPrimaryLabelContent(
+ .setPrimaryLabelTextContent(
new Text.Builder(context, "Primary label that overflows")
.setTypography(Typography.TYPOGRAPHY_CAPTION1)
.setColor(argb(Colors.PRIMARY))
@@ -634,7 +639,7 @@
.setTypography(Typography.TYPOGRAPHY_DISPLAY2)
.setOverflow(LayoutElementBuilders.TEXT_OVERFLOW_ELLIPSIZE)
.build())
- .setSecondaryLabelContent(
+ .setSecondaryLabelTextContent(
new Text.Builder(context, "Secondary label that overflows")
.setTypography(Typography.TYPOGRAPHY_CAPTION1)
.setColor(argb(Colors.ON_SURFACE))
@@ -643,10 +648,11 @@
.build());
testCases.put(
"edgecontentlayout2_no_primarylabel_golden" + goldenSuffix,
- new EdgeContentLayout2.Builder(deviceParameters)
+ new EdgeContentLayout.Builder(deviceParameters)
+ .setResponsiveContentInsetEnabled(true)
.setEdgeContent(progressIndicatorBuilder.build())
.setContent(mainContentText)
- .setSecondaryLabelContent(
+ .setSecondaryLabelTextContent(
new Text.Builder(context, "Secondary label")
.setTypography(Typography.TYPOGRAPHY_CAPTION1)
.setColor(argb(Colors.ON_SURFACE))
@@ -654,9 +660,10 @@
.build());
testCases.put(
"edgecontentlayout2_no_secondarylabel_present_golden" + goldenSuffix,
- new EdgeContentLayout2.Builder(deviceParameters)
+ new EdgeContentLayout.Builder(deviceParameters)
+ .setResponsiveContentInsetEnabled(true)
.setEdgeContent(progressIndicatorBuilder.build())
- .setPrimaryLabelContent(
+ .setPrimaryLabelTextContent(
new Text.Builder(context, "Primary label")
.setTypography(Typography.TYPOGRAPHY_CAPTION1)
.setColor(argb(Colors.PRIMARY))
@@ -665,15 +672,16 @@
.build());
testCases.put(
"edgecontentlayout2_all_double_secondarylabel_present_golden" + goldenSuffix,
- new EdgeContentLayout2.Builder(deviceParameters)
+ new EdgeContentLayout.Builder(deviceParameters)
+ .setResponsiveContentInsetEnabled(true)
.setEdgeContent(progressIndicatorBuilder.build())
- .setPrimaryLabelContent(
+ .setPrimaryLabelTextContent(
new Text.Builder(context, "Primary label")
.setTypography(Typography.TYPOGRAPHY_CAPTION1)
.setColor(argb(Colors.PRIMARY))
.build())
.setContent(mainContentText)
- .setSecondaryLabelContent(
+ .setSecondaryLabelTextContent(
new Column.Builder()
.addContent(
new Text.Builder(context, "Data point 1")
diff --git a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/CircularProgressIndicator.java b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/CircularProgressIndicator.java
index f0865e4..b9d4517 100644
--- a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/CircularProgressIndicator.java
+++ b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/CircularProgressIndicator.java
@@ -238,7 +238,7 @@
* additional margin around it by setting it to {@code false}.
*
* <p>Otherwise, if this indicator is used as a full screen one or in {@link
- * androidx.wear.protolayout.material.layouts.EdgeContentLayout2}, it's strongly recommended
+ * androidx.wear.protolayout.material.layouts.EdgeContentLayout}, it's strongly recommended
* to set this to {@code true}.
*
* <p>If not set, defaults to true.
diff --git a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/layouts/EdgeContentLayout.java b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/layouts/EdgeContentLayout.java
index 4fcbdf0..31f4d57 100644
--- a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/layouts/EdgeContentLayout.java
+++ b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/layouts/EdgeContentLayout.java
@@ -16,19 +16,28 @@
package androidx.wear.protolayout.material.layouts;
+import static androidx.annotation.Dimension.DP;
import static androidx.wear.protolayout.DimensionBuilders.dp;
import static androidx.wear.protolayout.DimensionBuilders.expand;
+import static androidx.wear.protolayout.DimensionBuilders.wrap;
import static androidx.wear.protolayout.material.ProgressIndicatorDefaults.DEFAULT_PADDING;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.EDGE_CONTENT_LAYOUT_CONTENT_AND_SECONDARY_LABEL_SPACING_DP;
import static androidx.wear.protolayout.material.layouts.LayoutDefaults.EDGE_CONTENT_LAYOUT_MARGIN_HORIZONTAL_ROUND_DP;
import static androidx.wear.protolayout.material.layouts.LayoutDefaults.EDGE_CONTENT_LAYOUT_MARGIN_HORIZONTAL_SQUARE_DP;
import static androidx.wear.protolayout.material.layouts.LayoutDefaults.EDGE_CONTENT_LAYOUT_PADDING_ABOVE_MAIN_CONTENT_DP;
import static androidx.wear.protolayout.material.layouts.LayoutDefaults.EDGE_CONTENT_LAYOUT_PADDING_BELOW_MAIN_CONTENT_DP;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.EDGE_CONTENT_LAYOUT_RESPONSIVE_MARGIN_HORIZONTAL_PERCENT;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.EDGE_CONTENT_LAYOUT_RESPONSIVE_MARGIN_VERTICAL_PERCENT;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.EDGE_CONTENT_LAYOUT_RESPONSIVE_OUTER_MARGIN_DP;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.LAYOUTS_LABEL_PADDING_PERCENT;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.insetElementWithPadding;
import static androidx.wear.protolayout.materialcore.Helper.checkNotNull;
import static androidx.wear.protolayout.materialcore.Helper.checkTag;
import static androidx.wear.protolayout.materialcore.Helper.getMetadataTagBytes;
import static androidx.wear.protolayout.materialcore.Helper.getTagBytes;
import static androidx.wear.protolayout.materialcore.Helper.isRoundDevice;
+import androidx.annotation.Dimension;
import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -36,6 +45,7 @@
import androidx.annotation.RestrictTo.Scope;
import androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters;
import androidx.wear.protolayout.DimensionBuilders.DpProp;
+import androidx.wear.protolayout.DimensionBuilders.SpacerDimension;
import androidx.wear.protolayout.LayoutElementBuilders;
import androidx.wear.protolayout.LayoutElementBuilders.Box;
import androidx.wear.protolayout.LayoutElementBuilders.Column;
@@ -57,7 +67,7 @@
* ProtoLayout layout that represents the suggested layout style for Material ProtoLayout, which has
* content around the edge of the screen (e.g. a ProgressIndicator) and the given content inside of
* it with the recommended margin and padding applied. Optional primary or secondary label can be
- * added above and below the main content, respectively.
+ * added above and below the additional content, respectively.
*
* <p>When accessing the contents of a container for testing, note that this element can't be simply
* casted back to the original type, i.e.:
@@ -78,12 +88,8 @@
* EdgeContentLayout myEcl =
* EdgeContentLayout.fromLayoutElement(box.getContents().get(0));
* }</pre>
- *
- * @deprecated Please use new version of this layout, {@link EdgeContentLayout2} that ensures that
- * tiles in the carousel are consistent and behave correctly on different screen sizes.
*/
// TODO(b/274916652): Link visuals once they are available.
-@Deprecated
public class EdgeContentLayout implements LayoutElement {
/**
* Prefix tool tag for Metadata in Modifiers, so we know that Box is actually a
@@ -113,23 +119,29 @@
* Bit position in a byte on {@link #FLAG_INDEX} index in metadata byte array to check whether
* the primary label is present or not.
*/
- static final int PRIMARY_LABEL_PRESENT = 0x2;
+ static final int PRIMARY_LABEL_PRESENT = 1 << 1;
/**
* Bit position in a byte on {@link #FLAG_INDEX} index in metadata byte array to check whether
* the secondary label is present or not.
*/
- static final int SECONDARY_LABEL_PRESENT = 0x4;
+ static final int SECONDARY_LABEL_PRESENT = 1 << 2;
/**
* Bit position in a byte on {@link #FLAG_INDEX} index in metadata byte array to check whether
- * the main content is present or not.
+ * the additional content is present or not.
*/
- static final int CONTENT_PRESENT = 0x8;
+ static final int CONTENT_PRESENT = 1 << 3;
/**
* Bit position in a byte on {@link #FLAG_INDEX} index in metadata byte array to check whether
- * the edge content is added before the main content (0) or after it (1).
+ * the edge content is added before the additional content (0) or after it (1).
*/
- static final int EDGE_CONTENT_POSITION = 0x10;
+ static final int EDGE_CONTENT_POSITION = 1 << 4;
+
+ /**
+ * Bit position in a byte on {@link #FLAG_INDEX} index in metadata byte array to check whether
+ * the responsive content inset is used or not.
+ */
+ static final int CONTENT_INSET_USED = 1 << 5;
@RestrictTo(Scope.LIBRARY)
@Retention(RetentionPolicy.SOURCE)
@@ -140,30 +152,15 @@
PRIMARY_LABEL_PRESENT,
SECONDARY_LABEL_PRESENT,
CONTENT_PRESENT,
- EDGE_CONTENT_POSITION
+ EDGE_CONTENT_POSITION,
+ CONTENT_INSET_USED
})
@interface ContentBits {}
@NonNull private final Box mImpl;
- // This contains optional labels, spacers and main content.
- @NonNull private final List<LayoutElement> mInnerColumn;
-
- // This contains edge content;
- @Nullable private final LayoutElement mEdgeContent;
- private final boolean mIsEdgeContentBehind;
-
EdgeContentLayout(@NonNull Box layoutElement) {
this.mImpl = layoutElement;
- // This contains inner columns and edge content.
- List<LayoutElement> contents = mImpl.getContents();
- int edgeContentIndex = (getMetadataTag()[FLAG_INDEX] & EDGE_CONTENT_POSITION) == 0 ? 0 : 1;
- int contentIndex = 1 - edgeContentIndex;
- this.mInnerColumn =
- ((Column) ((Box) contents.get(contentIndex)).getContents().get(0)).getContents();
- this.mEdgeContent =
- areElementsPresent(EDGE_CONTENT_PRESENT) ? contents.get(edgeContentIndex) : null;
- mIsEdgeContentBehind = edgeContentIndex == 0;
}
/** Builder class for {@link EdgeContentLayout}. */
@@ -175,17 +172,84 @@
@Nullable private LayoutElement mContent = null;
private byte mMetadataContentByte = 0;
private boolean mIsEdgeContentBehind = false;
+ private boolean mIsResponsiveInsetEnabled = false;
+ @Nullable private Float mEdgeContentThickness = null;
+ @NonNull
+ private DpProp mVerticalSpacerHeight =
+ EDGE_CONTENT_LAYOUT_CONTENT_AND_SECONDARY_LABEL_SPACING_DP;
/**
- * Creates a builder for the {@link EdgeContentLayout}t. Custom content inside of it can
+ * Creates a builder for the {@link EdgeContentLayout}. Custom content inside of it can
* later be set with ({@link #setContent}.
+ *
+ * <p>For optimal layouts across different screen sizes and better alignment with UX
+ * guidelines, it is highly recommended to call {@link #setResponsiveContentInsetEnabled}.
*/
public Builder(@NonNull DeviceParameters deviceParameters) {
this.mDeviceParameters = deviceParameters;
}
/**
+ * Changes this {@link EdgeContentLayout} to better follow guidelines for type of layout
+ * that has content around the edge.
+ *
+ * <p>These updates include:
+ * 1. Using responsive insets for its content primary and secondary label by adding some
+ * additional space on the sides of these elements to avoid content going off the screen
+ * edge.
+ * 2. Changing layout padding to responsive to better follow different screen sizes.
+ * 3. Positioning primary label at a fixed place on top of the screen rather than
+ * following additional content.
+ *
+ * <p>It is highly recommended to call this method with {@code true} when using this layout
+ * to optimize it for different screen sizes.
+ *
+ * @throws IllegalStateException if this and
+ * {@link #setEdgeContentBehindAllOtherContent(boolean)} are used together.
+ */
+ @NonNull
+ public Builder setResponsiveContentInsetEnabled(boolean enabled) {
+ if (mIsEdgeContentBehind) {
+ // We don't allow mixing this method with responsiveness.
+ throw new IllegalStateException(
+ "Setters setResponsiveContentInsetEnabled and "
+ + "setEdgeContentBehindAllOtherContent can't be used together. "
+ + "Please use only setResponsiveContentInsetEnabled, which will "
+ + "always place the edge content behind other content.");
+ }
+
+ this.mIsResponsiveInsetEnabled = enabled;
+ if (enabled) {
+ mMetadataContentByte = (byte) (mMetadataContentByte | CONTENT_INSET_USED);
+ } else {
+ mMetadataContentByte = (byte) (mMetadataContentByte & ~CONTENT_INSET_USED);
+ }
+ return this;
+ }
+
+ /**
+ * Sets the thickness of the hollow edge content so that other content is correctly placed.
+ * In other words, sets the space that should be reserved exclusively for the edge
+ * content and not be overdrawn by other inner content.
+ *
+ * <p>For example, for {@link CircularProgressIndicator} or {@link
+ * androidx.wear.protolayout.LayoutElementBuilders.ArcLine} elements, this should be equal
+ * to their stroke width/thickness.
+ *
+ * <p>Note that, calling this method when responsiveness is not set with
+ * {@link #setResponsiveContentInsetEnabled}, will be ignored.
+ */
+ @NonNull
+ public Builder setEdgeContentThickness(@Dimension(unit = DP) float thickness) {
+ this.mEdgeContentThickness = thickness;
+ return this;
+ }
+
+ /**
* Sets the content to be around the edges. This can be {@link CircularProgressIndicator}.
+ *
+ * <p>If this content is something other that {@link CircularProgressIndicator}, please add
+ * its thickness with {@link #setEdgeContentThickness} for best results.
*/
@NonNull
public Builder setEdgeContent(@NonNull LayoutElement edgeContent) {
@@ -194,7 +258,17 @@
return this;
}
- /** Sets the content in the primary label slot which will be above the main content. */
+ /**
+ * Sets the content in the primary label slot.
+ *
+ * <p>Depending on whether {@link #setResponsiveContentInsetEnabled} is set to true or
+ * not, this label will be placed as following:
+ * - If responsive behaviour is set, label will be above the additional content, on a fixed
+ * place to ensure Tiles consistency with other layouts. Additionally, the label will
+ * also have an inset to prevent it from going off the screen.
+ * - If responsive behaviour is not set or called, label will be above the additional
+ * content, centered in the remaining space.
+ */
@NonNull
public Builder setPrimaryLabelTextContent(@NonNull LayoutElement primaryLabelText) {
this.mPrimaryLabelText = primaryLabelText;
@@ -203,8 +277,11 @@
}
/**
- * Sets the content in the secondary label slot which will be below the main content. It is
- * highly recommended to have primary label set when having secondary label.
+ * Sets the content in the secondary label slot which will be below the additional content.
+ * It is highly recommended to have primary label set when having secondary label.
+ *
+ * <p>Note that when {@link #setResponsiveContentInsetEnabled} is set to {@code true}, the
+ * label will also have an inset to prevent it from going off the screen.
*/
@NonNull
public Builder setSecondaryLabelTextContent(@NonNull LayoutElement secondaryLabelText) {
@@ -222,12 +299,42 @@
}
/**
+ * Sets the space size between the additional content and secondary label if there is any.
+ * If one of those is not present, spacer is not used. If not set,
+ * {@link LayoutDefaults#EDGE_CONTENT_LAYOUT_CONTENT_AND_SECONDARY_LABEL_SPACING_DP} will
+ * be used.
+ *
+ * <p>Note that, this method should be used together with
+ * {@link #setResponsiveContentInsetEnabled}, otherwise it will be ignored.
+ */
+ @NonNull
+ public Builder setContentAndSecondaryLabelSpacing(@NonNull DpProp height) {
+ this.mVerticalSpacerHeight = height;
+ return this;
+ }
+
+ /**
* Sets whether the edge content passed in with {@link #setEdgeContent} should be positioned
* behind all other content in this layout or above it. If not set, defaults to {@code
* false}, meaning that the edge content will be placed above all other content.
+ *
+ * <p>Note that, if {@link #setResponsiveContentInsetEnabled} is set to {@code true}, edge
+ * content will always go behind all other content and this method call will be ignored.
+ *
+ * @throws IllegalStateException if this and {@link #setResponsiveContentInsetEnabled}
+ * are used together.
*/
@NonNull
public Builder setEdgeContentBehindAllOtherContent(boolean isBehind) {
+ if (mIsResponsiveInsetEnabled) {
+ // We don't allow mixing this method with responsiveness.
+ throw new IllegalStateException(
+ "Setters setResponsiveContentInsetEnabled and "
+ + "setEdgeContentBehindAllOtherContent can't be used together. "
+ + "Please use only setResponsiveContentInsetEnabled, which will "
+ + "always place the edge content behind other content.");
+ }
+
this.mIsEdgeContentBehind = isBehind;
return this;
}
@@ -236,6 +343,148 @@
@NonNull
@Override
public EdgeContentLayout build() {
+ if (mIsResponsiveInsetEnabled && mIsEdgeContentBehind) {
+ // We don't allow mixing this method with responsiveness.
+ throw new IllegalStateException(
+ "Setters setResponsiveContentInsetEnabled and "
+ + "setEdgeContentBehindAllOtherContent can't be used together. "
+ + "Please use only setResponsiveContentInsetEnabled, which will "
+ + "always place the edge content behind other content.");
+ }
+
+ return mIsResponsiveInsetEnabled ? responsiveLayoutBuild() : legacyLayoutBuild();
+ }
+
+ @NonNull
+ private EdgeContentLayout responsiveLayoutBuild() {
+ // Calculate what is the inset box max size, i.e., the size that all content can occupy
+ // without the edge content.
+ // Use provided thickness if set. Otherwise, see if we can get it from
+ // CircularProgressIndicator.
+ float edgeContentSize = getEdgeContentSize();
+
+ DpProp contentHeight = dp(
+ mDeviceParameters.getScreenWidthDp() - edgeContentSize);
+ DpProp contentWidth = dp(
+ mDeviceParameters.getScreenHeightDp() - edgeContentSize);
+
+ // TODO(b/321681652): Confirm with the UX if we can put 6dp as outer margin so it
+ // matches CPI.
+ float outerMargin =
+ mEdgeContent instanceof CircularProgressIndicator
+ ? EDGE_CONTENT_LAYOUT_RESPONSIVE_OUTER_MARGIN_DP
+ - DEFAULT_PADDING.getValue()
+ : EDGE_CONTENT_LAYOUT_RESPONSIVE_OUTER_MARGIN_DP;
+
+ // Horizontal and vertical padding added to the inner content.
+ float horizontalPaddingDp =
+ EDGE_CONTENT_LAYOUT_RESPONSIVE_MARGIN_HORIZONTAL_PERCENT
+ * mDeviceParameters.getScreenWidthDp();
+ float verticalPaddingDp =
+ EDGE_CONTENT_LAYOUT_RESPONSIVE_MARGIN_VERTICAL_PERCENT
+ * mDeviceParameters.getScreenWidthDp();
+
+ // Padding to restrict labels from going off the screen.
+ float labelHorizontalPaddingDp =
+ mDeviceParameters.getScreenWidthDp() * LAYOUTS_LABEL_PADDING_PERCENT;
+
+ Modifiers modifiers =
+ new Modifiers.Builder()
+ .setPadding(
+ new Padding.Builder()
+ .setRtlAware(true)
+ .setStart(dp(horizontalPaddingDp))
+ .setEnd(dp(horizontalPaddingDp))
+ .setTop(dp(verticalPaddingDp))
+ .setBottom(dp(verticalPaddingDp))
+ .build())
+ .build();
+
+ // In this variant, it's always behind so resetting the flag to 0.
+ mMetadataContentByte = (byte) (mMetadataContentByte & ~EDGE_CONTENT_POSITION);
+ byte[] metadata = METADATA_TAG_BASE.clone();
+ metadata[FLAG_INDEX] = mMetadataContentByte;
+
+ Box.Builder layout =
+ new Box.Builder()
+ .setWidth(dp(mDeviceParameters.getScreenWidthDp()))
+ .setHeight(dp(mDeviceParameters.getScreenHeightDp()))
+ .setModifiers(
+ new Modifiers.Builder()
+ .setMetadata(
+ new ElementMetadata.Builder()
+ .setTagData(metadata).build())
+ .setPadding(
+ new Padding.Builder()
+ .setAll(dp(outerMargin))
+ .setRtlAware(true).build())
+ .build());
+
+ if (mEdgeContent != null) {
+ layout.addContent(mEdgeContent);
+ }
+
+ // Contains primary label, additional content and secondary label.
+ Column.Builder allInnerContent =
+ new Column.Builder()
+ .setWidth(contentWidth)
+ .setHeight(contentHeight)
+ .setModifiers(modifiers);
+
+ if (mPrimaryLabelText != null) {
+ allInnerContent.addContent(
+ insetElementWithPadding(mPrimaryLabelText, labelHorizontalPaddingDp));
+ // TODO(b/321681652): Confirm with the UX that we don't need a space after this
+ // abel.
+ }
+
+ // Contains additional content and secondary label with wrapped height so it can be put
+ // inside of the Box to be centered. This is because primary label stays on top at
+ // the fixed place, while this content should be centered in the remaining space.
+ Column.Builder contentSecondaryLabel =
+ new Column.Builder().setWidth(expand()).setHeight(wrap());
+
+ if (mContent != null) {
+ contentSecondaryLabel.addContent(mContent);
+ }
+
+ if (mSecondaryLabelText != null) {
+ if (mContent != null) {
+ contentSecondaryLabel.addContent(
+ new Spacer.Builder().setHeight(mVerticalSpacerHeight).build());
+ }
+ contentSecondaryLabel.addContent(
+ insetElementWithPadding(mSecondaryLabelText, labelHorizontalPaddingDp));
+ }
+
+ allInnerContent.addContent(
+ new Box.Builder()
+ .setWidth(expand())
+ .setHeight(expand())
+ .addContent(contentSecondaryLabel.build())
+ .build());
+
+ layout.addContent(allInnerContent.build());
+
+ return new EdgeContentLayout(layout.build());
+ }
+
+ private float getEdgeContentSize() {
+ float edgeContentThickness =
+ mEdgeContentThickness == null
+ ?
+ // When not set, we try to get the thickness from CPI, otherwise we can
+ // only use 0.
+ (mEdgeContent instanceof CircularProgressIndicator
+ ? ((CircularProgressIndicator) mEdgeContent)
+ .getStrokeWidth().getValue()
+ : 0)
+ : mEdgeContentThickness;
+ return 2 * (EDGE_CONTENT_LAYOUT_RESPONSIVE_OUTER_MARGIN_DP + edgeContentThickness);
+ }
+
+ @NonNull
+ private EdgeContentLayout legacyLayoutBuild() {
float thicknessDp =
mEdgeContent instanceof CircularProgressIndicator
? ((CircularProgressIndicator) mEdgeContent).getStrokeWidth().getValue()
@@ -245,11 +494,11 @@
? EDGE_CONTENT_LAYOUT_MARGIN_HORIZONTAL_ROUND_DP
: EDGE_CONTENT_LAYOUT_MARGIN_HORIZONTAL_SQUARE_DP;
float indicatorWidth = 2 * (thicknessDp + DEFAULT_PADDING.getValue());
- float mainContentHeightDp = mDeviceParameters.getScreenHeightDp() - indicatorWidth;
- float mainContentWidthDp = mDeviceParameters.getScreenWidthDp() - indicatorWidth;
+ float contentHeightDp = mDeviceParameters.getScreenHeightDp() - indicatorWidth;
+ float contentWidthDp = mDeviceParameters.getScreenWidthDp() - indicatorWidth;
- DpProp mainContentHeight = dp(Math.min(mainContentHeightDp, mainContentWidthDp));
- DpProp mainContentWidth = dp(Math.min(mainContentHeightDp, mainContentWidthDp));
+ DpProp contentHeight = dp(Math.min(contentHeightDp, contentWidthDp));
+ DpProp contentWidth = dp(Math.min(contentHeightDp, contentWidthDp));
Modifiers modifiers =
new Modifiers.Builder()
@@ -262,7 +511,7 @@
.build();
if (!mIsEdgeContentBehind) {
- // If the edge content is above the main one, then its index should be 1.
+ // If the edge content is above the additional one, then its index should be 1.
// Otherwise it's 0.
mMetadataContentByte = (byte) (mMetadataContentByte | EDGE_CONTENT_POSITION);
}
@@ -316,8 +565,8 @@
.setModifiers(modifiers)
.setVerticalAlignment(LayoutElementBuilders.VERTICAL_ALIGN_CENTER)
.setHorizontalAlignment(LayoutElementBuilders.HORIZONTAL_ALIGN_CENTER)
- .setHeight(mainContentHeight)
- .setWidth(mainContentWidth)
+ .setHeight(contentHeight)
+ .setWidth(contentWidth)
.addContent(innerContentBuilder.build())
.build();
@@ -353,10 +602,22 @@
if (!areElementsPresent(CONTENT_PRESENT)) {
return null;
}
- // By tag we know that content exists. It will be at position 0 if there is no primary
- // label, or at position 2 (primary label, spacer - content) otherwise.
- int contentPosition = areElementsPresent(PRIMARY_LABEL_PRESENT) ? 2 : 0;
- return ((Box) mInnerColumn.get(contentPosition)).getContents().get(0);
+ if (isResponsiveContentInsetEnabled()) {
+ return getInnerColumnContentsForResponsive().get(0);
+ } else {
+ // By tag we know that content exists. It will be at position 0 if there is no primary
+ // label, or at position 2 (primary label, spacer - content) otherwise.
+ int contentPosition = areElementsPresent(PRIMARY_LABEL_PRESENT) ? 2 : 0;
+ return ((Box) getInnerContent(contentPosition)).getContents().get(0);
+ }
+ }
+
+ /**
+ * Returns element from the inner content that is on the given index. It is a callers
+ * responsibility to pass in the correct index.
+ */
+ private LayoutElement getInnerContent(int contentPosition) {
+ return getAllContent().getContents().get(contentPosition);
}
/** Get the primary label content from this layout. */
@@ -365,8 +626,11 @@
if (!areElementsPresent(PRIMARY_LABEL_PRESENT)) {
return null;
}
- // By tag we know that primary label exists. It will always be at position 0.
- return mInnerColumn.get(0);
+ // By tag we know that primary label exists. It will always be at position 0 in the inner
+ // content area.
+ return isResponsiveContentInsetEnabled()
+ ? ((Box) getInnerContent(0)).getContents().get(0)
+ : getInnerContent(0);
}
/** Get the secondary label content from this layout. */
@@ -375,19 +639,94 @@
if (!areElementsPresent(SECONDARY_LABEL_PRESENT)) {
return null;
}
- // By tag we know that secondary label exists. It will always be at last position.
- return mInnerColumn.get(mInnerColumn.size() - 1);
+ if (isResponsiveContentInsetEnabled()) {
+ List<LayoutElement> innerColumnContents = getInnerColumnContentsForResponsive();
+ return ((Box) innerColumnContents.get(innerColumnContents.size() - 1))
+ .getContents().get(0);
+ } else {
+ // By tag we know that secondary label exists. It will always be at last position.
+ List<LayoutElement> mInnerColumn = getAllContent().getContents();
+ return mInnerColumn.get(mInnerColumn.size() - 1);
+ }
+ }
+
+ /** Get the size of spacing between content and secondary from this layout. */
+ @Dimension(unit = Dimension.DP)
+ public float getContentAndSecondaryLabelSpacing() {
+ if (!isResponsiveContentInsetEnabled()) {
+ return EDGE_CONTENT_LAYOUT_CONTENT_AND_SECONDARY_LABEL_SPACING_DP.getValue();
+ }
+
+ List<LayoutElement> innerColumnContents = getInnerColumnContentsForResponsive();
+ if (areElementsPresent(CONTENT_PRESENT) && areElementsPresent(SECONDARY_LABEL_PRESENT)) {
+ LayoutElement element =
+ ((Box) innerColumnContents.get(innerColumnContents.size() - 2))
+ .getContents().get(0);
+ if (element instanceof Spacer) {
+ SpacerDimension height = ((Spacer) element).getHeight();
+ if (height instanceof DpProp) {
+ return ((DpProp) height).getValue();
+ }
+ }
+ }
+ return EDGE_CONTENT_LAYOUT_CONTENT_AND_SECONDARY_LABEL_SPACING_DP.getValue();
}
/** Returns the edge content from this layout. */
@Nullable
public LayoutElement getEdgeContent() {
- return mEdgeContent;
+ return areElementsPresent(EDGE_CONTENT_PRESENT)
+ ? mImpl.getContents().get(getEdgeContentPosition()) : null;
+ }
+
+ private int getEdgeContentPosition() {
+ return isEdgeContentBehindAllOtherContent() ? 0 : 1;
}
/** Returns if the edge content has been placed behind the other contents. */
public boolean isEdgeContentBehindAllOtherContent() {
- return mIsEdgeContentBehind;
+ return (getMetadataTag()[FLAG_INDEX] & EDGE_CONTENT_POSITION) == 0;
+ }
+
+ /** Returns whether the contents from this layout are using responsive inset. */
+ public boolean isResponsiveContentInsetEnabled() {
+ return areElementsPresent(CONTENT_INSET_USED);
+ }
+
+ /** Returns the total size of the edge content including margins. */
+ public float getEdgeContentThickness() {
+ Column allContent = getAllContent();
+ if (mImpl.getWidth() instanceof DpProp && allContent.getWidth() instanceof DpProp) {
+ float edgeContentTotalThickness =
+ ((DpProp) mImpl.getWidth()).getValue()
+ - ((DpProp) allContent.getWidth()).getValue();
+ return edgeContentTotalThickness / 2 - EDGE_CONTENT_LAYOUT_RESPONSIVE_OUTER_MARGIN_DP;
+ }
+ return 0;
+ }
+
+ /** Returns Column that may contain primary label, additional content and secondary label. */
+ private Column getAllContent() {
+ int contentIndex = 1 - getEdgeContentPosition();
+ return (Column) (isResponsiveContentInsetEnabled()
+ ? mImpl.getContents().get(areElementsPresent(EDGE_CONTENT_PRESENT)
+ ? 1 : 0)
+ : ((Box) mImpl.getContents().get(contentIndex)).getContents().get(0));
+ }
+
+ /**
+ * Returns all content inside of the inner Column that may contain additional content, spacer
+ * and secondary label.
+ */
+ private List<LayoutElement> getInnerColumnContentsForResponsive() {
+ return ((Column)
+ ((Box)
+ getAllContent()
+ .getContents()
+ .get(areElementsPresent(PRIMARY_LABEL_PRESENT) ? 1 : 0))
+ .getContents()
+ .get(0))
+ .getContents();
}
/**
diff --git a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/layouts/EdgeContentLayout2.java b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/layouts/EdgeContentLayout2.java
deleted file mode 100644
index cf88574..0000000
--- a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/layouts/EdgeContentLayout2.java
+++ /dev/null
@@ -1,504 +0,0 @@
-/*
- * Copyright 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.wear.protolayout.material.layouts;
-
-import static androidx.annotation.Dimension.DP;
-import static androidx.wear.protolayout.DimensionBuilders.dp;
-import static androidx.wear.protolayout.DimensionBuilders.expand;
-import static androidx.wear.protolayout.DimensionBuilders.wrap;
-import static androidx.wear.protolayout.material.ProgressIndicatorDefaults.DEFAULT_PADDING;
-import static androidx.wear.protolayout.material.layouts.LayoutDefaults.EDGE_CONTENT_LAYOUT2_MARGIN_HORIZONTAL_PERCENT;
-import static androidx.wear.protolayout.material.layouts.LayoutDefaults.EDGE_CONTENT_LAYOUT2_MARGIN_VERTICAL_PERCENT;
-import static androidx.wear.protolayout.material.layouts.LayoutDefaults.EDGE_CONTENT_LAYOUT2_OUTER_MARGIN_DP;
-import static androidx.wear.protolayout.material.layouts.LayoutDefaults.EDGE_CONTENT_LAYOUT2_CONTENT_AND_SECONDARY_LABEL_SPACING_DP;
-import static androidx.wear.protolayout.material.layouts.LayoutDefaults.LAYOUTS_LABEL_PADDING_PERCENT;
-import static androidx.wear.protolayout.material.layouts.LayoutDefaults.insetElementWithPadding;
-import static androidx.wear.protolayout.materialcore.Helper.checkNotNull;
-import static androidx.wear.protolayout.materialcore.Helper.checkTag;
-import static androidx.wear.protolayout.materialcore.Helper.getMetadataTagBytes;
-import static androidx.wear.protolayout.materialcore.Helper.getTagBytes;
-
-import android.annotation.SuppressLint;
-
-import androidx.annotation.Dimension;
-import androidx.annotation.IntDef;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.RestrictTo;
-import androidx.annotation.RestrictTo.Scope;
-import androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters;
-import androidx.wear.protolayout.DimensionBuilders.DpProp;
-import androidx.wear.protolayout.DimensionBuilders.SpacerDimension;
-import androidx.wear.protolayout.LayoutElementBuilders.Box;
-import androidx.wear.protolayout.LayoutElementBuilders.Column;
-import androidx.wear.protolayout.LayoutElementBuilders.LayoutElement;
-import androidx.wear.protolayout.LayoutElementBuilders.Spacer;
-import androidx.wear.protolayout.ModifiersBuilders.ElementMetadata;
-import androidx.wear.protolayout.ModifiersBuilders.Modifiers;
-import androidx.wear.protolayout.ModifiersBuilders.Padding;
-import androidx.wear.protolayout.expression.Fingerprint;
-import androidx.wear.protolayout.material.CircularProgressIndicator;
-import androidx.wear.protolayout.proto.LayoutElementProto;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * ProtoLayout layout that represents the suggested layout style for Material ProtoLayout, which has
- * content around the edge of the screen (e.g. a CircularProgressIndicator) and the given content
- * inside of it with the recommended margin and padding applied. Optional primary or secondary label
- * can be added above and below the additional content, respectively.
- *
- * <p>When accessing the contents of a container for testing, note that this element can't be simply
- * casted back to the original type, i.e.:
- *
- * <pre>{@code
- * EdgeContentLayout2 ecl = new EdgeContentLayout2...
- * Box box = new Box.Builder().addContent(ecl).build();
- *
- * EdgeContentLayout2 myEcl = (EdgeContentLayout2) box.getContents().get(0);
- * }</pre>
- *
- * will fail.
- *
- * <p>To be able to get {@link EdgeContentLayout2} object from any layout element, {@link
- * #fromLayoutElement} method should be used, i.e.:
- *
- * <pre>{@code
- * EdgeContentLayout2 myEcl =
- * EdgeContentLayout.fromLayoutElement(box.getContents().get(0));
- * }</pre>
- */
-// TODO(b/274916652): Link visuals once they are available.
-public final class EdgeContentLayout2 implements LayoutElement {
- /**
- * Prefix tool tag for Metadata in Modifiers, so we know that Box is actually a
- * EdgeContentLayout.
- */
- static final String METADATA_TAG_PREFIX = "ECL2_";
-
- /**
- * Index for byte array that contains bits to check whether the content and indicator are
- * present or not.
- */
- static final int FLAG_INDEX = METADATA_TAG_PREFIX.length();
-
- /**
- * Base tool tag for Metadata in Modifiers, so we know that Box is actually a EdgeContentLayout
- * and what optional content is added.
- */
- static final byte[] METADATA_TAG_BASE =
- Arrays.copyOf(getTagBytes(METADATA_TAG_PREFIX), FLAG_INDEX + 1);
-
- /**
- * Bit position in a byte on {@link #FLAG_INDEX} index in metadata byte array to check whether
- * the edge content is present or not.
- */
- static final int EDGE_CONTENT_PRESENT = 0x1;
-
- /**
- * Bit position in a byte on {@link #FLAG_INDEX} index in metadata byte array to check whether
- * the primary label is present or not.
- */
- static final int PRIMARY_LABEL_PRESENT = 1 << 1;
-
- /**
- * Bit position in a byte on {@link #FLAG_INDEX} index in metadata byte array to check whether
- * the secondary label is present or not.
- */
- static final int SECONDARY_LABEL_PRESENT = 1 << 2;
-
- /**
- * Bit position in a byte on {@link #FLAG_INDEX} index in metadata byte array to check whether
- * the additional content is present or not.
- */
- static final int CONTENT_PRESENT = 1 << 3;
-
- @RestrictTo(Scope.LIBRARY)
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(
- flag = true,
- value = {
- EDGE_CONTENT_PRESENT,
- PRIMARY_LABEL_PRESENT,
- SECONDARY_LABEL_PRESENT,
- CONTENT_PRESENT
- })
- @interface ContentBits {}
-
- // Top level impl element.
- @NonNull private final Box mImpl;
-
- EdgeContentLayout2(@NonNull Box layoutElement) {
- this.mImpl = layoutElement;
- }
-
- /** Builder class for {@link EdgeContentLayout2}. */
- public static final class Builder implements LayoutElement.Builder {
- @NonNull private final DeviceParameters mDeviceParameters;
- @Nullable private LayoutElement mEdgeContent = null;
- @Nullable private LayoutElement mPrimaryLabel = null;
- @Nullable private LayoutElement mSecondaryLabel = null;
- @Nullable private LayoutElement mContent = null;
-
- @NonNull
- private DpProp mVerticalSpacerHeight =
- EDGE_CONTENT_LAYOUT2_CONTENT_AND_SECONDARY_LABEL_SPACING_DP;
-
- private byte mMetadataContentByte = 0;
- @Nullable private Float mEdgeContentThickness = null;
-
- /**
- * Creates a builder for the {@link EdgeContentLayout2}. Custom content inside of it can
- * later be set with {@link #setEdgeContent}, {@link #setContent},
- * {@link #setPrimaryLabelContent} and {@link #setSecondaryLabelContent}.
- */
- public Builder(@NonNull DeviceParameters deviceParameters) {
- this.mDeviceParameters = deviceParameters;
- }
-
- /**
- * Sets the content to be around the edges. This can be {@link CircularProgressIndicator},
- * custom {@link androidx.wear.protolayout.LayoutElementBuilders.Arc}, image or other
- * element.
- *
- * <p>If this content is something other that {@link CircularProgressIndicator}, please add
- * its thickness with {@link #setEdgeContentThickness} for best results.
- */
- @NonNull
- public Builder setEdgeContent(@NonNull LayoutElement edgeContent) {
- this.mEdgeContent = edgeContent;
- mMetadataContentByte = (byte) (mMetadataContentByte | EDGE_CONTENT_PRESENT);
- return this;
- }
-
- /**
- * Sets the thickness of the hollow edge content so that other content is correctly placed.
- * In other words, sets the space that should be reserved exclusively for the edge
- * content and not be overdrawn by other inner content.
- *
- * <p>For example, for {@link CircularProgressIndicator} or {@link
- * androidx.wear.protolayout.LayoutElementBuilders.ArcLine} elements, this should be equal
- * to their stroke width/thickness.
- */
- @NonNull
- public Builder setEdgeContentThickness(@Dimension(unit = DP) float thickness) {
- this.mEdgeContentThickness = thickness;
- return this;
- }
-
- /**
- * Sets the content in the primary label slot which will be above the additional content,
- * on a fixed place to ensure Tiles consistency with other layouts.
- *
- * <p>The label will also have an inset to prevent it from going off the screen.
- */
- @NonNull
- public Builder setPrimaryLabelContent(@NonNull LayoutElement primaryLabel) {
- this.mPrimaryLabel = primaryLabel;
- mMetadataContentByte = (byte) (mMetadataContentByte | PRIMARY_LABEL_PRESENT);
- return this;
- }
-
- /**
- * Sets the content in the secondary label slot which will be below the additional content.
- * It is highly recommended to have primary label set when having secondary label.
- *
- * <p>The label will also have an inset to prevent it from going off the screen.
- */
- @NonNull
- public Builder setSecondaryLabelContent(@NonNull LayoutElement secondaryLabel) {
- this.mSecondaryLabel = secondaryLabel;
- mMetadataContentByte = (byte) (mMetadataContentByte | SECONDARY_LABEL_PRESENT);
- return this;
- }
-
- /**
- * Sets the additional content to center of this layout, inside of the edge content and
- * between labels if present.
- */
- @NonNull
- public Builder setContent(@NonNull LayoutElement content) {
- this.mContent = content;
- mMetadataContentByte = (byte) (mMetadataContentByte | CONTENT_PRESENT);
- return this;
- }
-
- /**
- * Sets the size of space between an additional content and secondary label if there is
- * any. If one of those is not present, spacer is not used. If not set,
- * {@link LayoutDefaults#EDGE_CONTENT_LAYOUT2_CONTENT_AND_SECONDARY_LABEL_SPACING_DP} will be
- * used.
- */
- @NonNull
- public Builder setContentAndSecondaryLabelSpacing(@NonNull DpProp height) {
- this.mVerticalSpacerHeight = height;
- return this;
- }
-
- /** Constructs and returns {@link EdgeContentLayout2} with the provided content and look. */
- @SuppressLint("CheckResult") // (b/247804720)
- @NonNull
- @Override
- public EdgeContentLayout2 build() {
- // Calculate what is the inset box max size, i.e., the size that all content can occupy
- // without the edge content.
- // Use provided thickness if set. Otherwise, see if we can get it from
- // CircularProgressIndicator.
- float edgeContentThickness =
- mEdgeContentThickness == null
- ?
- // When not set, we try to get the thickness from CPI, otherwise we can
- // only use 0.
- (mEdgeContent instanceof CircularProgressIndicator
- ? ((CircularProgressIndicator) mEdgeContent)
- .getStrokeWidth().getValue()
- : 0)
- : mEdgeContentThickness;
- float edgeContentSize = 2
- * (EDGE_CONTENT_LAYOUT2_OUTER_MARGIN_DP + edgeContentThickness);
-
- DpProp contentHeight = dp(
- mDeviceParameters.getScreenWidthDp() - edgeContentSize);
- DpProp contentWidth = dp(
- mDeviceParameters.getScreenHeightDp() - edgeContentSize);
-
- // TODO(b/321681652): Confirm with the UX if we can put 6dp as outer margin so it
- // matches CPI.
- float outerMargin =
- mEdgeContent instanceof CircularProgressIndicator
- ? EDGE_CONTENT_LAYOUT2_OUTER_MARGIN_DP - DEFAULT_PADDING.getValue()
- : EDGE_CONTENT_LAYOUT2_OUTER_MARGIN_DP;
-
- // Horizontal and vertical padding added to the inner content.
- float horizontalPaddingDp =
- EDGE_CONTENT_LAYOUT2_MARGIN_HORIZONTAL_PERCENT
- * mDeviceParameters.getScreenWidthDp();
- float verticalPaddingDp =
- EDGE_CONTENT_LAYOUT2_MARGIN_VERTICAL_PERCENT
- * mDeviceParameters.getScreenWidthDp();
-
- // Padding to restrict labels from going off the screen.
- float labelHorizontalPaddingDp =
- mDeviceParameters.getScreenWidthDp() * LAYOUTS_LABEL_PADDING_PERCENT;
-
- Modifiers modifiers =
- new Modifiers.Builder()
- .setPadding(
- new Padding.Builder()
- .setRtlAware(true)
- .setStart(dp(horizontalPaddingDp))
- .setEnd(dp(horizontalPaddingDp))
- .setTop(dp(verticalPaddingDp))
- .setBottom(dp(verticalPaddingDp))
- .build())
- .build();
-
- byte[] metadata = METADATA_TAG_BASE.clone();
- metadata[FLAG_INDEX] = mMetadataContentByte;
-
- Box.Builder layout =
- new Box.Builder()
- .setWidth(dp(mDeviceParameters.getScreenWidthDp()))
- .setHeight(dp(mDeviceParameters.getScreenHeightDp()))
- .setModifiers(
- new Modifiers.Builder()
- .setMetadata(
- new ElementMetadata.Builder()
- .setTagData(metadata).build())
- .setPadding(
- new Padding.Builder()
- .setAll(dp(outerMargin))
- .setRtlAware(true).build())
- .build());
-
- if (mEdgeContent != null) {
- layout.addContent(mEdgeContent);
- }
-
- // Contains primary label, additional content and secondary label.
- Column.Builder allInnerContent =
- new Column.Builder()
- .setWidth(contentWidth)
- .setHeight(contentHeight)
- .setModifiers(modifiers);
-
- if (mPrimaryLabel != null) {
- allInnerContent.addContent(
- insetElementWithPadding(mPrimaryLabel, labelHorizontalPaddingDp));
- // TODO(b/321681652): Confirm with the UX that we don't need a space after this
- // abel.
- }
-
- // Contains additional content and secondary label with wrapped height so it can be put
- // inside of the Box to be centered. This is because primary label stays on top at
- // the fixed place, while this content should be centered in the remaining space.
- Column.Builder contentSecondaryLabel =
- new Column.Builder().setWidth(expand()).setHeight(wrap());
-
- if (mContent != null) {
- contentSecondaryLabel.addContent(mContent);
- }
-
- if (mSecondaryLabel != null) {
- if (mContent != null) {
- contentSecondaryLabel.addContent(
- new Spacer.Builder().setHeight(mVerticalSpacerHeight).build());
- }
- contentSecondaryLabel.addContent(
- insetElementWithPadding(mSecondaryLabel, labelHorizontalPaddingDp));
- }
-
- allInnerContent.addContent(
- new Box.Builder()
- .setWidth(expand())
- .setHeight(expand())
- .addContent(contentSecondaryLabel.build())
- .build());
-
- layout.addContent(allInnerContent.build());
-
- return new EdgeContentLayout2(layout.build());
- }
- }
-
- private boolean areElementsPresent(@ContentBits int elementFlag) {
- return (getMetadataTag()[FLAG_INDEX] & elementFlag) == elementFlag;
- }
-
- /** Returns Column that may contain primary label, additional content and secondary label. */
- private Column getAllContent() {
- return (Column) mImpl.getContents().get(areElementsPresent(EDGE_CONTENT_PRESENT) ? 1 : 0);
- }
-
- /**
- * Returns all content inside of the inner Column that may contain additional content, spacer
- * and secondary label.
- */
- private List<LayoutElement> getInnerColumnContents() {
- return ((Column)
- ((Box)
- getAllContent()
- .getContents()
- .get(areElementsPresent(PRIMARY_LABEL_PRESENT) ? 1 : 0))
- .getContents()
- .get(0))
- .getContents();
- }
-
- /** Returns metadata tag set to this EdgeContentLayout. */
- @NonNull
- byte[] getMetadataTag() {
- return getMetadataTagBytes(checkNotNull(checkNotNull(mImpl.getModifiers()).getMetadata()));
- }
-
- /** Returns the inner content from this layout. */
- @Nullable
- public LayoutElement getContent() {
- return areElementsPresent(CONTENT_PRESENT) ? getInnerColumnContents().get(0) : null;
- }
-
- /** Get the primary label content from this layout. */
- @Nullable
- public LayoutElement getPrimaryLabelContent() {
- return areElementsPresent(PRIMARY_LABEL_PRESENT)
- ? ((Box) getAllContent().getContents().get(0)).getContents().get(0)
- : null;
- }
-
- /** Get the secondary label content from this layout. */
- @Nullable
- public LayoutElement getSecondaryLabelContent() {
- List<LayoutElement> innerColumnContents = getInnerColumnContents();
- return areElementsPresent(SECONDARY_LABEL_PRESENT)
- ? ((Box) innerColumnContents.get(innerColumnContents.size() - 1))
- .getContents().get(0)
- : null;
- }
-
- /** Get the size of spacing between content and secondary from this layout. */
- @Dimension(unit = Dimension.DP)
- public float getContentAndSecondaryLabelSpacing() {
- List<LayoutElement> innerColumnContents = getInnerColumnContents();
- if (areElementsPresent(CONTENT_PRESENT) && areElementsPresent(SECONDARY_LABEL_PRESENT)) {
- LayoutElement element =
- ((Box) innerColumnContents.get(innerColumnContents.size() - 2))
- .getContents().get(0);
- if (element instanceof Spacer) {
- SpacerDimension height = ((Spacer) element).getHeight();
- if (height instanceof DpProp) {
- return ((DpProp) height).getValue();
- }
- }
- }
- return EDGE_CONTENT_LAYOUT2_CONTENT_AND_SECONDARY_LABEL_SPACING_DP.getValue();
- }
-
- /** Returns the edge content from this layout. */
- @Nullable
- public LayoutElement getEdgeContent() {
- return areElementsPresent(EDGE_CONTENT_PRESENT) ? mImpl.getContents().get(0) : null;
- }
-
- /** Returns the total size of the edge content including margins. */
- public float getEdgeContentThickness() {
- Column allContent = getAllContent();
- if (mImpl.getWidth() instanceof DpProp && allContent.getWidth() instanceof DpProp) {
- float edgeContentTotalThickness =
- ((DpProp) mImpl.getWidth()).getValue()
- - ((DpProp) allContent.getWidth()).getValue();
- return edgeContentTotalThickness / 2 - EDGE_CONTENT_LAYOUT2_OUTER_MARGIN_DP;
- }
- return 0;
- }
-
- /**
- * Returns EdgeContentLayout object from the given LayoutElement (e.g. one retrieved from a
- * container's content with {@code container.getContents().get(index)}) if that element can be
- * converted to EdgeContentLayout. Otherwise, it will return null.
- */
- @Nullable
- public static EdgeContentLayout2 fromLayoutElement(@NonNull LayoutElement element) {
- if (element instanceof EdgeContentLayout2) {
- return (EdgeContentLayout2) element;
- }
- if (!(element instanceof Box)) {
- return null;
- }
- Box boxElement = (Box) element;
- if (!checkTag(boxElement.getModifiers(), METADATA_TAG_PREFIX, METADATA_TAG_BASE)) {
- return null;
- }
- // Now we are sure that this element is a EdgeContentLayout.
- return new EdgeContentLayout2(boxElement);
- }
-
- @NonNull
- @Override
- @RestrictTo(Scope.LIBRARY_GROUP)
- public LayoutElementProto.LayoutElement toLayoutElementProto() {
- return mImpl.toLayoutElementProto();
- }
-
- @Nullable
- @Override
- public Fingerprint getFingerprint() {
- return mImpl.getFingerprint();
- }
-}
diff --git a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/layouts/LayoutDefaults.java b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/layouts/LayoutDefaults.java
index 4e55955..8702307 100644
--- a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/layouts/LayoutDefaults.java
+++ b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/layouts/LayoutDefaults.java
@@ -111,36 +111,36 @@
/**
* The default percentage of the screen width for the horizontal margin in the {@link
- * EdgeContentLayout2}.
+ * EdgeContentLayout} with responsiveness.
*/
- static final float EDGE_CONTENT_LAYOUT2_MARGIN_HORIZONTAL_PERCENT = 6.3f / 100;
+ static final float EDGE_CONTENT_LAYOUT_RESPONSIVE_MARGIN_HORIZONTAL_PERCENT = 6.3f / 100;
/**
* The default percentage of the screen height for the vertical margin in the {@link
- * EdgeContentLayout2}.
+ * EdgeContentLayout} with responsiveness.
*/
- static final float EDGE_CONTENT_LAYOUT2_MARGIN_VERTICAL_PERCENT = 12f / 100;
+ static final float EDGE_CONTENT_LAYOUT_RESPONSIVE_MARGIN_VERTICAL_PERCENT = 12f / 100;
- /** The margins used in the {@link EdgeContentLayout2}. */
+ /** The margins used in the {@link EdgeContentLayout} with responsiveness. */
@Dimension(unit = DP)
- static final int EDGE_CONTENT_LAYOUT2_OUTER_MARGIN_DP = 8;
+ static final int EDGE_CONTENT_LAYOUT_RESPONSIVE_OUTER_MARGIN_DP = 8;
/**
* The default spacer width that should be between main content and secondary label if set in
- * the {@link EdgeContentLayout2}.
+ * the {@link EdgeContentLayout}.
*
* <p>It is recommended to use this on smaller screen sizes or when there's a lot of content in
* the layout.
*/
- public static final DpProp EDGE_CONTENT_LAYOUT2_CONTENT_AND_SECONDARY_LABEL_SPACING_DP = dp(8);
+ public static final DpProp EDGE_CONTENT_LAYOUT_CONTENT_AND_SECONDARY_LABEL_SPACING_DP = dp(8);
/**
* The default spacer width that should be between main content and secondary label if set in
- * the {@link EdgeContentLayout2}.
+ * the {@link EdgeContentLayout}.
*
* <p>It is recommended to use this on larger screen sizes (screen sizes above 225dp).
*/
- public static final DpProp EDGE_CONTENT_LAYOUT2_LARGE_CONTENT_AND_SECONDARY_LABEL_SPACING_DP =
+ public static final DpProp EDGE_CONTENT_LAYOUT_LARGE_CONTENT_AND_SECONDARY_LABEL_SPACING_DP =
dp(12);
/**
diff --git a/wear/protolayout/protolayout-material/src/test/java/androidx/wear/protolayout/material/layouts/EdgeContentLayout2Test.java b/wear/protolayout/protolayout-material/src/test/java/androidx/wear/protolayout/material/layouts/EdgeContentLayout2Test.java
deleted file mode 100644
index 00c107b..0000000
--- a/wear/protolayout/protolayout-material/src/test/java/androidx/wear/protolayout/material/layouts/EdgeContentLayout2Test.java
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * Copyright 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.wear.protolayout.material.layouts;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static java.nio.charset.StandardCharsets.UTF_8;
-
-import android.content.Context;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.test.core.app.ApplicationProvider;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters;
-import androidx.wear.protolayout.LayoutElementBuilders.Box;
-import androidx.wear.protolayout.LayoutElementBuilders.Column;
-import androidx.wear.protolayout.LayoutElementBuilders.LayoutElement;
-import androidx.wear.protolayout.ModifiersBuilders.ElementMetadata;
-import androidx.wear.protolayout.ModifiersBuilders.Modifiers;
-import androidx.wear.protolayout.material.CircularProgressIndicator;
-import androidx.wear.protolayout.material.Text;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.annotation.internal.DoNotInstrument;
-
-@RunWith(AndroidJUnit4.class)
-@DoNotInstrument
-public class EdgeContentLayout2Test {
- private static final Context CONTEXT = ApplicationProvider.getApplicationContext();
- private static final DeviceParameters DEVICE_PARAMETERS =
- new DeviceParameters.Builder().setScreenWidthDp(192).setScreenHeightDp(192).build();
- private static final Text PRIMARY_LABEL =
- new Text.Builder(CONTEXT, "Primary label").build();
- private static final Text SECONDARY_LABEL =
- new Text.Builder(CONTEXT, "Secondary label").build();
-
- @Test
- public void testAll() {
- LayoutElement content = new Box.Builder().build();
- CircularProgressIndicator progressIndicator =
- new CircularProgressIndicator.Builder().build();
- int edgeContentThickness = 20;
- EdgeContentLayout2 layout =
- new EdgeContentLayout2.Builder(DEVICE_PARAMETERS)
- .setContent(content)
- .setEdgeContent(progressIndicator)
- .setPrimaryLabelContent(PRIMARY_LABEL)
- .setSecondaryLabelContent(SECONDARY_LABEL)
- .setEdgeContentThickness(edgeContentThickness)
- .build();
-
- assertLayout(
- layout,
- progressIndicator,
- content,
- PRIMARY_LABEL,
- SECONDARY_LABEL,
- edgeContentThickness);
- }
-
- @Test
- public void testAll_defaultThickness() {
- LayoutElement content = new Box.Builder().build();
- CircularProgressIndicator progressIndicator =
- new CircularProgressIndicator.Builder().build();
- EdgeContentLayout2 layout =
- new EdgeContentLayout2.Builder(DEVICE_PARAMETERS)
- .setContent(content)
- .setEdgeContent(progressIndicator)
- .setPrimaryLabelContent(PRIMARY_LABEL)
- .setSecondaryLabelContent(SECONDARY_LABEL)
- .build();
-
- assertLayout(
- layout,
- progressIndicator,
- content,
- PRIMARY_LABEL,
- SECONDARY_LABEL,
- progressIndicator.getStrokeWidth().getValue());
- }
-
- @Test
- public void testContentOnly() {
- LayoutElement content = new Box.Builder().build();
- EdgeContentLayout2 layout =
- new EdgeContentLayout2.Builder(DEVICE_PARAMETERS).setContent(content).build();
-
- assertLayout(
- layout,
- /* expectedProgressIndicator= */ null,
- content,
- /* expectedPrimaryLabel= */ null,
- /* expectedSecondaryLabel= */ null,
- /* expectedEdgeContentThickness= */ 0);
- }
-
- @Test
- public void testIndicatorOnly() {
- CircularProgressIndicator progressIndicator =
- new CircularProgressIndicator.Builder().build();
- EdgeContentLayout2 layout =
- new EdgeContentLayout2.Builder(DEVICE_PARAMETERS)
- .setEdgeContent(progressIndicator).build();
-
- assertLayout(
- layout,
- progressIndicator,
- /* expectedContent= */ null,
- /* expectedPrimaryLabel= */ null,
- /* expectedSecondaryLabel= */ null,
- progressIndicator.getStrokeWidth().getValue());
- }
-
- @Test
- public void testEmpty() {
- EdgeContentLayout2 layout = new EdgeContentLayout2.Builder(DEVICE_PARAMETERS).build();
-
- assertLayout(
- layout,
- /* expectedProgressIndicator= */ null,
- /* expectedContent= */ null,
- /* expectedPrimaryLabel= */ null,
- /* expectedSecondaryLabel= */ null,
- /* expectedEdgeContentThickness= */ 0);
- }
-
- @Test
- public void testWrongElement() {
- Column box = new Column.Builder().build();
-
- assertThat(EdgeContentLayout2.fromLayoutElement(box)).isNull();
- }
-
- @Test
- public void testWrongBox() {
- Box box = new Box.Builder().build();
-
- assertThat(EdgeContentLayout2.fromLayoutElement(box)).isNull();
- }
-
- @Test
- public void testWrongTag() {
- Box box =
- new Box.Builder()
- .setModifiers(
- new Modifiers.Builder()
- .setMetadata(
- new ElementMetadata.Builder()
- .setTagData("test".getBytes(UTF_8)).build())
- .build())
- .build();
-
- assertThat(EdgeContentLayout2.fromLayoutElement(box)).isNull();
- }
-
- @Test
- public void testWrongLengthTag() {
- Box box =
- new Box.Builder()
- .setModifiers(
- new Modifiers.Builder()
- .setMetadata(
- new ElementMetadata.Builder()
- .setTagData(
- EdgeContentLayout2
- .METADATA_TAG_PREFIX
- .getBytes(UTF_8))
- .build())
- .build())
- .build();
-
- assertThat(EdgeContentLayout2.fromLayoutElement(box)).isNull();
- }
-
- private void assertLayout(
- @NonNull EdgeContentLayout2 actualLayout,
- @Nullable LayoutElement expectedProgressIndicator,
- @Nullable LayoutElement expectedContent,
- @Nullable LayoutElement expectedPrimaryLabel,
- @Nullable LayoutElement expectedSecondaryLabel,
- float expectedEdgeContentThickness) {
- assertLayoutIsEqual(
- actualLayout,
- expectedProgressIndicator,
- expectedContent,
- expectedPrimaryLabel,
- expectedSecondaryLabel,
- expectedEdgeContentThickness);
-
- Box box = new Box.Builder().addContent(actualLayout).build();
-
- EdgeContentLayout2 newLayout = EdgeContentLayout2
- .fromLayoutElement(box.getContents().get(0));
-
- assertThat(newLayout).isNotNull();
- assertLayoutIsEqual(
- newLayout,
- expectedProgressIndicator,
- expectedContent,
- expectedPrimaryLabel,
- expectedSecondaryLabel,
- expectedEdgeContentThickness);
-
- assertThat(EdgeContentLayout2.fromLayoutElement(actualLayout)).isEqualTo(actualLayout);
- }
-
- private void assertLayoutIsEqual(
- @NonNull EdgeContentLayout2 actualLayout,
- @Nullable LayoutElement expectedProgressIndicator,
- @Nullable LayoutElement expectedContent,
- @Nullable LayoutElement expectedPrimaryLabel,
- @Nullable LayoutElement expectedSecondaryLabel,
- float expectedEdgeContentThickness) {
- byte[] expectedMetadata = EdgeContentLayout2.METADATA_TAG_BASE.clone();
-
- if (expectedProgressIndicator == null) {
- assertThat(actualLayout.getEdgeContent()).isNull();
- } else {
- assertThat(actualLayout.getEdgeContent().toLayoutElementProto())
- .isEqualTo(expectedProgressIndicator.toLayoutElementProto());
- expectedMetadata[EdgeContentLayout2.FLAG_INDEX] =
- (byte)
- (expectedMetadata[EdgeContentLayout2.FLAG_INDEX]
- | EdgeContentLayout2.EDGE_CONTENT_PRESENT);
- }
-
- if (expectedContent == null) {
- assertThat(actualLayout.getContent()).isNull();
- } else {
- assertThat(actualLayout.getContent().toLayoutElementProto())
- .isEqualTo(expectedContent.toLayoutElementProto());
- expectedMetadata[EdgeContentLayout2.FLAG_INDEX] =
- (byte)
- (expectedMetadata[EdgeContentLayout2.FLAG_INDEX]
- | EdgeContentLayout2.CONTENT_PRESENT);
- }
-
- if (expectedPrimaryLabel == null) {
- assertThat(actualLayout.getPrimaryLabelContent()).isNull();
- } else {
- assertThat(actualLayout.getPrimaryLabelContent().toLayoutElementProto())
- .isEqualTo(expectedPrimaryLabel.toLayoutElementProto());
- expectedMetadata[EdgeContentLayout2.FLAG_INDEX] =
- (byte)
- (expectedMetadata[EdgeContentLayout2.FLAG_INDEX]
- | EdgeContentLayout2.PRIMARY_LABEL_PRESENT);
- }
-
- if (expectedSecondaryLabel == null) {
- assertThat(actualLayout.getSecondaryLabelContent()).isNull();
- } else {
- assertThat(actualLayout.getSecondaryLabelContent().toLayoutElementProto())
- .isEqualTo(expectedSecondaryLabel.toLayoutElementProto());
- expectedMetadata[EdgeContentLayout2.FLAG_INDEX] =
- (byte)
- (expectedMetadata[EdgeContentLayout2.FLAG_INDEX]
- | EdgeContentLayout2.SECONDARY_LABEL_PRESENT);
- }
-
- assertThat(actualLayout.getEdgeContentThickness()).isEqualTo(expectedEdgeContentThickness);
-
- assertThat(actualLayout.getMetadataTag()).isEqualTo(expectedMetadata);
- }
-}
diff --git a/wear/protolayout/protolayout-material/src/test/java/androidx/wear/protolayout/material/layouts/EdgeContentLayoutTest.java b/wear/protolayout/protolayout-material/src/test/java/androidx/wear/protolayout/material/layouts/EdgeContentLayoutTest.java
index b74fc9d..3c9bf44 100644
--- a/wear/protolayout/protolayout-material/src/test/java/androidx/wear/protolayout/material/layouts/EdgeContentLayoutTest.java
+++ b/wear/protolayout/protolayout-material/src/test/java/androidx/wear/protolayout/material/layouts/EdgeContentLayoutTest.java
@@ -18,6 +18,8 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertThrows;
+
import static java.nio.charset.StandardCharsets.UTF_8;
import android.content.Context;
@@ -64,6 +66,8 @@
.build();
assertLayout(layout, progressIndicator, content, PRIMARY_LABEL, SECONDARY_LABEL);
+ assertThat(layout.isEdgeContentBehindAllOtherContent()).isFalse();
+ assertThat(layout.isResponsiveContentInsetEnabled()).isFalse();
}
@Test
@@ -82,6 +86,7 @@
assertLayout(layout, progressIndicator, content, PRIMARY_LABEL, SECONDARY_LABEL);
assertThat(layout.isEdgeContentBehindAllOtherContent()).isTrue();
+ assertThat(layout.isResponsiveContentInsetEnabled()).isFalse();
}
@Test
@@ -91,6 +96,8 @@
new EdgeContentLayout.Builder(DEVICE_PARAMETERS).setContent(content).build();
assertLayout(layout, null, content, null, null);
+ assertThat(layout.isEdgeContentBehindAllOtherContent()).isFalse();
+ assertThat(layout.isResponsiveContentInsetEnabled()).isFalse();
}
@Test
@@ -103,6 +110,8 @@
.build();
assertLayout(layout, progressIndicator, null, null, null);
+ assertThat(layout.isEdgeContentBehindAllOtherContent()).isFalse();
+ assertThat(layout.isResponsiveContentInsetEnabled()).isFalse();
}
@Test
@@ -110,6 +119,129 @@
EdgeContentLayout layout = new EdgeContentLayout.Builder(DEVICE_PARAMETERS).build();
assertLayout(layout, null, null, null, null);
+ assertThat(layout.isEdgeContentBehindAllOtherContent()).isFalse();
+ assertThat(layout.isResponsiveContentInsetEnabled()).isFalse();
+ }
+
+ // Responsive test cases with behaviour with using setResponsiveContentInsetEnabled. They are
+ // repeated because the organization of elements inside of the layout is different then without
+ // this setter.
+
+ @Test
+ public void testAll_responsive() {
+ LayoutElement content = new Box.Builder().build();
+ CircularProgressIndicator progressIndicator =
+ new CircularProgressIndicator.Builder().build();
+ int edgeContentThickness = 20;
+ EdgeContentLayout layout =
+ new EdgeContentLayout.Builder(DEVICE_PARAMETERS)
+ .setResponsiveContentInsetEnabled(true)
+ .setContent(content)
+ .setEdgeContent(progressIndicator)
+ .setPrimaryLabelTextContent(PRIMARY_LABEL)
+ .setSecondaryLabelTextContent(SECONDARY_LABEL)
+ .setEdgeContentThickness(edgeContentThickness)
+ .build();
+
+ assertLayout(
+ layout,
+ progressIndicator,
+ content,
+ PRIMARY_LABEL,
+ SECONDARY_LABEL);
+
+ assertThat(layout.getEdgeContentThickness()).isEqualTo(edgeContentThickness);
+ assertThat(layout.isEdgeContentBehindAllOtherContent()).isTrue();
+ assertThat(layout.isResponsiveContentInsetEnabled()).isTrue();
+ }
+
+ @Test
+ public void testAll_defaultThickness_responsive() {
+ LayoutElement content = new Box.Builder().build();
+ CircularProgressIndicator progressIndicator =
+ new CircularProgressIndicator.Builder().build();
+ EdgeContentLayout layout =
+ new EdgeContentLayout.Builder(DEVICE_PARAMETERS)
+ .setResponsiveContentInsetEnabled(true)
+ .setContent(content)
+ .setEdgeContent(progressIndicator)
+ .setPrimaryLabelTextContent(PRIMARY_LABEL)
+ .setSecondaryLabelTextContent(SECONDARY_LABEL)
+ .build();
+
+ assertLayout(
+ layout,
+ progressIndicator,
+ content,
+ PRIMARY_LABEL,
+ SECONDARY_LABEL);
+
+ assertThat(layout.getEdgeContentThickness())
+ .isEqualTo(progressIndicator.getStrokeWidth().getValue());
+ assertThat(layout.isEdgeContentBehindAllOtherContent()).isTrue();
+ assertThat(layout.isResponsiveContentInsetEnabled()).isTrue();
+ }
+
+ @Test
+ public void testContentOnly_responsive() {
+ LayoutElement content = new Box.Builder().build();
+ EdgeContentLayout layout =
+ new EdgeContentLayout.Builder(DEVICE_PARAMETERS)
+ .setResponsiveContentInsetEnabled(true)
+ .setContent(content)
+ .build();
+
+ assertLayout(
+ layout,
+ /* expectedProgressIndicator= */ null,
+ content,
+ /* expectedPrimaryLabel= */ null,
+ /* expectedSecondaryLabel= */ null);
+
+ assertThat(layout.getEdgeContentThickness()).isEqualTo(0);
+ assertThat(layout.isEdgeContentBehindAllOtherContent()).isTrue();
+ assertThat(layout.isResponsiveContentInsetEnabled()).isTrue();
+ }
+
+ @Test
+ public void testIndicatorOnly_responsive() {
+ CircularProgressIndicator progressIndicator =
+ new CircularProgressIndicator.Builder().build();
+ EdgeContentLayout layout =
+ new EdgeContentLayout.Builder(DEVICE_PARAMETERS)
+ .setResponsiveContentInsetEnabled(true)
+ .setEdgeContent(progressIndicator)
+ .build();
+
+ assertLayout(
+ layout,
+ progressIndicator,
+ /* expectedContent= */ null,
+ /* expectedPrimaryLabel= */ null,
+ /* expectedSecondaryLabel= */ null);
+
+ assertThat(layout.getEdgeContentThickness())
+ .isEqualTo(progressIndicator.getStrokeWidth().getValue());
+ assertThat(layout.isEdgeContentBehindAllOtherContent()).isTrue();
+ assertThat(layout.isResponsiveContentInsetEnabled()).isTrue();
+ }
+
+ @Test
+ public void testEmpty_responsive() {
+ EdgeContentLayout layout = new EdgeContentLayout.Builder(DEVICE_PARAMETERS)
+ .setResponsiveContentInsetEnabled(true)
+ .build();
+
+ assertLayout(
+ layout,
+ /* expectedProgressIndicator= */ null,
+ /* expectedContent= */ null,
+ /* expectedPrimaryLabel= */ null,
+ /* expectedSecondaryLabel= */ null);
+
+ assertThat(layout.getEdgeContentThickness()).isEqualTo(0);
+ assertThat(layout.isEdgeContentBehindAllOtherContent()).isTrue();
+ assertThat(layout.isResponsiveContentInsetEnabled()).isTrue();
}
@Test
@@ -161,6 +293,28 @@
assertThat(EdgeContentLayout.fromLayoutElement(box)).isNull();
}
+ @Test
+ public void testResponsiveAndBehindContentSettersMixed() {
+ EdgeContentLayout.Builder builder =
+ new EdgeContentLayout.Builder(DEVICE_PARAMETERS)
+ .setResponsiveContentInsetEnabled(true);
+
+ assertThrows(
+ IllegalStateException.class,
+ () -> builder.setEdgeContentBehindAllOtherContent(true));
+ }
+
+ @Test
+ public void testBehindContentAndResponsiveSettersMixed() {
+ EdgeContentLayout.Builder builder =
+ new EdgeContentLayout.Builder(DEVICE_PARAMETERS)
+ .setEdgeContentBehindAllOtherContent(true);
+
+ assertThrows(
+ IllegalStateException.class,
+ () -> builder.setResponsiveContentInsetEnabled(true));
+ }
+
private void assertLayout(
@NonNull EdgeContentLayout actualLayout,
@Nullable LayoutElement expectedProgressIndicator,
@@ -243,17 +397,21 @@
// Reset bit for edge content position. If that bit is wrong, the above checks around
// content will fail, so we don't need to specifically check it here.
- resetEdgeContentPositionFlag(expectedMetadata);
+ resetEdgeContentPositionAndResponsiveFlag(expectedMetadata);
byte[] actualMetadata = actualLayout.getMetadataTag();
- resetEdgeContentPositionFlag(actualMetadata);
+ resetEdgeContentPositionAndResponsiveFlag(actualMetadata);
assertThat(actualMetadata).isEqualTo(expectedMetadata);
}
- private static void resetEdgeContentPositionFlag(byte[] expectedMetadata) {
+ private static void resetEdgeContentPositionAndResponsiveFlag(byte[] expectedMetadata) {
expectedMetadata[EdgeContentLayout.FLAG_INDEX] =
(byte)
(expectedMetadata[EdgeContentLayout.FLAG_INDEX]
& ~EdgeContentLayout.EDGE_CONTENT_POSITION);
+ expectedMetadata[EdgeContentLayout.FLAG_INDEX] =
+ (byte)
+ (expectedMetadata[EdgeContentLayout.FLAG_INDEX]
+ & ~EdgeContentLayout.CONTENT_INSET_USED);
}
}