개발일지

Android in A..Z - View (CustomViewGroup) 본문

Android (안드로이드)/View

Android in A..Z - View (CustomViewGroup)

강태종 2021. 4. 30. 03:36

CustomeViewGroup

Android에서 기본으로 제공하는 ViewGroup(Layout) 대신 ViewGroup을 상속받아 UI를 구축할 수 있다.


OverlapLayout 전체코드

class OverlapLayout @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0, defStyleRes: Int = 0) : ViewGroup(context, attrs, defStyleAttr, defStyleRes) {
    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        var width = 0
        var height = 0
        measureChildren(widthMeasureSpec, heightMeasureSpec)
        for (i in 0 until childCount) {
            if (i == childCount - 1) {
                width += get(i).measuredWidth
                height += get(i).measuredHeight
            } else {
                width += get(i).measuredWidth / 2
                height += get(i).measuredHeight / 2
            }
        }

        val w = if (MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY) {
            MeasureSpec.getSize(widthMeasureSpec)
        } else {
            width
        }

        val h = if (MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY) {
            MeasureSpec.getSize(widthMeasureSpec)
        } else {
            height
        }

        setMeasuredDimension(w, h)
    }

    override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
        var left = 0
        var top = 0
        for (view in children) {
            view.layout(left, top, left + view.measuredWidth, top + view.measuredHeight)

            left += view.measuredWidth / 2
            top += view.measuredHeight / 2
        }
    }
}

onMeasure

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        var width = 0
        var height = 0
        measureChildren(widthMeasureSpec, heightMeasureSpec)
        for (i in 0 until childCount) {
            if (i == childCount - 1) {
                width += get(i).measuredWidth
                height += get(i).measuredHeight
            } else {
                width += get(i).measuredWidth / 2
                height += get(i).measuredHeight / 2
            }
        }

        val w = if (MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY) {
            MeasureSpec.getSize(widthMeasureSpec)
        } else {
            width
        }

        val h = if (MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY) {
            MeasureSpec.getSize(widthMeasureSpec)
        } else {
            height
        }

        setMeasuredDimension(w, h)
    }

ViewGroup은 ChildView의 크기를 계산해서 자신의 크기를 측정해야한다. ChildView가 있는 View가 그려지는 과정은 전위순회 방식이기 때문에 measurChildren을 통해 ChildView의 크기를 측정(각 View마다 measure로 개별적인 MeasureSpec으로 측정할 수도 있다.)하고 자신의 크기를 측정한다.


onLayout

    override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
        var left = 0
        var top = 0
        for (view in children) {
            view.layout(left, top, left + view.measuredWidth, top + view.measuredHeight)

            left += view.measuredWidth / 2
            top += view.measuredHeight / 2
        }
    }

onLayout은 View의 위치를 정하는 함수로 ChildView의 위치를 계산하여 layout 함수를 호출해준다.

* 매개변수로 넘어오는 l, t, r, b는 절대위치 값이다.


XML

            <com.taetae98.customview.view.OverlapLayout
                android:id="@+id/overlap"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">
                <ImageView
                    android:adjustViewBounds="true"
                    android:src="@drawable/dog"
                    android:layout_width="100dp"
                    android:layout_height="wrap_content" />
                <ImageView
                    android:adjustViewBounds="true"
                    android:src="@drawable/cat"
                    android:layout_width="100dp"
                    android:layout_height="wrap_content" />
                <ImageView
                    android:src="@drawable/bird"
                    android:adjustViewBounds="true"
                    android:layout_width="100dp"
                    android:layout_height="wrap_content" />
            </com.taetae98.customview.view.OverlapLayout>

Git (예제코드)

github.com/KangTaeJong98/Example/tree/main/Android/CustomView

 

KangTaeJong98/Example

My Example Code. Contribute to KangTaeJong98/Example development by creating an account on GitHub.

github.com

 

Comments