CustomView 또한 하나의 View이기 때문에 CustomView에 대해서 학습하기 전에 View와 View가 그려지는 과정에서 대해서 파악해보려고 합니다.
1️⃣ View란
View는 Activity에서 화면을 구성하는 최소 단위입니다.즉,
사용자들이 안드로이드 App을 사용할 때 마이페이지 등에서 프로필 사진, 사용자 명, 뒤로가기 등의 구성 요소들을 볼 수 있듯이 화면에 보이는 모든 것은 View 입니다.
정확히는 앞에서 말한 것들이 TextView, ImageView, Button을 통해 화면에 표시되는 것입니다.
TextView, ImageView 뒤에 View가 붙는 것을 보고 유추할 수 있듯이 View 클래스를 상속받아 구현하고자 하는 View에 대하여 그리기 및 이벤트 처리 등의 작업하여 구현한 것입니다.
???: 아... 그럼 Button은 뒤에 View가 붙지 않았으니 View가 아니구나라고 생각할 수 있지만 Button도 View를 상속받아 구현되었습니다.
아래 코드와 사진을 확인해봅시다.
public class TextView extends View implements OnPreDrawListener {
...
}
public class Button extends TextView {
...
}
public class ImageView extends View {
...
}
위 내용에서 알 수 있듯이 View들이 계층 구조를 이루고 있고 모두 최상위엔 클래스인 View를 상속받는 것을 알 수 있습니다.
자 이제 View가 그려지는 과정에 대해서 알아보겠습니다.
2️⃣ View의 생명주기
Activity, Fragment가 생명주기를 가지는 것처럼 View도 생명주기가 있습니다.
CustomView를 만들기 위해선 View의 생명주기를 꼭 알고있어야 하며, 각 생명주기 Call back Method는 다음과 같습니다.
1. 생성자
public View(Context context)
코드에서 View를 생성할 때 호출되는 생성자입니다.
public View(Context context, @Nullable AttributeSet attrs)
레이아웃 파일에서 지정된 속성을 제공하여 View를 생성할 때 호출되는 생성자입니다.
해당 생정자는 기본 스타일인 0을 사용하므로 Context의 테마 및 지정된 AttributeSet의 속상 값만 적용합니다.
public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr)
레이아웃 파일에서 지정된 속성을 제공하여 View를 생성하고 테마 속성에서 클래스별 기본 스타일을 적용합니다.
해당 생성자는 서브 클래스가 확장될 때 자체 기본 스타일을 사용할 수 있도록 합니다.
예를들어 Button 클래스의 생성자는 수퍼 클래스 생성자를 호출하고 defStyleAttr에 R.attr.buttonStyle을
제공합니다. 이를 통해 테마의 버튼 스타일은 모든 기본 View 속성과 Button 클래스의 속성을 수정할 수 있습니다.
defStyleAttr 매개변수는 View의 기본값을 제공하는 Style 리소스에 대한 참조를 포함하는 현재 테마의 속성입니다.
기본값을 찾지 않으려면 0으로 지정할 수 있습니다.
public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes)
레이아웃 파일에서 지정된 속성을 제공하여 View 생성하고 테마 속성 또는 Style 리소스에서 클래스 별 기본 스타일을
적용합니다.
해당 생정자는 서브 클래스가 확장할 때 자체 기본 스타일을 사용할 수 있도록 합니다.(위와 유사)
매개변수 defStyleRes는 View의 defStyleAttr이 0이거나 테마에서 찾을 수 없는 경우에만 기본값을 제공하는
Style 리소스 ID 입니다. 기본값을 찾지 않으려면 0으로 지정합니다.
2. onFinishInflate()
모든 속성이 XML에서 확장된 후 호출되며, 프로그래밍 방식으로 View를 생성할 경우엔 호출되지 않습니다.
레이아웃의 경우 모든 자식 View가 추가되면 호출됩니다.
3. onAttachedToWindow()
View가 Window에 연결되면 호출됩니다.
4. measure(int widthMesasureSpec, int heighMeasureSpec)
View가 얼마나 커야 하는지 알아보기 위해 호출됩니다.
5. onMeasure(int widthMesasureSpec, int heighMeasureSpec)
View와 View의 내용을 측정하여 측정된 width 및 height를 결정합니다.
View의 크기를 확인하기 위해 호출됩니다.
ViewGroup의 경우 계속해서 각 자식 View에 대한 측정을 하고, 그에 대한 결과로 자신의 사이즈를 결정합니다.
계속 진행해야할 작업
6. layout()
7. onLayout()
8. dispatchToDraw()
9. draw()
10. onDraw()
11. Visible to User
12. User interaction
순회(Trabersals) or ViewUpdate
invalidate() , requestLayout()
13. onDetachedFromWindow()
참고자료
https://www.charlezz.com/?p=29013
https://www.charlezz.com/?p=34935
https://developer.android.com/training/custom-views/create-view?hl=ko
https://medium.com/revolut/custom-view-from-scratch-part-i-931178481903
https://labs.brandi.co.kr/2021/10/14/jeonhs.html
'Android' 카테고리의 다른 글
👋Android 인터뷰를 위한 간단 정리 (0) | 2022.05.12 |
---|---|
👋Android Programming : SnackBar! 기본 사용법부터 커스텀까지 (0) | 2022.05.08 |
👋Android Programming : TextInputLayout을 이용한 UI 디자인 (0) | 2022.03.21 |
Retrofit2, OkHttpInterceptor, Koin, RxKotlin, Coroutine, Sandwich 등을 이용해 내가 작성한 네트워크 통신 방법 (0) | 2022.03.05 |
RecyclerView) BaseAdapter, BaseViewMdoel, BaseModel, DiffUtil : 공통 어답터와 뷰홀더를 이용해 리사이클러뷰 사용하기 (0) | 2021.08.04 |