App_Dev/Android

[ 앱 개발자 도전기 : 안드로이드 ] View가 그려지는 순서

안다미로 : Web3 & D.S 2024. 11. 7. 21:10

 

 

 

 

[ 앱 개발자 도전기 : 안드로이드 ] View가 그려지는 순서

 


 

 

∇ View가 그려지는 과정

목   차

1. View가 그려지는 과정

  1-1. onAttachToWindwo()
  1-2. measure ( int widthMeasureSpec, int heightMeasureSpec )
  1-3. layout( int left, int top, int right, int bottom )
  1-4. draw ( Canvas canvas )
  
2. View의 업데이트.

  2-1. invalidate()
  2-2. requestLayout

 

 


 

1. View가 그려지는 과정.


     ※  View는  ' 포커스 ' 를 얻었을 때  레이아웃을 드로잉하도록 요청합니다.

 

          = > " 레이아웃 드로잉 " 은 Root가 되는 ViewGroup에서 시작되어서  XML 트리 구조를 따라서 

                       "  전위-순회-방식 " 으로 그려지게 됩니다.

 

                   ○ 전위 순회( Pre - order )

                         : " Root - Left - Right " 순서로 노드를 순회합니다.

ABDCEFG 순서로 순회.

 

       = > "VIEW" 는  'measure' - 'layout' - 'draw' 단계를 거쳐서 그려집니다.

 

 

 

      1-1  ◆ onAttachToWindow()

              : 부모뷰에 의해서   'addView()'가 호출 된 후 자식뷰는 윈도우에 붙게 됩니다.

                   - > 이 시점부터, 뷰의 'id'를 통한 접근이 가능해집니다.

                           [ 뷰의 id란 : 뷰를 식별하기 위한 식별자 ]

 


 

      1-2  ◆ measure ( int widthMeasureSpec,  int heightMeasureSpec )

             

                 ◎ 뷰의 크기와 좌표를 알아내고자 할 때 호출됩니다. !

 

                      = > 뷰의 실질적인 크기 측정은 measure() 가 아닌,

                                     measure() 안에 래핑 되어 있는 onMeasure()에서 MeasureSpec에 기반하여 수행됩니다!

 

 

                       ◇ measure()에서는 onMeasure()를 통해, 직전에 측정된 값을 캐싱합니다.

                               - > 반복적 호출이 발생하는 상황에서 보다 빠른 처리가 가능 !

 

                             § 강제로 뷰의 크기 측정이 다시 필요해지는 시점은?

                                    = > " foreceLayout flag " 를 설정하여 캐싱 된 값을 사용하지 않고 다시 측정 가능합니다.

                                                  == > 이 flag는 requestLayout()을 통해 설정 가능합니다.

 

                                  √ requestLayout()

                                      : View의 레이아웃을 갱신하기 위해 호출됩니다. [ View의 크기나 위치가 변경될 떄 호출 ]

                                          - > ViewGroup에게 레이아웃 갱신을 요청.( ViewGroup이 다시 자식 View의 크기와 위치 계산 )

 

                                  √ invalidate()

                                      : View의 내용을 다시 그리기 위해 호출됩니다.

                                          - View가 그려질 때, 시스템은 View의 onDraw() 메서드를 호출하여 , View의 내용을 그립니다.

 

                   

                             § 측정 과정에서, 부모와 자식뷰의 크기 정보를 전달하기 위해 2가지 클래스를 사용.

 

                                    ● ViewGroup.LayoutParams

                                           - 자식뷰가 부모뷰에게 자신이 측정할 방법을 알릴 때 사용

                                           - ViewGroup의 종류별로 다른 LayoutParams가 존재 가능.

                                           - LayoutParams의 속성은 [ 숫자, MATCH_PARENT ,  WRAP_CONTENT ]

 

                                    ● ViewGroup.MeasureSpec

                                         : 부모뷰가 자식뷰에게 요구사항을 전달하기 위해 사용.

                                            -  UNSPECIFIED : 부모뷰는 자식뷰가 원하는대로 치수를 결정.

                                            -  EXACTLY : 부모뷰가 자식뷰에게 정확한 크기를 강요.

                                            -  ATMOST : 부모뷰가 자식뷰에게 최대 크기를 강요.

 


      1-3  ◆ layout ( int left, int top, int right, int bottom )

 

                   ※ 뷰의 위치를 배치하기 위해 호출됩니다.

 

                          § measure()에 의해 각 뷰에 측정되어 저장 된 크기와 좌표 정보를 가지고

                                화면에서 뷰가 보여질 위치를 결정합니다.

 

                          § layout()에서는 뷰의 위치가 변경 되었는지 검사를 수행하며, 

                               이 검사 결과 위치 변경이 확인되었다면 onLayout()을 호출하여 위치를 다시 결정하게 됩니다.

 


      1-4  ◆ draw( Canvas canvas )

 

                 ※ View가 그려지기 위해 필요한 작업들을 다음과 같은 순서대로 수행합니다.

 

                            ● 백그라운드 드로잉.

                            ● 뷰의 그림자 효과를 위한 캔버스 캐싱

                            ● 뷰 드로잉 ( onDraw() 호출 )

                            ● 자식뷰 드로잉

                            ● 뷰 그림자 드로잉

                            ● Paint를 통한 뷰의 색상 설정.

 

                  § 실질적인 뷰의 드로잉은 onDraw()에서 호출됩니다.

                         onDraw()는 Canvas를 메소드의 파라미터로 제공받아서 뷰의 모양을 그립니다.

 


 

2. View의 업데이트


 

    뷰의 라이프사이클 중 invalidate()와  requestLayout()을 찾아볼 수 있습니다.

        이 메소드들은 Runtime 시점에서 뷰를 다시 그릴 수 있도록 합니다.

 

       2-1  ◆ invalidate ()

                 : 뷰의 그래픽이 변경되었을 때 호출합니다.

 

                      - 뷰를 측정이나 위치 변경 없이 다시 그리고 싶을 때 사용합니다.

                      - 뷰에 포함되는 Text 혹은 Color가 변경되었을 때, 

                                               사용자의 터치로 인해 뷰의 그래픽적인 요소가 바뀌어야 할 때

                                                onDraw()를 재호출하면서 뷰를 업데이트 합니다. 

 

 

       2-2  ◆ requestLayout()

 

                    : 뷰의 크기, 위치가 변경되었을 때 호출합니다.

                          - onMeasure() 부터 시작해서 뷰를 다시 그립니다.

                          - 뷰의 사이즈가 변경되었을 때, 그 변경 된 크기 정보와  위치를 다시 계산해야 하는 상황에서 사용.