View
- 그리기 및 이벤트 처리를 담당하는 UI 구성요소의 기본 클래스
- *위젯을 작성하는 데 사용되는 기본 클래스 (새로운 위젯을 만들기 위해선 View 를 상속하여 구현해야 한다)
- 위젯(컴포넌트) : View 를 상속받아 구현하는 TextView, Button 등 어떤 특수한 목적을 가지고 있는 View
- 위젯들을 담는 부모 뷰 Layout 도 View 를 상속받는 *ViewGroup 을 상속받아 구현한다.
- ViewGroup : View 의 또 다른 서브 클래스이자 보이지 않는 컨테이너로, 다른 View 들을 포함할 수 있다.
View 가 그려지는 과정
- 뷰는 포커스를 받게 되면 Android 에게 View Hierarchy 의 루트 노드를 제공하여 레이아웃을 그리게 된다.
- 액티비티의 onCreate() 내에서 setContentView() 를 통해 루트 노드 전달
- 레이아웃은 루트 노드부터 리프 노드까지 트리를 따라 순서대로 그려지게 된다.
- 부모가 먼저 그려지고 그 다음 자식들 순서대로 그려지는 형태 (Top-down 방식)
- 부모 뷰(ViewGroup, Layout)는 자식 뷰들의 draw() 를 호출하여 화면에 지정된 형태로 자식 뷰들을 그려줄 것을 요청한다.
- 모든 뷰는 스스로 그려질 책임이 있다.
- 레이아웃을 그리는 과정은 크게 *Measure 단계와 *Layout 단계를 거친다.
View Lifecycle
- 부모 뷰가 addView() 를 호출하면, 자식 뷰가 부모 뷰에 추가되고, 이후 뷰의 생명주기 과정이 진행된다.
1. Constructor(생성자)
public View(Context context) { .. }
public View(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
}
public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { .. }
- 모든 뷰는 생성자를 통해 초기화되며 생명 주기가 시작된다.
- 이때 *AttributeSet 을 전달받아 뷰의 속성을 설정할 수 있다.
- AttributeSet : XML 레이아웃 파일에서 정의된 뷰의 속성(Attribute)을 가져오는 데 사용되는 인터페이스
- addView() 메소드를 갖게 된다.
1-1. View(Context context)
- 코드에서 View 를 동적으로 만들 때 사용할 수 있는 간단한 생성자
- context : View 가 실행될 때 사용되는 context 로, 현재 테마, 리소스 등을 구성하는 데 사용된다.
1-2. View(Context context, @Nullable AttributeSet attrs)
- XML 에서 View 를 *전개 할 때 호출되는 생성자
- 전개(Inflate) : xml 에 표기된 레이아웃을 메모리에 로딩된 후 객체화 시키는 과정
- XML 파일에서 지정된 속성을 제공하여 XML 파일에서 View 를 구성할 때 호출된다.
- 이 생성자는 기본 스타일인 0을 사용하기 때문에 context 의 테마와 지정된 AttributeSet 의 속성 값만 적용된다.
1-3. View(Context context, @Nullable AttributeSet attrs, int defStyleAttr)
- XML 을 통해 전개를 하고 테마 속성에서 클래스별 기본 스타일을 적용한다.
- 이 생성자는 서브 클래스가 전개할 때 자체 기본 스타일을 사용할 수 있도록 한다.
- 예시: Button 클래스의 생성자는 슈퍼 클래스의 생성자를 호출하면서 defStyleAttr 에 R.attr.buttonStyle 을 제공한다. 이를 통해 Button 스타일이 적용되어, 기본적인 View 속성과 Button 클래스의 속성을 모두 수정할 수 있다.
- 버튼에 대한 일관된 스타일링을 유지하면서도, 추가적인 속성을 쉽게 조정할 수 있다.
- 예시: Button 클래스의 생성자는 슈퍼 클래스의 생성자를 호출하면서 defStyleAttr 에 R.attr.buttonStyle 을 제공한다. 이를 통해 Button 스타일이 적용되어, 기본적인 View 속성과 Button 클래스의 속성을 모두 수정할 수 있다.
- defStyleAttr : View의 기본값을 제공하는 Style 리소스 대한 참조를 포함하는 현재 테마의 속성이다. 기본값을 찾지 않으려면 0으로 지정할 수 있다.
1-4. View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes)
- XML 을 전개하고 테마 속성 또는 Style 리소스에서 클래스 별 기본 스타일을 적용한다.
- 이 생성자는 서브 클래스가 전개할 때 자체 기본 스타일을 사용할 수 있도록 한다. 위와 유사하다.
- defStyleRes : View 의 defStyleAttr 가 0이거나 테마에서 찾을 수 없는 경우에만 기본값을 제공하는 Style 리소스 ID 다. 기본값을 찾지 않으려면 0으로 지정한다.
2. onAttachedToWindow()
- 뷰가 윈도우에 연결될 때 호출된다.
- 뷰가 활성화될 수 있고, 뷰를 그리기 위한 surface 가 있다는 것을 아는 단계이다.
- 고유 ID 를 통해 뷰에 접근 가능하다.
- 리소스 할당을 시작하거나 리스너를 설정할 수 있다.
3. measure()
- 뷰가 얼마나 커야 하는지 크기를 요청한다.
- 뷰는 반드시 ViewGroup 에 속해 있다. 그러므로 뷰는 자신의 크기를 결정하기 위해 자신을 담고 있는 부모 뷰의 크기를 알아야 하고 그 안에서 자신이 사용할 영역을 알아야 한다.
- View 객체의 측정된 너비와 높이 값은 부모 뷰가 부여한 제약 조건을 준수해야 한다.
- Measure 단계가 모두 종료되고 모든 상위 뷰들과 자식 뷰들의 측정값을 모두 수락하는 단계를 거친다.
- 부모 뷰는 자식 뷰의 크기 합이 너무 크거나 작을 경우, 자식 뷰에 대해 두 번 이상의 measure() 호출을 할 수 있다.
- measure() 의 파라미터에는 *MeasureSpec 을 전달한다.
- View.MeasureSpecs : 부모 뷰가 자식 뷰의 크기를 제한할 때 사용한다.
- UNSPECIFIED : 자식 뷰의 크기에 대한 제한이 없다.
- EXACTLY : 자식 뷰의 정확한 사이즈를 설정한다.
- AT_MOST : 자식 뷰의 최대 사이즈를 설정한다.
- View.MeasureSpecs : 부모 뷰가 자식 뷰의 크기를 제한할 때 사용한다.
4. onMeasure()
- 뷰의 크기를 측정하기 위해 measure() 에서 호출하는 콜백 메서드로, 정확한 측정값을 제공하기 위해 재정의해야 한다.
- 측정값을 정하기 전에는 너비와 높이가 0이다.
- 부모 뷰는 모든 자식 뷰의 measure() 가 완료된 후, 자식 뷰의 getMeasuredWidth() 및 getMeasuredHeight() 값을 사용하여 자신의 크기를 설정한다.
- setMeasuredDimension() 호출하여 명시적으로 너비와 높이 설정한다.
- 호출하지 않으면 IllegalStateException 을 던진다.
- ViewGroup.LayoutParams : 자식 뷰가 부모 뷰에게 너비와 높이에 대해 얼마나 크게 되기를 원하는지를 설명한다.
- MATCH_PARENT : 자식 뷰가 부모 뷰의 크기에 꽉 맞추겠다.
- WRAP_CONTENT : 자식 뷰가 자신의 내용물 크기에 맞춰 크기를 조정하겠다.
- 정확한 숫자값 : DP 값
5. layout()
- 뷰와 모든 자식 뷰들의 위치를 요청한다.
6. onLayout()
- 뷰의 크기와 위치를 지정하기 위해 layout() 에서 호출하는 콜백 메서드
- 부모 뷰는 Measure 단계에서 측정된 크기를 사용하여 모든 자식 뷰들의 위치를 배정한다.
7. dispatchDraw()
- ViewGroup 에 속한 메서드
- 뷰가 다시 그려져야 할 경우, 자식 뷰들도 함께 다시 그려지도록 한다.
8. draw(), onDraw()
- 실제로 뷰를 그리는 단계
- 파라미터로 *Canvas 객체가 넘어오고, Canvas 객체에 *Paint 를 이용해서 텍스트, 선, 비트맵 등을 그리기 위한 메서드를 정의한다.
- Canvas : 어떤 도형을 그릴 것인지에 대한 메서드를 제공하는 객체
- Paint : 색상, 스타일, 글꼴 등을 정의하는 객체
- 크기와 위치는 이전에 계산되었기 때문에, 이를 기준으로 뷰가 그려지게 된다.
- 해당 콜백 메소드는 언제든 다시 호출될 수 있기 때문에, 이 안에서 객체를 생성하면 안된다.
- 스크롤, 스와이프 등 인터렉션이 발생하면 언제든 호출될 수 있다.
9-1. invalidate()
- 글자나 색상 등 크기 변화 없이 단순히 뷰의 속성 등이 변경된 경우, 뷰를 다시 그리기 위해 호출하는 메소드
9-2. requestLayout()
- 뷰의 크기 변화하면 레이아웃의 배치도 달라질 수 있기 때문에, 뷰를 다시 측정하기 위해 호출하는 메서드
10. 기타
10-1. onDetachedFromWindow()
- 뷰가 윈도우에서 분리될 때 호출된다.
- 이 시점에서 더 이상 드로잉을 할 표면이 없다.
- 예약된 자원을 정리하거나 정리하는 모든 종류의 작업을 중지해야 하는 곳이다.
- 부모 뷰에서 해당 뷰 제거를 호출하거나 액티비티가 onDestroy() 될 때 호출된다.
10-2. onFinishInflate()
- 뷰의 inflate 가 끝날 때 호출된다.
- 레이아웃의 경우 모든 Child View 가 추가 된 후에 호출된다.
'안드로이드 > Android' 카테고리의 다른 글
[Android] Strong, Soft, Weak, Phantom Reference (0) | 2024.10.21 |
---|---|
[Android] ConstraintLayout (0) | 2024.10.02 |
[Android] px(pixel), dp(dip), sp (0) | 2024.10.01 |