[go: nahoru, domu]

blob: 48a796eea17b6489f194fbf3092cab886222521f [file] [log] [blame]
Anastasia Soboleva75600892020-03-05 10:54:02 +00001/*
2 * Copyright 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package androidx.ui.layout.test
18
Anastasia Soboleva75600892020-03-05 10:54:02 +000019import androidx.test.filters.SmallTest
Mihai Popa73815e22019-11-19 16:26:59 +000020import androidx.ui.core.Alignment
Adam Powell999a89b2020-03-11 09:08:07 -070021import androidx.ui.core.Modifier
Anastasia Soboleva75600892020-03-05 10:54:02 +000022import androidx.ui.core.Ref
Adam Powell999a89b2020-03-11 09:08:07 -070023import androidx.ui.core.tag
Mihai Popa73815e22019-11-19 16:26:59 +000024import androidx.ui.core.globalPosition
25import androidx.ui.core.onPositioned
Mihai Popadc4c6ec2020-06-01 19:30:59 +010026import androidx.ui.core.positionInParent
Mihai Popa73815e22019-11-19 16:26:59 +000027import androidx.ui.foundation.Box
Mihai Popadc4c6ec2020-06-01 19:30:59 +010028import androidx.ui.layout.ConstrainScope
Mihai Popac9af2882020-03-16 17:55:00 +000029import androidx.ui.layout.ConstraintLayout
Mihai Popa53f4dd702020-05-27 12:57:45 +010030import androidx.ui.layout.ConstraintSet2
31import androidx.ui.layout.Dimension
Mihai Popa7d7481d2020-05-20 19:22:04 +010032import androidx.ui.layout.ExperimentalLayout
Mihai Popa73815e22019-11-19 16:26:59 +000033import androidx.ui.layout.aspectRatio
Adam Powell999a89b2020-03-11 09:08:07 -070034import androidx.ui.layout.fillMaxSize
Mihai Popa73815e22019-11-19 16:26:59 +000035import androidx.ui.layout.fillMaxWidth
Adam Powell999a89b2020-03-11 09:08:07 -070036import androidx.ui.layout.preferredSize
Mihai Popa73815e22019-11-19 16:26:59 +000037import androidx.ui.layout.preferredWidth
Adam Powell999a89b2020-03-11 09:08:07 -070038import androidx.ui.layout.rtl
Mihai Popadc4c6ec2020-06-01 19:30:59 +010039import androidx.ui.layout.size
Mihai Popa73815e22019-11-19 16:26:59 +000040import androidx.ui.layout.wrapContentSize
41import androidx.ui.test.createComposeRule
Filip Pavlis6fdb2502020-04-02 14:41:32 +010042import androidx.ui.test.runOnIdleCompose
Anastasia Soboleva75600892020-03-05 10:54:02 +000043import androidx.ui.unit.IntPxSize
44import androidx.ui.unit.PxPosition
Mihai Popa73815e22019-11-19 16:26:59 +000045import androidx.ui.unit.dp
Anastasia Soboleva75600892020-03-05 10:54:02 +000046import androidx.ui.unit.ipx
Mihai Popadc4c6ec2020-06-01 19:30:59 +010047import org.junit.Assert
Mihai Popa73815e22019-11-19 16:26:59 +000048import org.junit.Rule
Anastasia Soboleva75600892020-03-05 10:54:02 +000049import org.junit.Test
50import org.junit.runner.RunWith
51import org.junit.runners.JUnit4
Anastasia Soboleva75600892020-03-05 10:54:02 +000052
53@SmallTest
54@RunWith(JUnit4::class)
Mihai Popa7d7481d2020-05-20 19:22:04 +010055@OptIn(ExperimentalLayout::class)
Anastasia Soboleva75600892020-03-05 10:54:02 +000056class ConstraintLayoutTest : LayoutTest() {
Mihai Popa73815e22019-11-19 16:26:59 +000057 @get:Rule
58 val composeTestRule = createComposeRule()
59
60 // region sizing tests
Anastasia Soboleva75600892020-03-05 10:54:02 +000061
62 @Test
Mihai Popa73815e22019-11-19 16:26:59 +000063 fun dividerMatchTextHeight_spread() = with(density) {
64 val aspectRatioBoxSize = Ref<IntPxSize>()
65 val dividerSize = Ref<IntPxSize>()
66 composeTestRule.setContent {
67 ConstraintLayout(
68 // Make CL fixed width and wrap content height.
Mihai Popa53f4dd702020-05-27 12:57:45 +010069 modifier = Modifier.wrapContentSize(Alignment.TopStart).fillMaxWidth()
Mihai Popa73815e22019-11-19 16:26:59 +000070 ) {
Mihai Popa53f4dd702020-05-27 12:57:45 +010071 val (aspectRatioBox, divider) = createRefs()
Mihai Popadc4c6ec2020-06-01 19:30:59 +010072 val guideline = createGuidelineFromAbsoluteLeft(0.5f)
Mihai Popa53f4dd702020-05-27 12:57:45 +010073
74 Box(Modifier
75 .constrainAs(aspectRatioBox) {
76 centerTo(parent)
77 start.linkTo(guideline)
78 width = Dimension.preferredWrapContent
79 height = Dimension.wrapContent
80 }
Mihai Popa73815e22019-11-19 16:26:59 +000081 // Try to be large to make wrap content impossible.
82 .preferredWidth((composeTestRule.displayMetrics.widthPixels).ipx.toDp())
83 // This could be any (width in height out child) e.g. text
84 .aspectRatio(2f)
85 .onPositioned { coordinates ->
86 aspectRatioBoxSize.value = coordinates.size
87 }
88 )
Mihai Popa53f4dd702020-05-27 12:57:45 +010089 Box(Modifier
90 .constrainAs(divider) {
91 centerTo(parent)
92 width = Dimension.value(1.dp)
93 height = Dimension.fillToConstraints
94 }.onPositioned { coordinates ->
Mihai Popa73815e22019-11-19 16:26:59 +000095 dividerSize.value = coordinates.size
96 }
97 )
98 }
Anastasia Soboleva75600892020-03-05 10:54:02 +000099 }
100
Filip Pavlis6fdb2502020-04-02 14:41:32 +0100101 runOnIdleCompose {
Mihai Popa73815e22019-11-19 16:26:59 +0000102 // The aspect ratio could not wrap and it is wrap suggested, so it respects constraints.
103 assertEquals(
104 (composeTestRule.displayMetrics.widthPixels / 2).ipx,
105 aspectRatioBoxSize.value!!.width
106 )
107 // Aspect ratio is preserved.
108 assertEquals(
109 (composeTestRule.displayMetrics.widthPixels / 2 / 2).ipx,
110 aspectRatioBoxSize.value!!.height
111 )
112 // Divider has fixed width 1.dp in constraint set.
113 assertEquals(1.dp.toIntPx(), dividerSize.value!!.width)
114 // Divider has spread height so it should spread to fill the height of the CL,
115 // which in turns is given by the size of the aspect ratio box.
116 assertEquals(aspectRatioBoxSize.value!!.height, dividerSize.value!!.height)
117 }
Anastasia Soboleva75600892020-03-05 10:54:02 +0000118 }
119
120 @Test
Mihai Popa73815e22019-11-19 16:26:59 +0000121 fun dividerMatchTextHeight_percent() = with(density) {
122 val aspectRatioBoxSize = Ref<IntPxSize>()
123 val dividerSize = Ref<IntPxSize>()
124 composeTestRule.setContent {
125 ConstraintLayout(
126 // Make CL fixed width and wrap content height.
Mihai Popa53f4dd702020-05-27 12:57:45 +0100127 modifier = Modifier.wrapContentSize(Alignment.TopStart).fillMaxWidth()
Mihai Popa73815e22019-11-19 16:26:59 +0000128 ) {
Mihai Popa53f4dd702020-05-27 12:57:45 +0100129 val (aspectRatioBox, divider) = createRefs()
Mihai Popadc4c6ec2020-06-01 19:30:59 +0100130 val guideline = createGuidelineFromAbsoluteLeft(0.5f)
Mihai Popa53f4dd702020-05-27 12:57:45 +0100131
132 Box(Modifier
133 .constrainAs(aspectRatioBox) {
134 centerTo(parent)
135 start.linkTo(guideline)
136 width = Dimension.preferredWrapContent
137 height = Dimension.wrapContent
138 }
Mihai Popa73815e22019-11-19 16:26:59 +0000139 // Try to be large to make wrap content impossible.
140 .preferredWidth((composeTestRule.displayMetrics.widthPixels).ipx.toDp())
141 // This could be any (width in height out child) e.g. text
142 .aspectRatio(2f)
143 .onPositioned { coordinates ->
144 aspectRatioBoxSize.value = coordinates.size
145 }
146 )
Mihai Popa53f4dd702020-05-27 12:57:45 +0100147 Box(Modifier
148 .constrainAs(divider) {
149 centerTo(parent)
150 width = Dimension.value(1.dp)
151 height = Dimension.percent(0.8f)
152 }
Mihai Popa73815e22019-11-19 16:26:59 +0000153 .onPositioned { coordinates ->
154 dividerSize.value = coordinates.size
155 }
156 )
157 }
158 }
159
Filip Pavlis6fdb2502020-04-02 14:41:32 +0100160 runOnIdleCompose {
Mihai Popa73815e22019-11-19 16:26:59 +0000161 // The aspect ratio could not wrap and it is wrap suggested, so it respects constraints.
162 assertEquals(
163 (composeTestRule.displayMetrics.widthPixels / 2).ipx,
164 aspectRatioBoxSize.value!!.width
165 )
166 // Aspect ratio is preserved.
167 assertEquals(
168 (composeTestRule.displayMetrics.widthPixels / 2 / 2).ipx,
169 aspectRatioBoxSize.value!!.height
170 )
171 // Divider has fixed width 1.dp in constraint set.
172 assertEquals(1.dp.toIntPx(), dividerSize.value!!.width)
173 // Divider has percent height so it should spread to fill 0.8 of the height of the CL,
174 // which in turns is given by the size of the aspect ratio box.
Mihai Popa73815e22019-11-19 16:26:59 +0000175 assertEquals(aspectRatioBoxSize.value!!.height * 0.8f, dividerSize.value!!.height)
176 }
177 }
178
179 @Test
Mihai Popa73815e22019-11-19 16:26:59 +0000180 fun dividerMatchTextHeight_inWrapConstraintLayout_longText() = with(density) {
181 val aspectRatioBoxSize = Ref<IntPxSize>()
182 val dividerSize = Ref<IntPxSize>()
183 composeTestRule.setContent {
184 ConstraintLayout(
185 // Make CL wrap width and height.
Mihai Popa53f4dd702020-05-27 12:57:45 +0100186 modifier = Modifier.wrapContentSize(Alignment.TopStart)
Mihai Popa73815e22019-11-19 16:26:59 +0000187 ) {
Mihai Popa53f4dd702020-05-27 12:57:45 +0100188 val (aspectRatioBox, divider) = createRefs()
Mihai Popadc4c6ec2020-06-01 19:30:59 +0100189 val guideline = createGuidelineFromAbsoluteLeft(0.5f)
Mihai Popa53f4dd702020-05-27 12:57:45 +0100190
191 Box(Modifier
192 .constrainAs(aspectRatioBox) {
193 centerTo(parent)
194 start.linkTo(guideline)
195 width = Dimension.preferredWrapContent
196 height = Dimension.wrapContent
197 }
Mihai Popa73815e22019-11-19 16:26:59 +0000198 // Try to be large to make wrap content impossible.
199 .preferredWidth((composeTestRule.displayMetrics.widthPixels).ipx.toDp())
200 // This could be any (width in height out child) e.g. text
201 .aspectRatio(2f)
202 .onPositioned { coordinates ->
203 aspectRatioBoxSize.value = coordinates.size
204 }
205 )
Mihai Popa53f4dd702020-05-27 12:57:45 +0100206 Box(Modifier
207 .constrainAs(divider) {
208 centerTo(parent)
209 width = Dimension.value(1.dp)
210 height = Dimension.percent(0.8f)
211 }
Mihai Popa73815e22019-11-19 16:26:59 +0000212 .onPositioned { coordinates ->
213 dividerSize.value = coordinates.size
214 }
215 )
216 }
217 }
218
Filip Pavlis6fdb2502020-04-02 14:41:32 +0100219 runOnIdleCompose {
Mihai Popa73815e22019-11-19 16:26:59 +0000220 // The aspect ratio could not wrap and it is wrap suggested, so it respects constraints.
221 assertEquals(
222 (composeTestRule.displayMetrics.widthPixels / 2).ipx,
223 aspectRatioBoxSize.value!!.width
224 )
225 // Aspect ratio is preserved.
226 assertEquals(
227 (composeTestRule.displayMetrics.widthPixels / 2 / 2).ipx,
228 aspectRatioBoxSize.value!!.height
229 )
230 // Divider has fixed width 1.dp in constraint set.
231 assertEquals(1.dp.toIntPx(), dividerSize.value!!.width)
232 // Divider has percent height so it should spread to fill 0.8 of the height of the CL,
233 // which in turns is given by the size of the aspect ratio box.
234 // TODO(popam; b/150277566): uncomment
235 assertEquals(aspectRatioBoxSize.value!!.height * 0.8f, dividerSize.value!!.height)
236 }
237 }
238
239 @Test
Mihai Popa73815e22019-11-19 16:26:59 +0000240 fun dividerMatchTextHeight_inWrapConstraintLayout_shortText() = with(density) {
241 val constraintLayoutSize = Ref<IntPxSize>()
242 val aspectRatioBoxSize = Ref<IntPxSize>()
243 val dividerSize = Ref<IntPxSize>()
244 val size = 40.ipx.toDp()
245 composeTestRule.setContent {
246 ConstraintLayout(
247 // Make CL wrap width and height.
248 modifier = Modifier.wrapContentSize(Alignment.TopStart).onPositioned {
249 constraintLayoutSize.value = it.size
Mihai Popa73815e22019-11-19 16:26:59 +0000250 }
251 ) {
Mihai Popa53f4dd702020-05-27 12:57:45 +0100252 val (aspectRatioBox, divider) = createRefs()
Mihai Popadc4c6ec2020-06-01 19:30:59 +0100253 val guideline = createGuidelineFromAbsoluteLeft(0.5f)
Mihai Popa53f4dd702020-05-27 12:57:45 +0100254
255 Box(Modifier
256 .constrainAs(aspectRatioBox) {
257 centerTo(parent)
258 start.linkTo(guideline)
259 width = Dimension.preferredWrapContent
260 height = Dimension.wrapContent
261 }
262 // Small width for the CL to wrap it.
Mihai Popa73815e22019-11-19 16:26:59 +0000263 .preferredWidth(size)
Mihai Popa53f4dd702020-05-27 12:57:45 +0100264 // This could be any (width in height out child) e.g. text
Mihai Popa73815e22019-11-19 16:26:59 +0000265 .aspectRatio(2f)
266 .onPositioned { coordinates ->
267 aspectRatioBoxSize.value = coordinates.size
268 }
269 )
Mihai Popa53f4dd702020-05-27 12:57:45 +0100270 Box(Modifier
271 .constrainAs(divider) {
272 centerTo(parent)
273 width = Dimension.value(1.dp)
274 height = Dimension.fillToConstraints
275 }
Mihai Popa73815e22019-11-19 16:26:59 +0000276 .onPositioned { coordinates ->
277 dividerSize.value = coordinates.size
278 }
279 )
280 }
281 }
282
Filip Pavlis6fdb2502020-04-02 14:41:32 +0100283 runOnIdleCompose {
Mihai Popa73815e22019-11-19 16:26:59 +0000284 // The width of the ConstraintLayout should be twice the width of the aspect ratio box.
285 assertEquals(size.toIntPx() * 2, constraintLayoutSize.value!!.width)
286 // The height of the ConstraintLayout should be the height of the aspect ratio box.
287 assertEquals(size.toIntPx() / 2, constraintLayoutSize.value!!.height)
288 // The aspect ratio gets the requested size.
289 assertEquals(size.toIntPx(), aspectRatioBoxSize.value!!.width)
290 // Aspect ratio is preserved.
291 assertEquals(size.toIntPx() / 2, aspectRatioBoxSize.value!!.height)
292 // Divider has fixed width 1.dp in constraint set.
293 assertEquals(1.dp.toIntPx(), dividerSize.value!!.width)
294 // Divider should have the height of the aspect ratio box.
295 assertEquals(aspectRatioBoxSize.value!!.height, dividerSize.value!!.height)
296 }
297 }
298
299 // endregion
300
301 // region positioning tests
302
303 @Test
Mihai Popa53f4dd702020-05-27 12:57:45 +0100304 fun testConstraintLayout_withInlineDSL() = with(density) {
Mihai Popa73815e22019-11-19 16:26:59 +0000305 val boxSize = 100.ipx
306 val offset = 150.ipx
307
Anastasia Soboleva75600892020-03-05 10:54:02 +0000308 val position = Array(3) { Ref<PxPosition>() }
Anastasia Soboleva75600892020-03-05 10:54:02 +0000309
Mihai Popa73815e22019-11-19 16:26:59 +0000310 composeTestRule.setContent {
Mihai Popa53f4dd702020-05-27 12:57:45 +0100311 ConstraintLayout(Modifier.fillMaxSize()) {
312 val (box0, box1, box2) = createRefs()
313 Box(Modifier
314 .constrainAs(box0) {
315 centerTo(parent)
316 }
317 .preferredSize(boxSize.toDp(), boxSize.toDp())
318 .onPositioned {
319 position[0].value = it.globalPosition
320 }
321 )
Mihai Popa8f136d62020-06-03 22:51:18 +0100322 val half = createGuidelineFromAbsoluteLeft(fraction = 0.5f)
Mihai Popa53f4dd702020-05-27 12:57:45 +0100323 Box(Modifier
324 .constrainAs(box1) {
325 start.linkTo(half, margin = offset.toDp())
326 bottom.linkTo(box0.top)
327 }
328 .preferredSize(boxSize.toDp(), boxSize.toDp())
329 .onPositioned {
330 position[1].value = it.globalPosition
331 }
332 )
333 Box(Modifier
334 .constrainAs(box2) {
335 start.linkTo(parent.start, margin = offset.toDp())
336 bottom.linkTo(parent.bottom, margin = offset.toDp())
337 }
338 .preferredSize(boxSize.toDp(), boxSize.toDp())
339 .onPositioned {
340 position[2].value = it.globalPosition
341 }
342 )
343 }
344 }
Mihai Popa73815e22019-11-19 16:26:59 +0000345
Mihai Popa53f4dd702020-05-27 12:57:45 +0100346 val displayWidth = composeTestRule.displayMetrics.widthPixels.ipx
347 val displayHeight = composeTestRule.displayMetrics.heightPixels.ipx
Mihai Popa73815e22019-11-19 16:26:59 +0000348
Mihai Popa53f4dd702020-05-27 12:57:45 +0100349 runOnIdleCompose {
350 assertEquals(
351 PxPosition((displayWidth - boxSize) / 2, (displayHeight - boxSize) / 2),
352 position[0].value
353 )
354 assertEquals(
355 PxPosition(displayWidth / 2 + offset, (displayHeight - boxSize) / 2 - boxSize),
356 position[1].value
357 )
358 assertEquals(
359 PxPosition(offset, displayHeight - boxSize - offset),
360 position[2].value
361 )
362 }
363 }
364
365 @Test
366 fun testConstraintLayout_withConstraintSet() = with(density) {
367 val boxSize = 100.ipx
368 val offset = 150.ipx
369
370 val position = Array(3) { Ref<PxPosition>() }
371
372 composeTestRule.setContent {
373 ConstraintLayout(
374 ConstraintSet2 {
375 val box0 = createRefFor("box0")
376 val box1 = createRefFor("box1")
377 val box2 = createRefFor("box2")
378
379 constrain(box0) {
380 centerTo(parent)
Mihai Popa73815e22019-11-19 16:26:59 +0000381 }
382
Mihai Popa8f136d62020-06-03 22:51:18 +0100383 val half = createGuidelineFromAbsoluteLeft(fraction = 0.5f)
Mihai Popa53f4dd702020-05-27 12:57:45 +0100384 constrain(box1) {
385 start.linkTo(half, margin = offset.toDp())
386 bottom.linkTo(box0.top)
387 }
388
389 constrain(box2) {
390 start.linkTo(parent.start, margin = offset.toDp())
391 bottom.linkTo(parent.bottom, margin = offset.toDp())
Mihai Popa73815e22019-11-19 16:26:59 +0000392 }
Andrey Kulikov1526ea52020-04-07 18:43:27 +0100393 },
394 Modifier.fillMaxSize()
Mihai Popa73815e22019-11-19 16:26:59 +0000395 ) {
396 for (i in 0..2) {
397 Box(Modifier.tag("box$i").preferredSize(boxSize.toDp(), boxSize.toDp())
398 .onPositioned {
399 position[i].value = it.globalPosition
400 }
401 )
402 }
Anastasia Soboleva75600892020-03-05 10:54:02 +0000403 }
404 }
405
Mihai Popa73815e22019-11-19 16:26:59 +0000406 val displayWidth = composeTestRule.displayMetrics.widthPixels.ipx
407 val displayHeight = composeTestRule.displayMetrics.heightPixels.ipx
Anastasia Soboleva75600892020-03-05 10:54:02 +0000408
Filip Pavlis6fdb2502020-04-02 14:41:32 +0100409 runOnIdleCompose {
Mihai Popa73815e22019-11-19 16:26:59 +0000410 assertEquals(
411 PxPosition((displayWidth - boxSize) / 2, (displayHeight - boxSize) / 2),
412 position[0].value
413 )
414 assertEquals(
415 PxPosition(displayWidth / 2 + offset, (displayHeight - boxSize) / 2 - boxSize),
416 position[1].value
417 )
418 assertEquals(
419 PxPosition(offset, displayHeight - boxSize - offset),
420 position[2].value
421 )
Anastasia Soboleva75600892020-03-05 10:54:02 +0000422 }
423 }
Mihai Popa73815e22019-11-19 16:26:59 +0000424
425 @Test
426 fun testConstraintLayout_rtl() = with(density) {
427 val boxSize = 100.ipx
428 val offset = 150.ipx
429
430 val position = Array(3) { Ref<PxPosition>() }
431
432 composeTestRule.setContent {
Mihai Popa53f4dd702020-05-27 12:57:45 +0100433 ConstraintLayout(Modifier.rtl.fillMaxSize()) {
434 val (box0, box1, box2) = createRefs()
435 Box(Modifier
436 .constrainAs(box0) {
437 centerTo(parent)
Mihai Popa73815e22019-11-19 16:26:59 +0000438 }
Mihai Popa53f4dd702020-05-27 12:57:45 +0100439 .preferredSize(boxSize.toDp(), boxSize.toDp())
440 .onPositioned {
441 position[0].value = it.globalPosition
Mihai Popa73815e22019-11-19 16:26:59 +0000442 }
Mihai Popa53f4dd702020-05-27 12:57:45 +0100443 )
Mihai Popa8f136d62020-06-03 22:51:18 +0100444 val half = createGuidelineFromAbsoluteLeft(fraction = 0.5f)
Mihai Popa53f4dd702020-05-27 12:57:45 +0100445 Box(Modifier
446 .constrainAs(box1) {
447 start.linkTo(half, margin = offset.toDp())
448 bottom.linkTo(box0.top)
449 }
450 .preferredSize(boxSize.toDp(), boxSize.toDp())
451 .onPositioned {
452 position[1].value = it.globalPosition
453 }
454 )
455 Box(Modifier
456 .constrainAs(box2) {
457 start.linkTo(parent.start, margin = offset.toDp())
458 bottom.linkTo(parent.bottom, margin = offset.toDp())
459 }
460 .preferredSize(boxSize.toDp(), boxSize.toDp())
461 .onPositioned {
462 position[2].value = it.globalPosition
463 }
464 )
Mihai Popa73815e22019-11-19 16:26:59 +0000465 }
466 }
467
468 val displayWidth = composeTestRule.displayMetrics.widthPixels.ipx
469 val displayHeight = composeTestRule.displayMetrics.heightPixels.ipx
470
Filip Pavlis6fdb2502020-04-02 14:41:32 +0100471 runOnIdleCompose {
Mihai Popa73815e22019-11-19 16:26:59 +0000472 assertEquals(
473 PxPosition((displayWidth - boxSize) / 2, (displayHeight - boxSize) / 2),
474 position[0].value
475 )
476 assertEquals(
477 PxPosition(
478 displayWidth / 2 - offset - boxSize,
479 (displayHeight - boxSize) / 2 - boxSize
480 ),
481 position[1].value
482 )
483 assertEquals(
484 PxPosition(displayWidth - offset - boxSize, displayHeight - boxSize - offset),
485 position[2].value
486 )
487 }
488 }
Mihai Popadc4c6ec2020-06-01 19:30:59 +0100489
490 @Test
491 fun testConstraintLayout_helpers_ltr() = with(density) {
492 val size = 200.ipx.toDp()
493 val offset = 50.ipx.toDp()
494
495 val position = Array(8) { 0f }
496 composeTestRule.setContent {
497 ConstraintLayout(Modifier.size(size)) {
498 val guidelines = arrayOf(
499 createGuidelineFromStart(offset),
500 createGuidelineFromAbsoluteLeft(offset),
501 createGuidelineFromEnd(offset),
502 createGuidelineFromAbsoluteRight(offset),
503 createGuidelineFromStart(0.25f),
504 createGuidelineFromAbsoluteLeft(0.25f),
505 createGuidelineFromEnd(0.25f),
506 createGuidelineFromAbsoluteRight(0.25f)
507 )
508
509 guidelines.forEachIndexed { index, guideline ->
510 val ref = createRef()
511 Box(Modifier.size(1.dp)
512 .constrainAs(ref) {
513 absoluteLeft.linkTo(guideline)
514 }.onPositioned {
515 position[index] = it.positionInParent.x
516 }
517 )
518 }
519 }
520 }
521
522 runOnIdleCompose {
523 Assert.assertEquals(50f, position[0])
524 Assert.assertEquals(50f, position[1])
525 Assert.assertEquals(150f, position[2])
526 Assert.assertEquals(150f, position[3])
527 Assert.assertEquals(50f, position[4])
528 Assert.assertEquals(50f, position[5])
529 Assert.assertEquals(150f, position[6])
530 Assert.assertEquals(150f, position[7])
531 }
532 }
533
534 @Test
535 fun testConstraintLayout_helpers_rtl() = with(density) {
536 val size = 200.ipx.toDp()
537 val offset = 50.ipx.toDp()
538
539 val position = Array(8) { 0f }
540 composeTestRule.setContent {
541 ConstraintLayout(Modifier.size(size).rtl) {
542 val guidelines = arrayOf(
543 createGuidelineFromStart(offset),
544 createGuidelineFromAbsoluteLeft(offset),
545 createGuidelineFromEnd(offset),
546 createGuidelineFromAbsoluteRight(offset),
547 createGuidelineFromStart(0.25f),
548 createGuidelineFromAbsoluteLeft(0.25f),
549 createGuidelineFromEnd(0.25f),
550 createGuidelineFromAbsoluteRight(0.25f)
551 )
552
553 guidelines.forEachIndexed { index, guideline ->
554 val ref = createRef()
555 Box(Modifier.size(1.dp)
556 .constrainAs(ref) {
557 absoluteLeft.linkTo(guideline)
558 }.onPositioned {
559 position[index] = it.positionInParent.x
560 }
561 )
562 }
563 }
564 }
565
566 runOnIdleCompose {
567 Assert.assertEquals(150f, position[0])
568 Assert.assertEquals(50f, position[1])
569 Assert.assertEquals(50f, position[2])
570 Assert.assertEquals(150f, position[3])
571 Assert.assertEquals(150f, position[4])
572 Assert.assertEquals(50f, position[5])
573 Assert.assertEquals(50f, position[6])
574 Assert.assertEquals(150f, position[7])
575 }
576 }
577
578 @Test
579 fun testConstraintLayout_barriers_ltr() = with(density) {
580 val size = 200.ipx.toDp()
581 val offset = 50.ipx.toDp()
582
583 val position = Array(4) { 0f }
584 composeTestRule.setContent {
585 ConstraintLayout(Modifier.size(size)) {
586 val (box1, box2) = createRefs()
587 val guideline1 = createGuidelineFromAbsoluteLeft(offset)
588 val guideline2 = createGuidelineFromAbsoluteRight(offset)
589 Box(Modifier.size(1.ipx.toDp())
590 .constrainAs(box1) {
591 absoluteLeft.linkTo(guideline1)
592 }
593 )
594 Box(Modifier.size(1.ipx.toDp())
595 .constrainAs(box2) {
596 absoluteLeft.linkTo(guideline2)
597 }
598 )
599
600 val barriers = arrayOf(
601 createStartBarrier(box1, box2),
602 createAbsoluteLeftBarrier(box1, box2),
603 createEndBarrier(box1, box2),
604 createAbsoluteRightBarrier(box1, box2)
605 )
606
607 barriers.forEachIndexed { index, barrier ->
608 val ref = createRef()
609 Box(Modifier.size(1.dp)
610 .constrainAs(ref) {
611 absoluteLeft.linkTo(barrier)
612 }.onPositioned {
613 position[index] = it.positionInParent.x
614 }
615 )
616 }
617 }
618 }
619
620 runOnIdleCompose {
621 Assert.assertEquals(50f, position[0])
622 Assert.assertEquals(50f, position[1])
623 Assert.assertEquals(151f, position[2])
624 Assert.assertEquals(151f, position[3])
625 }
626 }
627
628 @Test
629 fun testConstraintLayout_barriers_rtl() = with(density) {
630 val size = 200.ipx.toDp()
631 val offset = 50.ipx.toDp()
632
633 val position = Array(4) { 0f }
634 composeTestRule.setContent {
635 ConstraintLayout(Modifier.size(size).rtl) {
636 val (box1, box2) = createRefs()
637 val guideline1 = createGuidelineFromAbsoluteLeft(offset)
638 val guideline2 = createGuidelineFromAbsoluteRight(offset)
639 Box(Modifier.size(1.ipx.toDp())
640 .constrainAs(box1) {
641 absoluteLeft.linkTo(guideline1)
642 }
643 )
644 Box(Modifier.size(1.ipx.toDp())
645 .constrainAs(box2) {
646 absoluteLeft.linkTo(guideline2)
647 }
648 )
649
650 val barriers = arrayOf(
651 createStartBarrier(box1, box2),
652 createAbsoluteLeftBarrier(box1, box2),
653 createEndBarrier(box1, box2),
654 createAbsoluteRightBarrier(box1, box2)
655 )
656
657 barriers.forEachIndexed { index, barrier ->
658 val ref = createRef()
659 Box(Modifier.size(1.dp)
660 .constrainAs(ref) {
661 absoluteLeft.linkTo(barrier)
662 }.onPositioned {
663 position[index] = it.positionInParent.x
664 }
665 )
666 }
667 }
668 }
669
670 runOnIdleCompose {
671 Assert.assertEquals(151f, position[0])
672 Assert.assertEquals(50f, position[1])
673 Assert.assertEquals(50f, position[2])
674 Assert.assertEquals(151f, position[3])
675 }
676 }
677
678 @Test
679 fun testConstraintLayout_anchors_ltr() = with(density) {
680 val size = 200.ipx.toDp()
681 val offset = 50.ipx.toDp()
682
683 val position = Array(16) { 0f }
684 composeTestRule.setContent {
685 ConstraintLayout(Modifier.size(size)) {
686 val box = createRef()
687 val guideline = createGuidelineFromAbsoluteLeft(offset)
688 Box(Modifier.size(1.ipx.toDp())
689 .constrainAs(box) {
690 absoluteLeft.linkTo(guideline)
691 }
692 )
693
694 val anchors = listOf<ConstrainScope.() -> Unit>(
695 { start.linkTo(box.start) },
696 { absoluteLeft.linkTo(box.start) },
697 { start.linkTo(box.absoluteLeft) },
698 { absoluteLeft.linkTo(box.absoluteLeft) },
699 { end.linkTo(box.start) },
700 { absoluteRight.linkTo(box.start) },
701 { end.linkTo(box.absoluteLeft) },
702 { absoluteRight.linkTo(box.absoluteLeft) },
703 { start.linkTo(box.end) },
704 { absoluteLeft.linkTo(box.end) },
705 { start.linkTo(box.absoluteRight) },
706 { absoluteLeft.linkTo(box.absoluteRight) },
707 { end.linkTo(box.end) },
708 { absoluteRight.linkTo(box.end) },
709 { end.linkTo(box.absoluteRight) },
710 { absoluteRight.linkTo(box.absoluteRight) }
711 )
712
713 anchors.forEachIndexed { index, anchor ->
714 val ref = createRef()
715 Box(Modifier.size(1.ipx.toDp())
716 .constrainAs(ref) {
717 anchor()
718 }.onPositioned {
719 position[index] = it.positionInParent.x
720 }
721 )
722 }
723 }
724 }
725
726 runOnIdleCompose {
727 Assert.assertEquals(50f, position[0])
728 Assert.assertEquals(50f, position[1])
729 Assert.assertEquals(50f, position[2])
730 Assert.assertEquals(50f, position[3])
731 Assert.assertEquals(49f, position[4])
732 Assert.assertEquals(49f, position[5])
733 Assert.assertEquals(49f, position[6])
734 Assert.assertEquals(49f, position[7])
735 Assert.assertEquals(51f, position[8])
736 Assert.assertEquals(51f, position[9])
737 Assert.assertEquals(51f, position[10])
738 Assert.assertEquals(51f, position[11])
739 Assert.assertEquals(50f, position[12])
740 Assert.assertEquals(50f, position[13])
741 Assert.assertEquals(50f, position[14])
742 Assert.assertEquals(50f, position[15])
743 }
744 }
745
746 @Test
747 fun testConstraintLayout_anchors_rtl() = with(density) {
748 val size = 200.ipx.toDp()
749 val offset = 50.ipx.toDp()
750
751 val position = Array(16) { 0f }
752 composeTestRule.setContent {
753 ConstraintLayout(Modifier.size(size).rtl) {
754 val box = createRef()
755 val guideline = createGuidelineFromAbsoluteLeft(offset)
756 Box(Modifier.size(1.ipx.toDp())
757 .constrainAs(box) {
758 absoluteLeft.linkTo(guideline)
759 }
760 )
761
762 val anchors = listOf<ConstrainScope.() -> Unit>(
763 { start.linkTo(box.start) },
764 { absoluteLeft.linkTo(box.start) },
765 { start.linkTo(box.absoluteLeft) },
766 { absoluteLeft.linkTo(box.absoluteLeft) },
767 { end.linkTo(box.start) },
768 { absoluteRight.linkTo(box.start) },
769 { end.linkTo(box.absoluteLeft) },
770 { absoluteRight.linkTo(box.absoluteLeft) },
771 { start.linkTo(box.end) },
772 { absoluteLeft.linkTo(box.end) },
773 { start.linkTo(box.absoluteRight) },
774 { absoluteLeft.linkTo(box.absoluteRight) },
775 { end.linkTo(box.end) },
776 { absoluteRight.linkTo(box.end) },
777 { end.linkTo(box.absoluteRight) },
778 { absoluteRight.linkTo(box.absoluteRight) }
779 )
780
781 anchors.forEachIndexed { index, anchor ->
782 val ref = createRef()
783 Box(Modifier.size(1.ipx.toDp())
784 .constrainAs(ref) {
785 anchor()
786 }.onPositioned {
787 position[index] = it.positionInParent.x
788 }
789 )
790 }
791 }
792 }
793
794 runOnIdleCompose {
795 Assert.assertEquals(50f, position[0])
796 Assert.assertEquals(51f, position[1])
797 Assert.assertEquals(49f, position[2])
798 Assert.assertEquals(50f, position[3])
799 Assert.assertEquals(51f, position[4])
800 Assert.assertEquals(50f, position[5])
801 Assert.assertEquals(50f, position[6])
802 Assert.assertEquals(49f, position[7])
803 Assert.assertEquals(49f, position[8])
804 Assert.assertEquals(50f, position[9])
805 Assert.assertEquals(50f, position[10])
806 Assert.assertEquals(51f, position[11])
807 Assert.assertEquals(50f, position[12])
808 Assert.assertEquals(49f, position[13])
809 Assert.assertEquals(51f, position[14])
810 Assert.assertEquals(50f, position[15])
811 }
812 }
Mihai Popaa11cfa22020-06-03 22:21:11 +0100813
814 @Test
815 fun testConstraintLayout_barriers_margins() = with(density) {
816 val size = 200.ipx.toDp()
817 val offset = 50.ipx.toDp()
818
819 val position = Array(2) { PxPosition(0f, 0f) }
820 composeTestRule.setContent {
821 ConstraintLayout(Modifier.size(size)) {
822 val box = createRef()
823 val guideline1 = createGuidelineFromAbsoluteLeft(offset)
824 val guideline2 = createGuidelineFromTop(offset)
825 Box(Modifier.size(1.ipx.toDp())
826 .constrainAs(box) {
827 absoluteLeft.linkTo(guideline1)
828 top.linkTo(guideline2)
829 }
830 )
831
832 val leftBarrier = createAbsoluteLeftBarrier(box, margin = 10.ipx.toDp())
833 val topBarrier = createTopBarrier(box, margin = 10.ipx.toDp())
834 val rightBarrier = createAbsoluteRightBarrier(box, margin = 10.ipx.toDp())
835 val bottomBarrier = createBottomBarrier(box, margin = 10.ipx.toDp())
836
837 Box(Modifier.size(1.dp)
838 .constrainAs(createRef()) {
839 absoluteLeft.linkTo(leftBarrier)
840 top.linkTo(topBarrier)
841 }.onPositioned {
842 position[0] = it.positionInParent
843 }
844 )
845
846 Box(Modifier.size(1.dp)
847 .constrainAs(createRef()) {
848 absoluteLeft.linkTo(rightBarrier)
849 top.linkTo(bottomBarrier)
850 }.onPositioned {
851 position[1] = it.positionInParent
852 }
853 )
854 }
855 }
856
857 runOnIdleCompose {
858 Assert.assertEquals(PxPosition(60f, 60f), position[0])
859 Assert.assertEquals(PxPosition(61f, 61f), position[1])
860 }
861 }
Mihai Popa73815e22019-11-19 16:26:59 +0000862}