기본적인 사용법에 이어 이번엔 chain과 barrier에 대해 알아보자!
1. Chain
constraintLayout의 기능 중 하나로 chain 기능이 있다.
이것을 compose로 구현해 보자!
ConstraintLayout(Modifier.size(60.dp)) {
val (box1, box2, box3) = createRefs()
Box(
modifier = Modifier
.size(10.dp)
.background(Color.Red)
.constrainAs(box1) {
top.linkTo(parent.top)
}
)
Box(
modifier = Modifier
.size(10.dp)
.background(Color.Yellow)
.constrainAs(box2) {
top.linkTo(parent.top)
}
)
Box(
modifier = Modifier
.size(10.dp)
.background(Color.Green)
.constrainAs(box3) {
top.linkTo(parent.top)
}
)
createHorizontalChain(box1, box2, box3)
createVerticalChain(box1, box2, box3)
}
compose에서는 createHorizontalChain, createVerticalChain을 통해 만들어줘야 한다.
그리고 ChainStyle을 지정해 그림 1과 같이 만들 수 있다.
ChainStyle의 값은 아래와 같이 있다.
@Immutable
class ChainStyle internal constructor(
internal val style: SolverChain,
internal val bias: Float? = null
) {
companion object {
/**
* A chain style that evenly distributes the contained layouts.
*/
@Stable
val Spread = ChainStyle(SolverChain.SPREAD)
/**
* A chain style where the first and last layouts are affixed to the constraints
* on each end of the chain and the rest are evenly distributed.
*/
@Stable
val SpreadInside = ChainStyle(SolverChain.SPREAD_INSIDE)
/**
* A chain style where the contained layouts are packed together and placed to the
* center of the available space.
*/
@Stable
val Packed = Packed(0.5f)
/**
* A chain style where the contained layouts are packed together and placed in
* the available space according to a given [bias].
*/
@Stable
fun Packed(bias: Float) = ChainStyle(SolverChain.PACKED, bias)
}
}
Box(
modifier = Modifier
.size(10.dp)
.background(Color.Red)
.constrainAs(box1) {
top.linkTo(parent.top)
start.linkTo(parent.start)
}
)
Box(
modifier = Modifier
.size(10.dp)
.background(Color.Yellow)
.constrainAs(box2) {
start.linkTo(box1.end)
}
)
Box(
modifier = Modifier
.size(10.dp)
.background(Color.Green)
.constrainAs(box3) {
start.linkTo(box2.start)
}
)
createHorizontalChain(box1, box2, box3, chainStyle = ChainStyle.SpreadInside)
코드 1을 위와 같이 수정하여 사용할 수 있다.
createHorizontalChain에 chainStyle을 넣어 사용한다.
2. Barrier
여러 컴포저블을 참고하여 가장 극단적인 위젯을 기반으로 가상 가이드라인을 만드는 것
createTopBarrier, createBottomBarrier, createEndBarrier, createStartBarrier를 사용
예를 들어 chain의 예시 사진 처럼 상자가 3개가 있고 top으로 부터 위치가 각각 다를 때 가장 아래의 box에 글을 추가하고 싶다면 어떻게 해야할까?
val (box1, box2, box3, text) = createRefs()
Box(
modifier = Modifier
.size(10.dp)
.background(Color.Red)
.constrainAs(box1) {
top.linkTo(parent.top)
start.linkTo(parent.start)
}
)
Box(
modifier = Modifier
.size(10.dp)
.background(Color.Yellow)
.constrainAs(box2) {
top.linkTo(parent.top, margin = 10.dp)
start.linkTo(box1.end)
}
)
Box(
modifier = Modifier
.size(10.dp)
.background(Color.Green)
.constrainAs(box3) {
top.linkTo(parent.top, margin = 20.dp)
start.linkTo(box2.start)
}
)
createHorizontalChain(box1, box2, box3, chainStyle = ChainStyle.Spread)
val barrier = createBottomBarrier(box1, box2, box3)
Text(
text = "여기가 최하단",
fontSize = 10.sp,
modifier = Modifier.constrainAs(text) {
top.linkTo(barrier)
}
)
코드 1을 이렇게 수정해보면 좌측의 사진처럼 나오게 된다.
글씨가 아래 부분에 나오기 때문에 createBottomBarrier를 통해 box1~3을 넣고 top에 각각 margin을 줘 값을 다르게 하면 가장 하단인 것을 찾아 그 아래에 barrier가 생기게 된다.
그 barrier를 Text의 top에 넣게 되면, box1~3의 위치가 변경됨에 따라 barrier의 위치도 바뀌므로 Text의 위치가 자동으로 바뀌게 된다!
이런식으로 top, start, end, bottom에 원하는 대로 barrier를 만들어 사용할 수 있다.
fun createBottomBarrier(
vararg elements: ConstrainedLayoutReference,
margin: Dp = 0.dp
): HorizontalAnchor {
val id = createHelperId()
tasks.add { state ->
state.barrier(id, SolverDirection.BOTTOM).apply {
add(*(elements.map { it.id }.toTypedArray()))
}.margin(state.convertDimension(margin))
}
updateHelpersHashCode(15)
elements.forEach { updateHelpersHashCode(it.hashCode()) }
updateHelpersHashCode(margin.hashCode())
return HorizontalAnchor(id, 0)
}
또한 Barrier에는 margin 값을 넣을 수 있기 때문에 원하는 대로 margin 값을 줄 수 있다.
val barrier = createBottomBarrier(box1, box2, box3, margin = 10.dp)
[참고 및 출처]
'개발 공부 > 안드로이드' 카테고리의 다른 글
[Compose] 컴포즈 공부하기 7 - Snackbar (0) | 2023.09.11 |
---|---|
[Compose] 컴포즈 공부하기 6 - Scaffold (0) | 2023.09.07 |
[Compose] 컴포즈 공부하기5 - ConstraintLayout 1 (0) | 2023.09.06 |
[Compose] 컴포즈 공부하기4 - Image (with painter) (0) | 2023.08.30 |
StateFlow에 대해 알아보자! (with LiveData) (0) | 2023.08.23 |