From 9e10b29231a261842d9fb7f6604bd37dc0524ed7 Mon Sep 17 00:00:00 2001 From: Shane Date: Thu, 6 Apr 2023 08:26:15 -0700 Subject: [PATCH] Row & Column feature parity experiment --- .../compose/ConstraintLayoutBaseScope.kt | 24 ++ .../core/state/ConstraintSetParser.java | 12 + .../core/state/helpers/GridReference.java | 29 ++ .../constraintlayout/core/utils/GridCore.java | 87 +++- .../example/constraintlayout/ComposeColumn.kt | 351 +++++++++++++++ .../example/constraintlayout/ComposeRow.kt | 399 ++++++++++++++++++ .../constraintlayout/RowColumnExpeirment.kt | 348 +++++++++++++++ projects/GridExperiments/core/build.gradle | 1 + 8 files changed, 1248 insertions(+), 3 deletions(-) create mode 100644 projects/ComposeConstraintLayout/app/src/main/java/com/example/constraintlayout/ComposeColumn.kt create mode 100644 projects/ComposeConstraintLayout/app/src/main/java/com/example/constraintlayout/ComposeRow.kt create mode 100644 projects/ComposeConstraintLayout/app/src/main/java/com/example/constraintlayout/RowColumnExpeirment.kt diff --git a/constraintlayout/compose/src/main/java/androidx/constraintlayout/compose/ConstraintLayoutBaseScope.kt b/constraintlayout/compose/src/main/java/androidx/constraintlayout/compose/ConstraintLayoutBaseScope.kt index 351bad161..16df12afe 100644 --- a/constraintlayout/compose/src/main/java/androidx/constraintlayout/compose/ConstraintLayoutBaseScope.kt +++ b/constraintlayout/compose/src/main/java/androidx/constraintlayout/compose/ConstraintLayoutBaseScope.kt @@ -740,6 +740,7 @@ abstract class ConstraintLayoutBaseScope internal constructor(extendFrom: CLObje horizontalGap: Dp = 0.dp, columnWeights: IntArray = intArrayOf(), padding: Dp = 0.dp, + horizontalChainStyle: ChainStyle = ChainStyle.None, ): ConstrainedLayoutReference { return createGrid( elements = elements, @@ -752,6 +753,7 @@ abstract class ConstraintLayoutBaseScope internal constructor(extendFrom: CLObje paddingTop = padding, paddingRight = padding, paddingBottom = padding, + chainStyle = horizontalChainStyle, ) } @@ -808,6 +810,8 @@ abstract class ConstraintLayoutBaseScope internal constructor(extendFrom: CLObje columnWeights: IntArray = intArrayOf(), paddingHorizontal: Dp = 0.dp, paddingVertical: Dp = 0.dp, + horizontalChainStyle: ChainStyle = ChainStyle.None, + horizontalChainBias: Float = 0.5f, ): ConstrainedLayoutReference { return createGrid( elements = elements, @@ -820,6 +824,8 @@ abstract class ConstraintLayoutBaseScope internal constructor(extendFrom: CLObje paddingTop = paddingVertical, paddingRight = paddingHorizontal, paddingBottom = paddingVertical, + chainStyle = horizontalChainStyle, + chainBias = horizontalChainBias ) } @@ -873,6 +879,8 @@ abstract class ConstraintLayoutBaseScope internal constructor(extendFrom: CLObje rowWeights: IntArray = intArrayOf(), verticalGap: Dp = 0.dp, padding: Dp = 0.dp, + verticalChainStyle: ChainStyle = ChainStyle.None, + verticalChainBias: Float = 0.5f, ): ConstrainedLayoutReference { return createGrid( elements = elements, @@ -885,6 +893,8 @@ abstract class ConstraintLayoutBaseScope internal constructor(extendFrom: CLObje paddingTop = padding, paddingRight = padding, paddingBottom = padding, + chainStyle = verticalChainStyle, + chainBias = verticalChainBias ) } @@ -940,6 +950,8 @@ abstract class ConstraintLayoutBaseScope internal constructor(extendFrom: CLObje rowWeights: IntArray = intArrayOf(), paddingHorizontal: Dp = 0.dp, paddingVertical: Dp = 0.dp, + verticalChainStyle: ChainStyle = ChainStyle.Spread, + verticalChainBias: Float = 0.5f ): ConstrainedLayoutReference { return createGrid( elements = elements, @@ -952,6 +964,8 @@ abstract class ConstraintLayoutBaseScope internal constructor(extendFrom: CLObje paddingTop = paddingVertical, paddingRight = paddingHorizontal, paddingBottom = paddingVertical, + chainStyle = verticalChainStyle, + chainBias = verticalChainBias, ) } @@ -1299,6 +1313,8 @@ abstract class ConstraintLayoutBaseScope internal constructor(extendFrom: CLObje paddingRight: Dp = 0.dp, paddingBottom: Dp = 0.dp, flags: Array = arrayOf(), + chainStyle: ChainStyle = ChainStyle.None, + chainBias: Float = 0.5f ): ConstrainedLayoutReference { val ref = ConstrainedLayoutReference(createHelperId()) val elementArray = CLArray(charArrayOf()) @@ -1338,6 +1354,8 @@ abstract class ConstraintLayoutBaseScope internal constructor(extendFrom: CLObje putString("skips", skips) putString("spans", spans) put("flags", flagArray) + put("chainStyle", CLString.from(chainStyle.name)) + put("chainBias", CLNumber(chainBias)) } return ref @@ -1798,6 +1816,12 @@ class ChainStyle internal constructor( internal val bias: Float? = null ) { companion object { + /** + * Not apply chain style + */ + @Stable + val None = ChainStyle("none") + /** * A chain style that evenly distributes the contained layouts. */ diff --git a/constraintlayout/core/src/main/java/androidx/constraintlayout/core/state/ConstraintSetParser.java b/constraintlayout/core/src/main/java/androidx/constraintlayout/core/state/ConstraintSetParser.java index 52c385002..79e37775f 100644 --- a/constraintlayout/core/src/main/java/androidx/constraintlayout/core/state/ConstraintSetParser.java +++ b/constraintlayout/core/src/main/java/androidx/constraintlayout/core/state/ConstraintSetParser.java @@ -1051,6 +1051,18 @@ private static void parseGridType(String gridType, } } break; + case "chainStyle": + String chainStyle = element.get(param).content(); + if (chainStyle != null && chainStyle.length() > 0) { + grid.setChainStyle(chainStyle); + } + break; + case "chainBias": + float chainBias = element.get(param).getFloat(); + if (chainBias >= 0 && chainBias <= 1) { + grid.setChainBias(chainBias); + } + break; default: ConstraintReference reference = state.constraints(name); applyAttribute(state, layoutVariables, reference, element, param); diff --git a/constraintlayout/core/src/main/java/androidx/constraintlayout/core/state/helpers/GridReference.java b/constraintlayout/core/src/main/java/androidx/constraintlayout/core/state/helpers/GridReference.java index 4d37e9a24..51f7495eb 100644 --- a/constraintlayout/core/src/main/java/androidx/constraintlayout/core/state/helpers/GridReference.java +++ b/constraintlayout/core/src/main/java/androidx/constraintlayout/core/state/helpers/GridReference.java @@ -117,6 +117,27 @@ public GridReference(@NonNull State state, @NonNull State.Helper type) { */ private int[] mFlags; + public String getChainStyle() { + return mChainStyle; + } + + public void setChainStyle(String chainStyle) { + mChainStyle = chainStyle; + } + + private String mChainStyle; + + + public float getChainBias() { + return mChainBias; + } + + public void setChainBias(float chainBias) { + mChainBias = chainBias; + } + + private float mChainBias; + /** * get padding left * @return padding left @@ -454,6 +475,14 @@ public void apply() { mGrid.setFlags(mFlags); } + if (mChainStyle != null) { + mGrid.setChainStyle(mChainStyle); + } + + if (mChainBias >= 0 && mChainBias <= 1) { + mGrid.setChainBias(mChainBias); + } + // General attributes of a widget applyBase(); } diff --git a/constraintlayout/core/src/main/java/androidx/constraintlayout/core/utils/GridCore.java b/constraintlayout/core/src/main/java/androidx/constraintlayout/core/utils/GridCore.java index 4f195c759..bd0d33745 100644 --- a/constraintlayout/core/src/main/java/androidx/constraintlayout/core/utils/GridCore.java +++ b/constraintlayout/core/src/main/java/androidx/constraintlayout/core/utils/GridCore.java @@ -42,6 +42,11 @@ public class GridCore extends VirtualLayout { private static final int MAX_ROWS = 50; // maximum number of rows can be specified. private static final int MAX_COLUMNS = 50; // maximum number of columns can be specified. + // Values of the chain styles + public static final String CHAIN_SPREAD = "spread"; + public static final String CHAIN_SPREAD_INSIDE = "spread_inside"; + public static final String CHAIN_PACKED = "packed"; + /** * Container for all the ConstraintWidgets */ @@ -162,6 +167,27 @@ public class GridCore extends VirtualLayout { */ private boolean mSubGridByColRow = false; + public String getChainStyle() { + return mChainStyle; + } + + public void setChainStyle(String chainStyle) { + mChainStyle = chainStyle; + } + + public float getChainBias() { + return mChainBias; + } + + public void setChainBias(float chainBias) { + mChainBias = chainBias; + } + + private String mChainStyle; + + + private float mChainBias; + public GridCore() { updateActualRowsAndColumns(); initMatrices(); @@ -781,9 +807,64 @@ private void setBoxWidgetVerticalChains() { * Chains the boxWidgets and add constraints to the widgets */ private void addConstraints() { - setBoxWidgetVerticalChains(); - setBoxWidgetHorizontalChains(); - arrangeWidgets(); +// setBoxWidgetVerticalChains(); +// setBoxWidgetHorizontalChains(); +// arrangeWidgets(); + + int style = -1; + if (mChainStyle.equals(CHAIN_SPREAD)) { + style = 0; + } else if (mChainStyle.equals(CHAIN_SPREAD_INSIDE)) { + style = 1; + } else if (mChainStyle.equals(CHAIN_PACKED)) { + style = 2; + } + + if (mRows == 1 && style != -1) { + for (int i = 0; i < mWidgetsCount; i++) { + if (i == 0) { + mWidgets[i].mLeft.connect(mLeft, 0); + mWidgets[i].setHorizontalChainStyle(style); + mWidgets[i].setHorizontalBiasPercent(mChainBias); + } else { + mWidgets[i].mLeft.connect(mWidgets[i - 1].mRight, 0); + } + if (i == mWidgetsCount - 1) { + mWidgets[i].mRight.connect(mRight, 0); + } else { + mWidgets[i].mRight.connect(mWidgets[i + 1].mLeft, 0); + } + + if (mWidgets[i].mTop.mTarget == null && mWidgets[i].mBottom.mTarget == null) { + mWidgets[i].mTop.connect(mTop, 0); + mWidgets[i].mBottom.connect(mBottom, 0); + } + } + } else if (mColumns == 1 && style != -1) { + for (int i = 0; i < mWidgetsCount; i++) { + if (i == 0) { + mWidgets[i].mTop.connect(mTop, 0); + mWidgets[i].setVerticalChainStyle(style); + mWidgets[i].setVerticalBiasPercent(mChainBias); + } else { + mWidgets[i].mTop.connect(mWidgets[i - 1].mBottom, 0); + } + if (i == mWidgetsCount - 1) { + mWidgets[i].mBottom.connect(mBottom, 0); + } else { + mWidgets[i].mBottom.connect(mWidgets[i + 1].mTop, 0); + } + + if (mWidgets[i].mLeft.mTarget == null && mWidgets[i].mRight.mTarget == null) { + mWidgets[i].mLeft.connect(mLeft, 0); + mWidgets[i].mRight.connect(mRight, 0); + } + } + } else { + setBoxWidgetVerticalChains(); + setBoxWidgetHorizontalChains(); + arrangeWidgets(); + } } /** diff --git a/projects/ComposeConstraintLayout/app/src/main/java/com/example/constraintlayout/ComposeColumn.kt b/projects/ComposeConstraintLayout/app/src/main/java/com/example/constraintlayout/ComposeColumn.kt new file mode 100644 index 000000000..8186ec73c --- /dev/null +++ b/projects/ComposeConstraintLayout/app/src/main/java/com/example/constraintlayout/ComposeColumn.kt @@ -0,0 +1,351 @@ +/* + * Copyright (C) 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 com.example.constraintlayout + +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.material.Button +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.layout.layoutId +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.constraintlayout.compose.* + +@Preview(group = "EqualWeight") +@Composable +fun ColumnEqualWeight() { + ConstraintLayout( + ConstraintSet { + val a = createRefFor("1") + val b = createRefFor("2") + val c = createRefFor("3") + val d = createRefFor("4") + + val g1 = createColumn( + a, b, c, d, + verticalChainStyle = ChainStyle.Spread, + verticalChainBias = 1f + ) + constrain(g1) { + width = Dimension.matchParent + height = Dimension.matchParent + start.linkTo(parent.start) + end.linkTo(parent.end) + } + + constrain(a) { + height = Dimension.fillToConstraints + verticalChainWeight = 1f + } + constrain(b) { + height = Dimension.fillToConstraints + verticalChainWeight = 1f + } + constrain(c) { + height = Dimension.fillToConstraints + verticalChainWeight = 1f + } + constrain(d) { + height = Dimension.fillToConstraints + verticalChainWeight = 1f + } + }, + modifier = Modifier.fillMaxSize() + ) { + val numArray = arrayOf("1", "2", "3", "4") + for (num in numArray) { + Button( + modifier = Modifier.layoutId(num).size(50.dp), + onClick = {}, + ) { + Text(text = String.format("%s", num)) + } + } + } +} + +@Preview(group = "SpaceEvenly") +@Composable +fun ColumnSpaceEvenly() { + ConstraintLayout( + ConstraintSet { + val a = createRefFor("1") + val b = createRefFor("2") + val c = createRefFor("3") + val d = createRefFor("4") + + val g1 = createColumn( + a, b, c, d, + verticalChainStyle = ChainStyle.Spread, + ) + constrain(g1) { + width = Dimension.matchParent + height = Dimension.matchParent + start.linkTo(parent.start) + end.linkTo(parent.end) + } + }, + modifier = Modifier.fillMaxSize() + ) { + val numArray = arrayOf("1", "2", "3", "4") + for (num in numArray) { + Button( + modifier = Modifier.layoutId(num).size(50.dp), + onClick = {}, + ) { + Text(text = String.format("%s", num)) + } + } + } +} + +@Preview(group = "SpaceAround") +@Composable +fun ColumnSpaceAround() { + ConstraintLayout( + ConstraintSet { + val a = createRefFor("1") + val b = createRefFor("2") + val c = createRefFor("3") + val d = createRefFor("4") + + val g1 = createColumn( + a, b, c, d, + ) + constrain(g1) { + width = Dimension.matchParent + height = Dimension.matchParent + start.linkTo(parent.start) + end.linkTo(parent.end) + } + }, + modifier = Modifier.fillMaxSize() + ) { + val numArray = arrayOf("1", "2", "3", "4") + for (num in numArray) { + Button( + modifier = Modifier.layoutId(num).size(50.dp), + onClick = {}, + ) { + Text(text = String.format("%s", num)) + } + } + } +} + +@Preview(group = "SpaceBetween") +@Composable +fun ColumnSpaceBetween() { + ConstraintLayout( + ConstraintSet { + val a = createRefFor("1") + val b = createRefFor("2") + val c = createRefFor("3") + val d = createRefFor("4") + + val g1 = createColumn( + a, b, c, d, + verticalChainStyle = ChainStyle.SpreadInside, + ) + constrain(g1) { + width = Dimension.matchParent + height = Dimension.matchParent + start.linkTo(parent.start) + end.linkTo(parent.end) + } + }, + modifier = Modifier.fillMaxSize() + ) { + val numArray = arrayOf("1", "2", "3", "4") + for (num in numArray) { + Button( + modifier = Modifier.layoutId(num).size(50.dp), + onClick = {}, + ) { + Text(text = String.format("%s", num)) + } + } + } +} + +@Preview(group = "Center") +@Composable +fun ColumnCenter() { + ConstraintLayout( + ConstraintSet { + val a = createRefFor("1") + val b = createRefFor("2") + val c = createRefFor("3") + val d = createRefFor("4") + + val g1 = createColumn( + a, b, c, d, + verticalChainStyle = ChainStyle.Packed, + verticalChainBias = 0.5f + ) + constrain(g1) { + width = Dimension.matchParent + height = Dimension.matchParent + start.linkTo(parent.start) + end.linkTo(parent.end) + } + }, + modifier = Modifier.fillMaxSize() + ) { + val numArray = arrayOf("1", "2", "3", "4") + for (num in numArray) { + Button( + modifier = Modifier.layoutId(num).size(50.dp), + onClick = {}, + ) { + Text(text = String.format("%s", num)) + } + } + } +} + +@Preview(group = "TopCenter") +@Composable +fun ColumnTopCenter() { + ConstraintLayout( + ConstraintSet { + val a = createRefFor("1") + val b = createRefFor("2") + val c = createRefFor("3") + val d = createRefFor("4") + + val g1 = createColumn( + a, b, c, d, + verticalChainStyle = ChainStyle.Packed, + verticalChainBias = 0f + ) + constrain(g1) { + width = Dimension.matchParent + height = Dimension.matchParent + start.linkTo(parent.start) + end.linkTo(parent.end) + } + }, + modifier = Modifier.fillMaxSize() + ) { + val numArray = arrayOf("1", "2", "3", "4") + for (num in numArray) { + Button( + modifier = Modifier.layoutId(num).size(50.dp), + onClick = {}, + ) { + Text(text = String.format("%s", num)) + } + } + } +} + +@Preview(group = "BottomCenter") +@Composable +fun ColumnBottomCenter() { + ConstraintLayout( + ConstraintSet { + val a = createRefFor("1") + val b = createRefFor("2") + val c = createRefFor("3") + val d = createRefFor("4") + + val g1 = createColumn( + a, b, c, d, + verticalChainStyle = ChainStyle.Packed, + verticalChainBias = 1f + ) + constrain(g1) { + width = Dimension.matchParent + height = Dimension.matchParent + start.linkTo(parent.start) + end.linkTo(parent.end) + } + }, + modifier = Modifier.fillMaxSize() + ) { + val numArray = arrayOf("1", "2", "3", "4") + for (num in numArray) { + Button( + modifier = Modifier.layoutId(num).size(50.dp), + onClick = {}, + ) { + Text(text = String.format("%s", num)) + } + } + } +} + +@Preview(group = "WeightFilled") +@Composable +fun ColumnWeightFilled() { + ConstraintLayout( + ConstraintSet { + val a = createRefFor("1") + val b = createRefFor("2") + val c = createRefFor("3") + val d = createRefFor("4") + + val g1 = createColumn( + a, b, c, d, + verticalChainStyle = ChainStyle.Spread, + verticalChainBias = 1f + ) + constrain(g1) { + width = Dimension.matchParent + height = Dimension.matchParent + start.linkTo(parent.start) + end.linkTo(parent.end) + } + + constrain(a) { + height = Dimension.fillToConstraints + verticalChainWeight = 1f + } + constrain(b) { + height = Dimension.fillToConstraints + verticalChainWeight = 2f + } + constrain(c) { + height = Dimension.fillToConstraints + verticalChainWeight = 1f + } + constrain(d) { + height = Dimension.fillToConstraints + verticalChainWeight = 1f + } + }, + modifier = Modifier.fillMaxSize() + ) { + val numArray = arrayOf("1", "2", "3", "4") + for (num in numArray) { + Button( + modifier = Modifier.layoutId(num).size(50.dp), + onClick = {}, + ) { + Text(text = String.format("%s", num)) + } + } + } +} + + + diff --git a/projects/ComposeConstraintLayout/app/src/main/java/com/example/constraintlayout/ComposeRow.kt b/projects/ComposeConstraintLayout/app/src/main/java/com/example/constraintlayout/ComposeRow.kt new file mode 100644 index 000000000..6523a4123 --- /dev/null +++ b/projects/ComposeConstraintLayout/app/src/main/java/com/example/constraintlayout/ComposeRow.kt @@ -0,0 +1,399 @@ +/* + * Copyright (C) 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 com.example.constraintlayout + + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.material.Button +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.FirstBaseline +import androidx.compose.ui.layout.LastBaseline +import androidx.compose.ui.layout.layoutId +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.constraintlayout.compose.* + +@Preview(group = "EqualWeight") +@Composable +fun RowEqualWeight() { + ConstraintLayout( + ConstraintSet { + val a = createRefFor("1") + val b = createRefFor("2") + val c = createRefFor("3") + val d = createRefFor("4") + + val g1 = createRow( + a, b, c, d, + horizontalChainStyle = ChainStyle.Spread, + horizontalChainBias = 1f + ) + constrain(g1) { + width = Dimension.matchParent + height = Dimension.matchParent + top.linkTo(parent.top) + bottom.linkTo(parent.bottom) + } + + constrain(a) { + width = Dimension.fillToConstraints + horizontalChainWeight = 1f + } + constrain(b) { + width = Dimension.fillToConstraints + horizontalChainWeight = 1f + } + constrain(c) { + width = Dimension.fillToConstraints + horizontalChainWeight = 1f + } + constrain(d) { + width = Dimension.fillToConstraints + horizontalChainWeight = 1f + } + }, + modifier = Modifier.fillMaxSize() + ) { + val numArray = arrayOf("1", "2", "3", "4") + for (num in numArray) { + Button( + modifier = Modifier.layoutId(num).width(50.dp), + onClick = {}, + ) { + Text(text = String.format("%s", num)) + } + } + } +} + +@Preview(group = "SpaceEvenly") +@Composable +fun RowSpaceEvenly() { + ConstraintLayout( + ConstraintSet { + val a = createRefFor("1") + val b = createRefFor("2") + val c = createRefFor("3") + val d = createRefFor("4") + + val g1 = createRow( + a, b, c, d, + horizontalChainStyle = ChainStyle.Spread, + ) + constrain(g1) { + width = Dimension.matchParent + height = Dimension.matchParent + top.linkTo(parent.top) + bottom.linkTo(parent.bottom) + } + }, + modifier = Modifier.fillMaxSize() + ) { + val numArray = arrayOf("1", "2", "3", "4") + for (num in numArray) { + Button( + modifier = Modifier.layoutId(num).width(50.dp), + onClick = {}, + ) { + Text(text = String.format("%s", num)) + } + } + } +} + +@Preview(group = "SpaceAround") +@Composable +fun RowSpaceAround() { + ConstraintLayout( + ConstraintSet { + val a = createRefFor("1") + val b = createRefFor("2") + val c = createRefFor("3") + val d = createRefFor("4") + + val g1 = createRow( + a, b, c, d, + ) + constrain(g1) { + width = Dimension.matchParent + height = Dimension.matchParent + top.linkTo(parent.top) + bottom.linkTo(parent.bottom) + } + }, + modifier = Modifier.fillMaxSize() + ) { + val numArray = arrayOf("1", "2", "3", "4") + for (num in numArray) { + Button( + modifier = Modifier.layoutId(num).width(50.dp), + onClick = {}, + ) { + Text(text = String.format("%s", num)) + } + } + } +} + +@Preview(group = "SpaceBetween") +@Composable +fun RowSpaceBetween() { + ConstraintLayout( + ConstraintSet { + val a = createRefFor("1") + val b = createRefFor("2") + val c = createRefFor("3") + val d = createRefFor("4") + + val g1 = createRow( + a, b, c, d, + horizontalChainStyle = ChainStyle.SpreadInside, + ) + constrain(g1) { + width = Dimension.matchParent + height = Dimension.matchParent + top.linkTo(parent.top) + bottom.linkTo(parent.bottom) + } + }, + modifier = Modifier.fillMaxSize() + ) { + val numArray = arrayOf("1", "2", "3", "4") + for (num in numArray) { + Button( + modifier = Modifier.layoutId(num).width(50.dp), + onClick = {}, + ) { + Text(text = String.format("%s", num)) + } + } + } +} + +@Preview(group = "Center") +@Composable +fun RowCenter() { + ConstraintLayout( + ConstraintSet { + val a = createRefFor("1") + val b = createRefFor("2") + val c = createRefFor("3") + val d = createRefFor("4") + + val g1 = createRow( + a, b, c, d, + horizontalChainStyle = ChainStyle.Packed, + horizontalChainBias = 0.5f + ) + constrain(g1) { + width = Dimension.matchParent + height = Dimension.matchParent + top.linkTo(parent.top) + bottom.linkTo(parent.bottom) + } + }, + modifier = Modifier.fillMaxSize() + ) { + val numArray = arrayOf("1", "2", "3", "4") + for (num in numArray) { + Button( + modifier = Modifier.layoutId(num).width(50.dp), + onClick = {}, + ) { + Text(text = String.format("%s", num)) + } + } + } +} + +@Preview(group = "StartCenter") +@Composable +fun RowStartCenter() { + ConstraintLayout( + ConstraintSet { + val a = createRefFor("1") + val b = createRefFor("2") + val c = createRefFor("3") + val d = createRefFor("4") + + val g1 = createRow( + a, b, c, d, + horizontalChainStyle = ChainStyle.Packed, + horizontalChainBias = 0f + ) + constrain(g1) { + width = Dimension.matchParent + height = Dimension.matchParent + top.linkTo(parent.top) + bottom.linkTo(parent.bottom) + } + }, + modifier = Modifier.fillMaxSize() + ) { + val numArray = arrayOf("1", "2", "3", "4") + for (num in numArray) { + Button( + modifier = Modifier.layoutId(num).width(50.dp), + onClick = {}, + ) { + Text(text = String.format("%s", num)) + } + } + } +} + +@Preview(group = "EndCenter") +@Composable +fun RowEndCenter() { + ConstraintLayout( + ConstraintSet { + val a = createRefFor("1") + val b = createRefFor("2") + val c = createRefFor("3") + val d = createRefFor("4") + + val g1 = createRow( + a, b, c, d, + horizontalChainStyle = ChainStyle.Packed, + horizontalChainBias = 1f + ) + constrain(g1) { + width = Dimension.matchParent + height = Dimension.matchParent + top.linkTo(parent.top) + bottom.linkTo(parent.bottom) + } + }, + modifier = Modifier.fillMaxSize() + ) { + val numArray = arrayOf("1", "2", "3", "4") + for (num in numArray) { + Button( + modifier = Modifier.layoutId(num).width(50.dp), + onClick = {}, + ) { + Text(text = String.format("%s", num)) + } + } + } +} + +@Preview(group = "Baseline") +@Composable +fun RowBaseline() { + ConstraintLayout( + ConstraintSet { + val a = createRefFor("1") + val b = createRefFor("2") + val c = createRefFor("3") + val d = createRefFor("box") + val g1 = createRow( + a, b, c, d, + horizontalChainStyle = ChainStyle.Spread, + ) + constrain(g1) { + width = Dimension.matchParent + height = Dimension.matchParent + top.linkTo(parent.top) + bottom.linkTo(parent.bottom) + } + constrain(d) { + bottom.linkTo(c.baseline) + } + }, + modifier = Modifier.fillMaxSize() + ) { + val numArray = arrayOf("1", "2", "3") + for (num in numArray) { + Button( + modifier = Modifier.layoutId(num).width(50.dp), + onClick = {}, + ) { + Text(text = String.format("%s", num)) + } + Box(Modifier.layoutId("box").size(50.dp).background(Color.Blue)) + } + } +} + +@Preview(group = "WeightFilled") +@Composable +fun RowWeightFilled() { + ConstraintLayout( + ConstraintSet { + val a = createRefFor("1") + val b = createRefFor("2") + val c = createRefFor("3") + val d = createRefFor("4") + + val g1 = createRow( + a, b, c, d, + horizontalChainStyle = ChainStyle.Spread, + horizontalChainBias = 1f + ) + constrain(g1) { + width = Dimension.matchParent + height = Dimension.matchParent + top.linkTo(parent.top) + bottom.linkTo(parent.bottom) + } + + constrain(a) { + width = Dimension.fillToConstraints + horizontalChainWeight = 1f + } + constrain(b) { + width = Dimension.fillToConstraints + horizontalChainWeight = 2f + } + constrain(c) { + width = Dimension.fillToConstraints + horizontalChainWeight = 1f + } + constrain(d) { + width = Dimension.fillToConstraints + horizontalChainWeight = 1f + } + }, + modifier = Modifier.fillMaxSize() + ) { + val numArray = arrayOf("1", "2", "3", "4") + for (num in numArray) { + Button( + modifier = Modifier.layoutId(num).width(50.dp), + onClick = {}, + ) { + Text(text = String.format("%s", num)) + } + } + } +} + + diff --git a/projects/ComposeConstraintLayout/app/src/main/java/com/example/constraintlayout/RowColumnExpeirment.kt b/projects/ComposeConstraintLayout/app/src/main/java/com/example/constraintlayout/RowColumnExpeirment.kt new file mode 100644 index 000000000..b9898ebc0 --- /dev/null +++ b/projects/ComposeConstraintLayout/app/src/main/java/com/example/constraintlayout/RowColumnExpeirment.kt @@ -0,0 +1,348 @@ +/* + * Copyright (C) 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 com.example.constraintlayout + + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.material.Button +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.FirstBaseline +import androidx.compose.ui.layout.LastBaseline +import androidx.compose.ui.layout.layoutId +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.constraintlayout.compose.* + +@Preview(group = "chain") +@Composable +fun ChainDemo() { + ConstraintLayout( + ConstraintSet { + val a = createRefFor("1") + val b = createRefFor("2") + val c = createRefFor("3") + val d = createRefFor("4") + val e = createRefFor("5") + val c1 = createHorizontalChain( + a, b, c, d, e, + chainStyle = ChainStyle.Spread + ) + constrain(c1) { + start.linkTo(parent.start) + end.linkTo(parent.end) + } + constrain(a) { +// width = Dimension.fillToConstraints.atMostWrapContent +// horizontalChainWeight = 1f + } + constrain(b) { +// width = Dimension.fillToConstraints.atMostWrapContent +// horizontalChainWeight = 1f +// top.linkTo(g1.top) + } + constrain(c) { +// width = Dimension.fillToConstraints.atMostWrapContent +// horizontalChainWeight = 1f +// bottom.linkTo(g1.bottom) + } + constrain(d) { +// width = Dimension.fillToConstraints.atMostWrapContent +// horizontalChainWeight = 1f + } + constrain(e) { +// width = Dimension.fillToConstraints.atMostWrapContent +// horizontalChainWeight = 1f + top.linkTo(d.baseline) + } + + }, + modifier = Modifier.fillMaxSize() + ) { + val numArray = arrayOf("1", "2", "3", "4") + for (num in numArray) { + Button( + modifier = Modifier.layoutId(num).width(50.dp), + onClick = {}, + ) { + Text(text = String.format("btn%s", num)) + } + } + Box(modifier = Modifier.size(50.dp).layoutId(5).background(color = Color.Red)) + } +} + +@Preview(group = "flow") +@Composable +fun FlowDemo() { + ConstraintLayout( + ConstraintSet { + val a = createRefFor("1") + val b = createRefFor("2") + val c = createRefFor("3") + val d = createRefFor("4") + val e = createRefFor("5") + val f1 = createFlow( + a, b, c, d, e, + horizontalStyle = FlowStyle.Packed, + horizontalFlowBias = 0.5f + ) + constrain(f1) { + width = Dimension.matchParent + height = Dimension.matchParent + start.linkTo(parent.start) + end.linkTo(parent.end) + top.linkTo(parent.top) + bottom.linkTo(parent.bottom) + } + constrain(a) { +// width = Dimension.fillToConstraints +// horizontalChainWeight = 1f + bottom.linkTo(f1.bottom) + } + constrain(b) { +// width = Dimension.fillToConstraints +// horizontalChainWeight = 2f + top.linkTo(f1.top) + } + constrain(c) { +// width = Dimension.fillToConstraints +// horizontalChainWeight = 1f + bottom.linkTo(d.baseline) + } + constrain(d) { +// width = Dimension.fillToConstraints +// horizontalChainWeight = 1f + top.linkTo(f1.top) + bottom.linkTo(f1.bottom) + } + constrain(e) { +// width = Dimension.fillToConstraints +// horizontalChainWeight = 1f + top.linkTo(d.baseline) + } + + }, + modifier = Modifier.fillMaxSize() + ) { + val numArray = arrayOf("1", "2", "3", "4") + for (num in numArray) { + Button( + modifier = Modifier.layoutId(num).width(50.dp), + onClick = {}, + ) { + Text(text = String.format("btn%s", num)) + } + } + Box(modifier = Modifier.size(50.dp).layoutId(5).background(color = Color.Red)) + } +} + +@Preview(group = "row") +@Composable +fun ChainRowDemo() { + ConstraintLayout( + ConstraintSet { + val a = createRefFor("1") + val b = createRefFor("2") + val c = createRefFor("3") + val d = createRefFor("4") + val e = createRefFor("5") + + val g1 = createRow( + a, b, c, d, e, + horizontalChainStyle = ChainStyle.SpreadInside, +// horizontalChainBias = 1f + ) + constrain(g1) { + width = Dimension.matchParent + height = Dimension.matchParent + top.linkTo(parent.top) + bottom.linkTo(parent.bottom) + start.linkTo(parent.start) + end.linkTo(parent.end) + } + constrain(a) { +// width = Dimension.fillToConstraints +// horizontalChainWeight = 1f + } + constrain(b) { +// width = Dimension.fillToConstraints +// horizontalChainWeight = 1f +// top.linkTo(g1.top) + } + constrain(c) { +// width = Dimension.fillToConstraints +// horizontalChainWeight = 1f +// bottom.linkTo(g1.bottom) + } + constrain(d) { +// width = Dimension.fillToConstraints +// horizontalChainWeight = 1f + top.linkTo(g1.top) + bottom.linkTo(g1.bottom) + } + constrain(e) { +// width = Dimension.fillToConstraints +// horizontalChainWeight = 1f + top.linkTo(d.baseline) + } + }, + modifier = Modifier.fillMaxSize() + ) { + val numArray = arrayOf("1", "2", "3", "4") + for (num in numArray) { + Button( + modifier = Modifier.layoutId(num).width(50.dp), + onClick = {}, + ) { + Text(text = String.format("%s", num)) + } + } + Box(modifier = Modifier.size(50.dp).layoutId(5).background(color = Color.Red)) + } +} + +@Preview(group = "compose") +@Composable +fun ComposeRow() { + Row (modifier = Modifier.fillMaxHeight(0.5f).fillMaxWidth()) { + Box(modifier = Modifier.size(50.dp) + .background(color = Color.Red) + .alignBy { it.measuredHeight } + ) + Text("Hello World", + color = Color.Blue, + fontSize = 30.sp, + modifier = Modifier.alignBy(FirstBaseline) + ) + Box(modifier = Modifier.size(50.dp) + .background(color = Color.Red) + .alignBy { it.measuredHeight / 2 } + ) + Text("Hello World line3", + color = Color.Blue, + fontSize = 30.sp, + modifier = Modifier.alignBy(LastBaseline) + ) + } + Row(modifier = Modifier.fillMaxSize(), + Arrangement.SpaceBetween, + Alignment.CenterVertically, + ) { + Box(modifier = Modifier.size(50.dp) + .background(color = Color.Blue) + .weight(1f, fill = false) + ) + Box(modifier = Modifier.size(50.dp) + .background(color = Color.Red) + .weight(2f, fill = false) + ) + Box(modifier = Modifier.size(50.dp) + .background(color = Color.Green) + .weight(1f, fill = false) + ) + Box(modifier = Modifier.size(50.dp) + .background(color = Color.Green) + .weight(1f, fill = false) + ) + } +} + +@Preview(group = "column") +@Composable +fun ChainColumnDemo() { + ConstraintLayout( + ConstraintSet { + val a = createRefFor("1") + val b = createRefFor("2") + val c = createRefFor("3") + val d = createRefFor("4") + val g1 = createColumn( + a, b, c, d, + verticalChainStyle = ChainStyle.SpreadInside + ) + constrain(g1) { + width = Dimension.matchParent + height = Dimension.matchParent +// start.linkTo(parent.start) +// end.linkTo(parent.end) +// top.linkTo(parent.top) +// bottom.linkTo(parent.bottom) + } + }, + modifier = Modifier.fillMaxSize() + ) { + val numArray = arrayOf("1", "2", "3", "4") + for (num in numArray) { + Button( + modifier = Modifier.layoutId(num).width(50.dp), + onClick = {}, + ) { + Text(text = String.format("btn%s", num)) + } + } + } +} + +@Preview(group = "chain2") +@Composable +fun ChainColumnDemo1() { + ConstraintLayout( + ConstraintSet { + val a = createRefFor("1") + val b = createRefFor("2") + val c = createRefFor("3") + val d = createRefFor("4") + val e = createRefFor("5") + val c1 = createVerticalChain( + a, b, c, d, e, + chainStyle = ChainStyle.Packed + ) + constrain(c1) { + top.linkTo(parent.top) + bottom.linkTo(parent.bottom) + } + + }, + modifier = Modifier.fillMaxSize() + ) { + val numArray = arrayOf("1", "2", "3", "4") + for (num in numArray) { + Button( + modifier = Modifier.layoutId(num).width(50.dp), + onClick = {}, + ) { + Text(text = String.format("btn%s", num)) + } + } + Box(modifier = Modifier.size(50.dp).layoutId(5).background(color = Color.Red)) + } +} + diff --git a/projects/GridExperiments/core/build.gradle b/projects/GridExperiments/core/build.gradle index 35012e1a0..5456e2fb6 100644 --- a/projects/GridExperiments/core/build.gradle +++ b/projects/GridExperiments/core/build.gradle @@ -12,4 +12,5 @@ sourceSets{ dependencies { testImplementation 'org.testng:testng:7.3.0' + implementation "androidx.annotation:annotation:1.5.0" }