[Android] CustomView Ep.0 - View는 어떻게 그려지는가

김병수·2022년 8월 10일
0

CustomView

목록 보기
1/1
post-thumbnail
post-custom-banner
본 게시글은 저자가 이해한 내용을 바탕으로 작성되었기 때문에, 잘못된 내용이 포함될 수 있습니다.
만약, 잘못된 내용을 발견하셨다면 덧글로 지적 부탁드립니다.😃
확인 후에 잘못된 부분을 바로잡을 수 있도록 노력하겠습니다.

View? ViewGroup??

View

View
1. [명사] 견해나 생각 또는 태도
2. [동사] 보다, ~라고 여기다

가 아니고, 안드로이드 공식 문서에 따르면

This class represents the basic building block for user interface components. A View occupies a rectangular area on the screen and is responsible for drawing and event handling. View is the base class for widgets, which are used to create interactive UI components (buttons, text fields, etc.)

View는 안드로이드에서 가장 기본이 되는 사용자 인터페이스를 의미함을 알 수 있다.

말이 약간 어려운 것 같지만,
화면에 그려지고 클릭이나 터치 등의 이벤트를 처리할 수 있는 사각형의 영역을 View라고 한다.
TextView Button ImageView 등이 View에 해당한다.

ViewGroup

그렇다면 ViewGroup은 무엇인가?
안드로이드 공식 문서에 따르면

A ViewGroup is a special view that can contain other views (called children.) The view group is the base class for layouts and views containers.

ViewGroup은 다른 View들을 포함할 수 있는 약간 특별한 View임을 알 수 있다.
안드로이드 개발을 해본 사람들이라면 흔히 사용해봤을 LinearLayout ConstraintLayout 등과 같은 Layout들이 ViewGroup에 해당한다.

이를 통해 CustomView를 구현할 때,
CustomView가 다른 View를 포함해야 한다면 ViewGroup을, 그렇지 않다면 View를 이용해야 한다는 것을 알 수 있다.


View가 그려지는 과정

View가 그려지는 과정은 크게 measure layout draw 3단계로 구분된다.

measure

View의 크기를 측정하는 단계로서, measure() onMeasure()가 포함된다.

measure()

onMeasure() 직전에 호출되는 함수이다.
주로 View의 크기를 측정하고자 할 때, 즉 onMeasure()를 호출하기 위해 사용한다.

onMeasure()

View의 크기를 측정하기 위한 함수이다.
ViewGroup의 경우에는 Child View의 크기를 먼저 계산한 이후에 나온 결과 값을 바탕으로 크기를 계산한다.

protected open fun onMeasure(
    widthMeasureSpec: Int, 
    heightMeasureSpec: Int
): Unit

파라미터로 넘어오는 widthMeasureSpecheightMeasureSpec은 MeasureSpec에 정의되어 있는 값이다.

MeasureSpec?

안드로이드 공식 문서에 따르면

A MeasureSpec encapsulates the layout requirements passed from parent to child. Each MeasureSpec represents a requirement for either the width or the height. A MeasureSpec is comprised of a size and a mode. There are three possible modes:

MeasureSpec은 부모로부터 자식으로 전달되는 레이아웃 요구사항이라고 하는데,
쉽게 말하면 onMeasure()에서 View의 크기를 측정할 때 부모 View로 부터 전달받은 제약 사항 이라고 생각하면 쉽다.

MeasureSpec에는 3가지의 모드가 있는데, 각각의 의미는 다음과 같다.

  • UNSPECIFIED
    : 부모 View가 자식 View에게 특별한 제한을 두지 않은 경우, 따라서 자식 View는 원하는 크기가 될 수 있다.

  • EXACTLY
    : 부모 View의 크기가 이미 고정된 경우, 따라서 자식 View는 부모 View의 크기보다 작아야만 한다.

  • AT_MOST
    : 부모 View가 지정한 크기까지 자식 View는 원하는 만큼 커질 수 있다.

layout

measure 단계에서 측정한 크기를 바탕으로 View의 내용물을 배치하는 단계로서, layout() onLayout()이 포함된다.

layout()

onLayout() 직전에 호출되는 함수이다.
주로 View를 다시 배치하고자 할 때, 즉 onLayout()을 호출하기 위해 사용한다.

onLayout()

View를 배치하기 위한 함수이다.

protected open fun onLayout(
    changed: Boolean, 
    left: Int, 
    top: Int, 
    right: Int, 
    bottom: Int
): Unit

파라미터로 넘어오는 값들은 각각 View의 좌측, 상단, 우측, 하단에 해당하는 좌표를 의미하며, 부모 View에 대한 상대 좌표이다.
measure 단계에서 측정한 크기와 파라미터로 넘어온 좌표 값을 바탕으로 뷰를 배치한다.

draw

measure와 layout 단계에서 결정된 크기와 위치를 바탕으로 View를 화면에 그리는 단계로서, dispatchDraw() draw() onDraw()가 포함된다.
draw 단계는 화면에 그리는 단계이기 때문에 상당히 자주 호출된다.

따라서 draw 단계에서 새로운 객체를 생성하는 것은 좋지 않다고 한다.


Ep.1 Preview

다음 포스팅에서는 여러 안드로이드 앱에서 흔하게 확인할 수 있는 더보기 기능이 추가된 ReadMoreTextView를 구현하는 방법에 대하여 작성할 예정이다.

포스팅에 포함된 모든 CustomView는 깃허브에 업로드 될 예정이며,
질문과 개선 사항에 대한 지적은 언제나 환영합니다. 🙌

profile
주니어 개발자
post-custom-banner

0개의 댓글