[go: nahoru, domu]

blob: 8f39c7e25e57fba2dc61b92000d2814151238832 [file] [log] [blame]
/*
* Copyright 2020 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.compose.foundation.layout
import androidx.compose.mutableStateOf
import androidx.test.filters.SmallTest
import androidx.ui.core.Modifier
import androidx.ui.core.Ref
import androidx.ui.core.positionInRoot
import androidx.ui.core.layoutId
import androidx.ui.core.onPositioned
import androidx.ui.core.positionInParent
import androidx.compose.foundation.Box
import androidx.ui.geometry.Offset
import androidx.ui.test.createComposeRule
import androidx.ui.test.runOnIdle
import androidx.ui.unit.IntSize
import androidx.ui.test.waitForIdle
import androidx.ui.unit.dp
import org.junit.Assert
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import kotlin.math.roundToInt
@SmallTest
@RunWith(JUnit4::class)
@OptIn(ExperimentalLayout::class)
class ConstraintLayoutTest : LayoutTest() {
@get:Rule
val composeTestRule = createComposeRule()
// region sizing tests
@Test
fun dividerMatchTextHeight_spread() = with(density) {
val aspectRatioBoxSize = Ref<IntSize>()
val dividerSize = Ref<IntSize>()
composeTestRule.setContent {
ConstraintLayout(
// Make CL fixed width and wrap content height.
modifier = Modifier.fillMaxWidth()
) {
val (aspectRatioBox, divider) = createRefs()
val guideline = createGuidelineFromAbsoluteLeft(0.5f)
Box(Modifier
.constrainAs(aspectRatioBox) {
centerTo(parent)
start.linkTo(guideline)
width = Dimension.preferredWrapContent
height = Dimension.wrapContent
}
// Try to be large to make wrap content impossible.
.preferredWidth((composeTestRule.displayMetrics.widthPixels).toDp())
// This could be any (width in height out child) e.g. text
.aspectRatio(2f)
.onPositioned { coordinates ->
aspectRatioBoxSize.value = coordinates.size
}
)
Box(Modifier
.constrainAs(divider) {
centerTo(parent)
width = Dimension.value(1.dp)
height = Dimension.fillToConstraints
}.onPositioned { coordinates ->
dividerSize.value = coordinates.size
}
)
}
}
runOnIdle {
// The aspect ratio could not wrap and it is wrap suggested, so it respects constraints.
assertEquals(
(composeTestRule.displayMetrics.widthPixels / 2),
aspectRatioBoxSize.value!!.width
)
// Aspect ratio is preserved.
assertEquals(
(composeTestRule.displayMetrics.widthPixels / 2 / 2),
aspectRatioBoxSize.value!!.height
)
// Divider has fixed width 1.dp in constraint set.
assertEquals(1.dp.toIntPx(), dividerSize.value!!.width)
// Divider has spread height so it should spread to fill the height of the CL,
// which in turns is given by the size of the aspect ratio box.
assertEquals(aspectRatioBoxSize.value!!.height, dividerSize.value!!.height)
}
}
@Test
fun dividerMatchTextHeight_spread_withPreferredWrapHeightText() = with(density) {
val aspectRatioBoxSize = Ref<IntSize>()
val dividerSize = Ref<IntSize>()
composeTestRule.setContent {
ConstraintLayout(
// Make CL fixed width and wrap content height.
modifier = Modifier.fillMaxWidth()
) {
val (aspectRatioBox, divider) = createRefs()
val guideline = createGuidelineFromAbsoluteLeft(0.5f)
Box(Modifier
.constrainAs(aspectRatioBox) {
centerTo(parent)
start.linkTo(guideline)
width = Dimension.preferredWrapContent
height = Dimension.preferredWrapContent
}
// Try to be large to make wrap content impossible.
.preferredWidth((composeTestRule.displayMetrics.widthPixels).toDp())
// This could be any (width in height out child) e.g. text
.aspectRatio(2f)
.onPositioned { coordinates ->
aspectRatioBoxSize.value = coordinates.size
}
)
Box(Modifier
.constrainAs(divider) {
centerTo(parent)
width = Dimension.value(1.dp)
height = Dimension.fillToConstraints
}.onPositioned { coordinates ->
dividerSize.value = coordinates.size
}
)
}
}
runOnIdle {
// The aspect ratio could not wrap and it is wrap suggested, so it respects constraints.
assertEquals(
(composeTestRule.displayMetrics.widthPixels / 2),
aspectRatioBoxSize.value!!.width
)
// Aspect ratio is preserved.
assertEquals(
(composeTestRule.displayMetrics.widthPixels / 2 / 2),
aspectRatioBoxSize.value!!.height
)
// Divider has fixed width 1.dp in constraint set.
assertEquals(1.dp.toIntPx(), dividerSize.value!!.width)
// Divider has spread height so it should spread to fill the height of the CL,
// which in turns is given by the size of the aspect ratio box.
assertEquals(aspectRatioBoxSize.value!!.height, dividerSize.value!!.height)
}
}
@Test
fun dividerMatchTextHeight_percent() = with(density) {
val aspectRatioBoxSize = Ref<IntSize>()
val dividerSize = Ref<IntSize>()
composeTestRule.setContent {
ConstraintLayout(
// Make CL fixed width and wrap content height.
modifier = Modifier.fillMaxWidth()
) {
val (aspectRatioBox, divider) = createRefs()
val guideline = createGuidelineFromAbsoluteLeft(0.5f)
Box(Modifier
.constrainAs(aspectRatioBox) {
centerTo(parent)
start.linkTo(guideline)
width = Dimension.preferredWrapContent
height = Dimension.wrapContent
}
// Try to be large to make wrap content impossible.
.preferredWidth((composeTestRule.displayMetrics.widthPixels).toDp())
// This could be any (width in height out child) e.g. text
.aspectRatio(2f)
.onPositioned { coordinates ->
aspectRatioBoxSize.value = coordinates.size
}
)
Box(Modifier
.constrainAs(divider) {
centerTo(parent)
width = Dimension.value(1.dp)
height = Dimension.percent(0.8f)
}
.onPositioned { coordinates ->
dividerSize.value = coordinates.size
}
)
}
}
runOnIdle {
// The aspect ratio could not wrap and it is wrap suggested, so it respects constraints.
assertEquals(
(composeTestRule.displayMetrics.widthPixels / 2),
aspectRatioBoxSize.value!!.width
)
// Aspect ratio is preserved.
assertEquals(
(composeTestRule.displayMetrics.widthPixels / 2 / 2),
aspectRatioBoxSize.value!!.height
)
// Divider has fixed width 1.dp in constraint set.
assertEquals(1.dp.toIntPx(), dividerSize.value!!.width)
// Divider has percent height so it should spread to fill 0.8 of the height of the CL,
// which in turns is given by the size of the aspect ratio box.
assertEquals((aspectRatioBoxSize.value!!.height * 0.8f).roundToInt(),
dividerSize.value!!.height)
}
}
@Test
fun dividerMatchTextHeight_inWrapConstraintLayout_longText() = with(density) {
val aspectRatioBoxSize = Ref<IntSize>()
val dividerSize = Ref<IntSize>()
composeTestRule.setContent {
// CL is wrap content.
ConstraintLayout {
val (aspectRatioBox, divider) = createRefs()
val guideline = createGuidelineFromAbsoluteLeft(0.5f)
Box(Modifier
.constrainAs(aspectRatioBox) {
centerTo(parent)
start.linkTo(guideline)
width = Dimension.preferredWrapContent
height = Dimension.wrapContent
}
// Try to be large to make wrap content impossible.
.preferredWidth((composeTestRule.displayMetrics.widthPixels).toDp())
// This could be any (width in height out child) e.g. text
.aspectRatio(2f)
.onPositioned { coordinates ->
aspectRatioBoxSize.value = coordinates.size
}
)
Box(Modifier
.constrainAs(divider) {
centerTo(parent)
width = Dimension.value(1.dp)
height = Dimension.percent(0.8f)
}
.onPositioned { coordinates ->
dividerSize.value = coordinates.size
}
)
}
}
runOnIdle {
// The aspect ratio could not wrap and it is wrap suggested, so it respects constraints.
assertEquals(
(composeTestRule.displayMetrics.widthPixels / 2),
aspectRatioBoxSize.value!!.width
)
// Aspect ratio is preserved.
assertEquals(
(composeTestRule.displayMetrics.widthPixels / 2 / 2),
aspectRatioBoxSize.value!!.height
)
// Divider has fixed width 1.dp in constraint set.
assertEquals(1.dp.toIntPx(), dividerSize.value!!.width)
// Divider has percent height so it should spread to fill 0.8 of the height of the CL,
// which in turns is given by the size of the aspect ratio box.
// TODO(popam; b/150277566): uncomment
assertEquals(
(aspectRatioBoxSize.value!!.height * 0.8f).roundToInt(),
dividerSize.value!!.height
)
}
}
@Test
fun dividerMatchTextHeight_inWrapConstraintLayout_shortText() = with(density) {
val constraintLayoutSize = Ref<IntSize>()
val aspectRatioBoxSize = Ref<IntSize>()
val dividerSize = Ref<IntSize>()
val size = 40.toDp()
composeTestRule.setContent {
ConstraintLayout(
// CL is wrapping width and height.
modifier = Modifier.onPositioned {
constraintLayoutSize.value = it.size
}
) {
val (aspectRatioBox, divider) = createRefs()
val guideline = createGuidelineFromAbsoluteLeft(0.5f)
Box(Modifier
.constrainAs(aspectRatioBox) {
centerTo(parent)
start.linkTo(guideline)
width = Dimension.preferredWrapContent
height = Dimension.wrapContent
}
// Small width for the CL to wrap it.
.preferredWidth(size)
// This could be any (width in height out child) e.g. text
.aspectRatio(2f)
.onPositioned { coordinates ->
aspectRatioBoxSize.value = coordinates.size
}
)
Box(Modifier
.constrainAs(divider) {
centerTo(parent)
width = Dimension.value(1.dp)
height = Dimension.fillToConstraints
}
.onPositioned { coordinates ->
dividerSize.value = coordinates.size
}
)
}
}
runOnIdle {
// The width of the ConstraintLayout should be twice the width of the aspect ratio box.
assertEquals(size.toIntPx() * 2, constraintLayoutSize.value!!.width)
// The height of the ConstraintLayout should be the height of the aspect ratio box.
assertEquals(size.toIntPx() / 2, constraintLayoutSize.value!!.height)
// The aspect ratio gets the requested size.
assertEquals(size.toIntPx(), aspectRatioBoxSize.value!!.width)
// Aspect ratio is preserved.
assertEquals(size.toIntPx() / 2, aspectRatioBoxSize.value!!.height)
// Divider has fixed width 1.dp in constraint set.
assertEquals(1.dp.toIntPx(), dividerSize.value!!.width)
// Divider should have the height of the aspect ratio box.
assertEquals(aspectRatioBoxSize.value!!.height, dividerSize.value!!.height)
}
}
// endregion
// region positioning tests
@Test
fun testConstraintLayout_withInlineDSL() = with(density) {
val boxSize = 100
val offset = 150
val position = Array(3) { Ref<Offset>() }
composeTestRule.setContent {
ConstraintLayout(Modifier.fillMaxSize()) {
val (box0, box1, box2) = createRefs()
Box(Modifier
.constrainAs(box0) {
centerTo(parent)
}
.preferredSize(boxSize.toDp(), boxSize.toDp())
.onPositioned {
position[0].value = it.positionInRoot
}
)
val half = createGuidelineFromAbsoluteLeft(fraction = 0.5f)
Box(Modifier
.constrainAs(box1) {
start.linkTo(half, margin = offset.toDp())
bottom.linkTo(box0.top)
}
.preferredSize(boxSize.toDp(), boxSize.toDp())
.onPositioned {
position[1].value = it.positionInRoot
}
)
Box(Modifier
.constrainAs(box2) {
start.linkTo(parent.start, margin = offset.toDp())
bottom.linkTo(parent.bottom, margin = offset.toDp())
}
.preferredSize(boxSize.toDp(), boxSize.toDp())
.onPositioned {
position[2].value = it.positionInRoot
}
)
}
}
val displayWidth = composeTestRule.displayMetrics.widthPixels
val displayHeight = composeTestRule.displayMetrics.heightPixels
runOnIdle {
assertEquals(
Offset(
((displayWidth - boxSize) / 2).toFloat(),
((displayHeight - boxSize) / 2).toFloat()),
position[0].value
)
assertEquals(
Offset(
(displayWidth / 2 + offset).toFloat(),
((displayHeight - boxSize) / 2 - boxSize).toFloat()
),
position[1].value
)
assertEquals(
Offset(
offset.toFloat(),
(displayHeight - boxSize - offset).toFloat()
),
position[2].value
)
}
}
@Test
fun testConstraintLayout_withConstraintSet() = with(density) {
val boxSize = 100
val offset = 150
val position = Array(3) { Ref<Offset>() }
composeTestRule.setContent {
ConstraintLayout(
ConstraintSet2 {
val box0 = createRefFor("box0")
val box1 = createRefFor("box1")
val box2 = createRefFor("box2")
constrain(box0) {
centerTo(parent)
}
val half = createGuidelineFromAbsoluteLeft(fraction = 0.5f)
constrain(box1) {
start.linkTo(half, margin = offset.toDp())
bottom.linkTo(box0.top)
}
constrain(box2) {
start.linkTo(parent.start, margin = offset.toDp())
bottom.linkTo(parent.bottom, margin = offset.toDp())
}
},
Modifier.fillMaxSize()
) {
for (i in 0..2) {
Box(Modifier.layoutId("box$i").preferredSize(boxSize.toDp(), boxSize.toDp())
.onPositioned {
position[i].value = it.positionInRoot
}
)
}
}
}
val displayWidth = composeTestRule.displayMetrics.widthPixels
val displayHeight = composeTestRule.displayMetrics.heightPixels
runOnIdle {
assertEquals(
Offset(
(displayWidth - boxSize) / 2f,
(displayHeight - boxSize) / 2f
),
position[0].value
)
assertEquals(
Offset(
(displayWidth / 2f + offset).toFloat(),
((displayHeight - boxSize) / 2 - boxSize).toFloat()
),
position[1].value
)
assertEquals(
Offset(
offset.toFloat(),
(displayHeight - boxSize - offset).toFloat()
),
position[2].value
)
}
}
@Test
fun testConstraintLayout_rtl() = with(density) {
val boxSize = 100
val offset = 150
val position = Array(3) { Ref<Offset>() }
composeTestRule.setContent {
ConstraintLayout(Modifier.rtl.fillMaxSize()) {
val (box0, box1, box2) = createRefs()
Box(Modifier
.constrainAs(box0) {
centerTo(parent)
}
.preferredSize(boxSize.toDp(), boxSize.toDp())
.onPositioned {
position[0].value = it.positionInRoot
}
)
val half = createGuidelineFromAbsoluteLeft(fraction = 0.5f)
Box(Modifier
.constrainAs(box1) {
start.linkTo(half, margin = offset.toDp())
bottom.linkTo(box0.top)
}
.preferredSize(boxSize.toDp(), boxSize.toDp())
.onPositioned {
position[1].value = it.positionInRoot
}
)
Box(Modifier
.constrainAs(box2) {
start.linkTo(parent.start, margin = offset.toDp())
bottom.linkTo(parent.bottom, margin = offset.toDp())
}
.preferredSize(boxSize.toDp(), boxSize.toDp())
.onPositioned {
position[2].value = it.positionInRoot
}
)
}
}
val displayWidth = composeTestRule.displayMetrics.widthPixels
val displayHeight = composeTestRule.displayMetrics.heightPixels
runOnIdle {
assertEquals(
Offset(
(displayWidth - boxSize) / 2f,
(displayHeight - boxSize) / 2f
),
position[0].value
)
assertEquals(
Offset(
(displayWidth / 2 - offset - boxSize).toFloat(),
((displayHeight - boxSize) / 2 - boxSize).toFloat()
),
position[1].value
)
assertEquals(
Offset(
(displayWidth - offset - boxSize).toFloat(),
(displayHeight - boxSize - offset).toFloat()
),
position[2].value
)
}
}
@Test
fun testConstraintLayout_helpers_ltr() = with(density) {
val size = 200.toDp()
val offset = 50.toDp()
val position = Array(8) { 0f }
composeTestRule.setContent {
ConstraintLayout(Modifier.size(size)) {
val guidelines = arrayOf(
createGuidelineFromStart(offset),
createGuidelineFromAbsoluteLeft(offset),
createGuidelineFromEnd(offset),
createGuidelineFromAbsoluteRight(offset),
createGuidelineFromStart(0.25f),
createGuidelineFromAbsoluteLeft(0.25f),
createGuidelineFromEnd(0.25f),
createGuidelineFromAbsoluteRight(0.25f)
)
guidelines.forEachIndexed { index, guideline ->
val ref = createRef()
Box(Modifier.size(1.dp)
.constrainAs(ref) {
absoluteLeft.linkTo(guideline)
}.onPositioned {
position[index] = it.positionInParent.x
}
)
}
}
}
runOnIdle {
Assert.assertEquals(50f, position[0])
Assert.assertEquals(50f, position[1])
Assert.assertEquals(150f, position[2])
Assert.assertEquals(150f, position[3])
Assert.assertEquals(50f, position[4])
Assert.assertEquals(50f, position[5])
Assert.assertEquals(150f, position[6])
Assert.assertEquals(150f, position[7])
}
}
@Test
fun testConstraintLayout_helpers_rtl() = with(density) {
val size = 200.toDp()
val offset = 50.toDp()
val position = Array(8) { 0f }
composeTestRule.setContent {
ConstraintLayout(Modifier.size(size).rtl) {
val guidelines = arrayOf(
createGuidelineFromStart(offset),
createGuidelineFromAbsoluteLeft(offset),
createGuidelineFromEnd(offset),
createGuidelineFromAbsoluteRight(offset),
createGuidelineFromStart(0.25f),
createGuidelineFromAbsoluteLeft(0.25f),
createGuidelineFromEnd(0.25f),
createGuidelineFromAbsoluteRight(0.25f)
)
guidelines.forEachIndexed { index, guideline ->
val ref = createRef()
Box(Modifier.size(1.dp)
.constrainAs(ref) {
absoluteLeft.linkTo(guideline)
}.onPositioned {
position[index] = it.positionInParent.x
}
)
}
}
}
runOnIdle {
Assert.assertEquals(150f, position[0])
Assert.assertEquals(50f, position[1])
Assert.assertEquals(50f, position[2])
Assert.assertEquals(150f, position[3])
Assert.assertEquals(150f, position[4])
Assert.assertEquals(50f, position[5])
Assert.assertEquals(50f, position[6])
Assert.assertEquals(150f, position[7])
}
}
@Test
fun testConstraintLayout_barriers_ltr() = with(density) {
val size = 200.toDp()
val offset = 50.toDp()
val position = Array(4) { 0f }
composeTestRule.setContent {
ConstraintLayout(Modifier.size(size)) {
val (box1, box2) = createRefs()
val guideline1 = createGuidelineFromAbsoluteLeft(offset)
val guideline2 = createGuidelineFromAbsoluteRight(offset)
Box(Modifier.size(1.toDp())
.constrainAs(box1) {
absoluteLeft.linkTo(guideline1)
}
)
Box(Modifier.size(1.toDp())
.constrainAs(box2) {
absoluteLeft.linkTo(guideline2)
}
)
val barriers = arrayOf(
createStartBarrier(box1, box2),
createAbsoluteLeftBarrier(box1, box2),
createEndBarrier(box1, box2),
createAbsoluteRightBarrier(box1, box2)
)
barriers.forEachIndexed { index, barrier ->
val ref = createRef()
Box(Modifier.size(1.dp)
.constrainAs(ref) {
absoluteLeft.linkTo(barrier)
}.onPositioned {
position[index] = it.positionInParent.x
}
)
}
}
}
runOnIdle {
Assert.assertEquals(50f, position[0])
Assert.assertEquals(50f, position[1])
Assert.assertEquals(151f, position[2])
Assert.assertEquals(151f, position[3])
}
}
@Test
fun testConstraintLayout_barriers_rtl() = with(density) {
val size = 200.toDp()
val offset = 50.toDp()
val position = Array(4) { 0f }
composeTestRule.setContent {
ConstraintLayout(Modifier.size(size).rtl) {
val (box1, box2) = createRefs()
val guideline1 = createGuidelineFromAbsoluteLeft(offset)
val guideline2 = createGuidelineFromAbsoluteRight(offset)
Box(Modifier.size(1.toDp())
.constrainAs(box1) {
absoluteLeft.linkTo(guideline1)
}
)
Box(Modifier.size(1.toDp())
.constrainAs(box2) {
absoluteLeft.linkTo(guideline2)
}
)
val barriers = arrayOf(
createStartBarrier(box1, box2),
createAbsoluteLeftBarrier(box1, box2),
createEndBarrier(box1, box2),
createAbsoluteRightBarrier(box1, box2)
)
barriers.forEachIndexed { index, barrier ->
val ref = createRef()
Box(Modifier.size(1.dp)
.constrainAs(ref) {
absoluteLeft.linkTo(barrier)
}.onPositioned {
position[index] = it.positionInParent.x
}
)
}
}
}
runOnIdle {
Assert.assertEquals(151f, position[0])
Assert.assertEquals(50f, position[1])
Assert.assertEquals(50f, position[2])
Assert.assertEquals(151f, position[3])
}
}
@Test
fun testConstraintLayout_anchors_ltr() = with(density) {
val size = 200.toDp()
val offset = 50.toDp()
val position = Array(16) { 0f }
composeTestRule.setContent {
ConstraintLayout(Modifier.size(size)) {
val box = createRef()
val guideline = createGuidelineFromAbsoluteLeft(offset)
Box(Modifier.size(1.toDp())
.constrainAs(box) {
absoluteLeft.linkTo(guideline)
}
)
val anchors = listOf<ConstrainScope.() -> Unit>(
{ start.linkTo(box.start) },
{ absoluteLeft.linkTo(box.start) },
{ start.linkTo(box.absoluteLeft) },
{ absoluteLeft.linkTo(box.absoluteLeft) },
{ end.linkTo(box.start) },
{ absoluteRight.linkTo(box.start) },
{ end.linkTo(box.absoluteLeft) },
{ absoluteRight.linkTo(box.absoluteLeft) },
{ start.linkTo(box.end) },
{ absoluteLeft.linkTo(box.end) },
{ start.linkTo(box.absoluteRight) },
{ absoluteLeft.linkTo(box.absoluteRight) },
{ end.linkTo(box.end) },
{ absoluteRight.linkTo(box.end) },
{ end.linkTo(box.absoluteRight) },
{ absoluteRight.linkTo(box.absoluteRight) }
)
anchors.forEachIndexed { index, anchor ->
val ref = createRef()
Box(Modifier.size(1.toDp())
.constrainAs(ref) {
anchor()
}.onPositioned {
position[index] = it.positionInParent.x
}
)
}
}
}
runOnIdle {
Assert.assertEquals(50f, position[0])
Assert.assertEquals(50f, position[1])
Assert.assertEquals(50f, position[2])
Assert.assertEquals(50f, position[3])
Assert.assertEquals(49f, position[4])
Assert.assertEquals(49f, position[5])
Assert.assertEquals(49f, position[6])
Assert.assertEquals(49f, position[7])
Assert.assertEquals(51f, position[8])
Assert.assertEquals(51f, position[9])
Assert.assertEquals(51f, position[10])
Assert.assertEquals(51f, position[11])
Assert.assertEquals(50f, position[12])
Assert.assertEquals(50f, position[13])
Assert.assertEquals(50f, position[14])
Assert.assertEquals(50f, position[15])
}
}
@Test
fun testConstraintLayout_anchors_rtl() = with(density) {
val size = 200.toDp()
val offset = 50.toDp()
val position = Array(16) { 0f }
composeTestRule.setContent {
ConstraintLayout(Modifier.size(size).rtl) {
val box = createRef()
val guideline = createGuidelineFromAbsoluteLeft(offset)
Box(Modifier.size(1.toDp())
.constrainAs(box) {
absoluteLeft.linkTo(guideline)
}
)
val anchors = listOf<ConstrainScope.() -> Unit>(
{ start.linkTo(box.start) },
{ absoluteLeft.linkTo(box.start) },
{ start.linkTo(box.absoluteLeft) },
{ absoluteLeft.linkTo(box.absoluteLeft) },
{ end.linkTo(box.start) },
{ absoluteRight.linkTo(box.start) },
{ end.linkTo(box.absoluteLeft) },
{ absoluteRight.linkTo(box.absoluteLeft) },
{ start.linkTo(box.end) },
{ absoluteLeft.linkTo(box.end) },
{ start.linkTo(box.absoluteRight) },
{ absoluteLeft.linkTo(box.absoluteRight) },
{ end.linkTo(box.end) },
{ absoluteRight.linkTo(box.end) },
{ end.linkTo(box.absoluteRight) },
{ absoluteRight.linkTo(box.absoluteRight) }
)
anchors.forEachIndexed { index, anchor ->
val ref = createRef()
Box(Modifier.size(1.toDp())
.constrainAs(ref) {
anchor()
}.onPositioned {
position[index] = it.positionInParent.x
}
)
}
}
}
runOnIdle {
Assert.assertEquals(50f, position[0])
Assert.assertEquals(51f, position[1])
Assert.assertEquals(49f, position[2])
Assert.assertEquals(50f, position[3])
Assert.assertEquals(51f, position[4])
Assert.assertEquals(50f, position[5])
Assert.assertEquals(50f, position[6])
Assert.assertEquals(49f, position[7])
Assert.assertEquals(49f, position[8])
Assert.assertEquals(50f, position[9])
Assert.assertEquals(50f, position[10])
Assert.assertEquals(51f, position[11])
Assert.assertEquals(50f, position[12])
Assert.assertEquals(49f, position[13])
Assert.assertEquals(51f, position[14])
Assert.assertEquals(50f, position[15])
}
}
@Test
fun testConstraintLayout_barriers_margins() = with(density) {
val size = 200.toDp()
val offset = 50.toDp()
val position = Array(2) { Offset(0f, 0f) }
composeTestRule.setContent {
ConstraintLayout(Modifier.size(size)) {
val box = createRef()
val guideline1 = createGuidelineFromAbsoluteLeft(offset)
val guideline2 = createGuidelineFromTop(offset)
Box(Modifier.size(1.toDp())
.constrainAs(box) {
absoluteLeft.linkTo(guideline1)
top.linkTo(guideline2)
}
)
val leftBarrier = createAbsoluteLeftBarrier(box, margin = 10.toDp())
val topBarrier = createTopBarrier(box, margin = 10.toDp())
val rightBarrier = createAbsoluteRightBarrier(box, margin = 10.toDp())
val bottomBarrier = createBottomBarrier(box, margin = 10.toDp())
Box(Modifier.size(1.dp)
.constrainAs(createRef()) {
absoluteLeft.linkTo(leftBarrier)
top.linkTo(topBarrier)
}.onPositioned {
position[0] = it.positionInParent
}
)
Box(Modifier.size(1.dp)
.constrainAs(createRef()) {
absoluteLeft.linkTo(rightBarrier)
top.linkTo(bottomBarrier)
}.onPositioned {
position[1] = it.positionInParent
}
)
}
}
runOnIdle {
Assert.assertEquals(Offset(60f, 60f), position[0])
Assert.assertEquals(Offset(61f, 61f), position[1])
}
}
@Test(expected = Test.None::class)
fun testConstraintLayout_inlineDSL_recompositionDoesNotCrash() = with(density) {
val first = mutableStateOf(true)
composeTestRule.setContent {
ConstraintLayout {
val box = createRef()
if (first.value) {
Box(Modifier.constrainAs(box) { })
} else {
Box(Modifier.constrainAs(box) { })
}
}
}
runOnIdle {
first.value = false
}
waitForIdle()
}
@Test(expected = Test.None::class)
fun testConstraintLayout_ConstraintSetDSL_recompositionDoesNotCrash() = with(density) {
val first = mutableStateOf(true)
composeTestRule.setContent {
ConstraintLayout(ConstraintSet2 {
val box = createRefFor("box")
constrain(box) { }
}) {
if (first.value) {
Box(Modifier.layoutId("box"))
} else {
Box(Modifier.layoutId("box"))
}
}
}
runOnIdle {
first.value = false
}
waitForIdle()
}
@Test(expected = Test.None::class)
fun testConstraintLayout_inlineDSL_remeasureDoesNotCrash() = with(density) {
val first = mutableStateOf(true)
composeTestRule.setContent {
ConstraintLayout(if (first.value) Modifier else Modifier.padding(10.dp)) {
Box(if (first.value) Modifier else Modifier.size(20.dp))
}
}
runOnIdle {
first.value = false
}
waitForIdle()
}
@Test(expected = Test.None::class)
fun testConstraintLayout_ConstraintSetDSL_remeasureDoesNotCrash() = with(density) {
val first = mutableStateOf(true)
composeTestRule.setContent {
ConstraintLayout(
modifier = if (first.value) Modifier else Modifier.padding(10.dp),
constraintSet = ConstraintSet2 { }
) {
Box(if (first.value) Modifier else Modifier.size(20.dp))
}
}
runOnIdle {
first.value = false
}
waitForIdle()
}
}