Kotlin

[Kotlin] ConstraintLayout 동적으로 제어하기

무하지 2021. 9. 13. 13:34
반응형

 

constraintlayout을 코틀린에서 런타임에 동적으로 제어해보자.

이때 binding은 뷰 바인딩 인스턴스이다.

 

  • 전체코드
val constraintLayout = binding.root
val constraintSet = ConstraintSet()
constraintSet.clone(constraintLayout)
constraintSet.connect(binding.eyes.id, ConstraintSet.TOP, binding.face.id, ConstraintSet.TOP, 200)
constraintSet.connect(binding.eyes.id, ConstraintSet.START, binding.face.id, ConstraintSet.START, 10)
constraintSet.applyTo(constraintLayout)

 

eyes를 face의 TOP으로부터 200만큼, face의 START로부터 10만큼 떨어지게 했다.

다만 코드상에서는 XML과 달리 단위가 무조건 픽셀이다. 따라서 dp로 바꿔줄 필요가 있다. 아래는 dp를 픽셀 단위로 바꿔주는 함수이다.

 

fun convertDpToPixel(dp: Float, context: Context): Int {
        return (dp * (context.resources.displayMetrics.densityDpi.toFloat() / DisplayMetrics.DENSITY_DEFAULT)).toInt()
}

 

쓰일 일이 많을 것 같아 이를 좀 더 일반화해서 함수로 만들어봤다.

private fun constraintWidget(constraintLayout: ConstraintLayout, target: Int, standard: Int, startMargin: Float, topMargin: Float) {
    val constraintSet = ConstraintSet()
    constraintSet.clone(constraintLayout)
    constraintSet.connect(target, ConstraintSet.START, standard, ConstraintSet.START, convertDpToPixel(startMargin, this))
    constraintSet.connect(target, ConstraintSet.TOP, standard, ConstraintSet.TOP, convertDpToPixel(topMargin, this))
    constraintSet.applyTo(constraintLayout)
}

private fun convertDpToPixel(dp: Float, context: Context): Int {
    return (dp * (context.resources.displayMetrics.densityDpi.toFloat() / DisplayMetrics.DENSITY_DEFAULT)).toInt()
}

 

  • 사용
constraintWidget(binding.root, binding.eyes.id, binding.face.id, 36f, 56f)

root 레이아웃에서 eyes 위젯을 face를 기준으로 start에서 36dp, top에서 56dp 마진을 갖게 제약한다.

반응형