android ViewGroup 학습

8974 단어
1. 개술
코드 를 쓰기 전에 나 는 몇 가지 질문 을 해 야 한다.
1. View Group 의 직책 은 무엇 입 니까?
ViewGroup 은 View 를 설치 한 용기 에 해당 하 며, 레이아웃 xml 를 쓸 때 용기 (layot 를 시작 으로 하 는 속성 은 모두 용기 에 알려 주기 위 한 것), 우리 의 너비 (layot width), 높이 (layot height), 정렬 방식 (layot gravity) 등 을 알려 줍 니 다.물론 margin 등 도 있다.그래서 View Group 의 기능 은:
childView 에 건의 하 는 너비 와 높이, 측정 모드 를 계산 합 니 다.childView 의 위 치 를 결정 합 니 다.왜 직접 확인 하 는 것 이 아니 라 너비 와 높이 만 권장 하 는 지 잊 지 마 세 요. childView 너비 와 높이 는 wrap 로 설정 할 수 있 습 니 다.content, 이렇게 해야만 childView 만 이 자신의 너비 와 높이 를 계산 할 수 있 습 니 다.
2. View 의 직책 은 무엇 입 니까?
View 의 직책 은 측정 모델 과 ViewGroup 이 제안 한 너비 와 높이 에 따라 자신의 너비 와 높이 를 계산한다.그리고 더 중요 한 직책 은:
ViewGroup 이 지정 한 영역 에 자신의 형 태 를 그립 니 다.
3. ViewGroup 과 LayoutParams 의 관 계 는?
LinearLayout 에 childView 를 쓸 때 layot 를 쓸 수 있 는 것 을 기억 해 보 세 요.gravity,layout_weight 속성;Relative Layout 에 있 는 childView 에는 layot 가 있 습 니 다.centerInParent 속성 이지 만 layot 가 없습니다.gravity,layout_weight, 왜 그런 가요?
이것 은 모든 ViewGroup 이 하나의 LayoutParams 를 지정 해 야 하기 때 문 입 니 다. childView 가 어떤 속성 을 지원 하 는 지 확인 하 는 데 사 용 됩 니 다. 예 를 들 어 LinearLayout 가 LinearLayout. LayoutParams 등 입 니 다.LinearLayout 의 소스 코드 를 보 러 가면 내부 에 LinearLayout. Layout Params 가 정의 되 어 있 습 니 다. 이 경우 weight 와 gravity 의 모습 을 발견 할 수 있 습 니 다.
2. View 의 3 가지 측정 모델
위 에서 언급 한 View Group 은 childView 에 측정 모드 를 지정 합 니 다. 다음은 세 가지 측정 모드 를 간단하게 소개 합 니 다.
EXACTLY: 정확 한 값 을 설정 했다 는 뜻 입 니 다. 보통 childView 가 너비, 높이 를 정확 한 값 으로 설정 할 때 matchparent 시 ViewGroup 은 이 를 EXACTLY 로 설정 합 니 다.
AT_MOST: 하위 레이아웃 이 최대 값 으로 제한 되 어 있 음 을 나타 내 며, 일반적으로 childView 가 너비, 높이 를 wrap 로 설정 합 니 다.content 시 ViewGroup 은 AT 로 설정 합 니 다.MOST;
UNSPECIFIED: 하위 레이아웃 이 크 고 싶 은 만큼 크다 는 뜻 입 니 다. 보통 AadapterView 의 item 의 height Mode, ScrollView 의 childView 의 height Mode 에 나타 납 니 다.이런 모델 은 비교적 보기 드물다.
주: 위의 모든 줄 은 일반적인 것 이 있 습 니 다. 위 에서 말 한 것 은 절대적 인 것 이 아니 라 childView 의 mode 설정 은 ViewGroup 의 측정 mode 와 일정한 관 계 를 가 집 니 다.물론 이것 은 첫 번 째 사용자 정의 뷰 그룹 이 고 대부분 상황 이 위의 규칙 이기 때문에 통속 적 이 고 이해 하기 쉬 우 므 로 다른 내용 을 깊이 토론 하지 않 습 니 다.
3. API 측면 에서 분석
위 에서 ViewGroup 과 View 의 직책 을 서술 하 였 으 며, 아래 는 API 측면 에서 분석 하 였 다.
View 는 ViewGroup 에서 들 어 오 는 측정 값 과 패턴 에 따라 자신의 너비 와 높이 를 확인 한 다음 에 onDraw 에서 자신 에 대한 그리 기 를 완성 합 니 다.
ViewGroup 은 View 에 view 의 측정 값 과 모드 (onMeasure 에서 완료) 를 전달 해 야 하 며, 이 ViewGroup 의 부모 레이아웃 에 대해 서도 onMeasure 에서 자신의 너비 와 높이 를 확인 해 야 합 니 다.또한, onLayout 에서 childView 의 위 치 를 지정 해 야 합 니 다.
4. 완전한 예
수요: 저 희 는 ViewGroup 을 정의 합 니 다. 내부 에 0 에서 4 개의 childView 가 들 어 갈 수 있 습 니 다. 각각 왼쪽 상단, 오른쪽 상단, 왼쪽 아래, 오른쪽 아래 에 표 시 됩 니 다.
1. 이 View Group 의 LayoutParams 를 결정 합 니 다.
이 예 에 대해 저 희 는 ViewGroup 이 margin 을 지원 할 수 있 기만 하면 됩 니 다. 그러면 저 희 는 시스템 의 MarginLayoutParams 를 직접 사용 합 니 다.

    @Override  
    public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs)  
    {  
        return new MarginLayoutParams(getContext(), attrs);  
    }  

부모 클래스 의 이 방법 을 다시 쓰 고 되 돌려 줍 니 다.
MarginLayoutParams 의 인 스 턴 스 는 우리 의 ViewGroup 에 LayoutParams 를 MarginLayoutParams 로 지정 합 니 다.
2、onMeasure
역할:
onMeasure 에서 childView 의 측정 값 과 패턴 을 계산 하고 자신의 너비 와 높이 를 설정 합 니 다.

/** 
     *     ChildView           ChildView     ,         
     */  
    @Override  
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)  
    {  
        /** 
         *    ViewGroup            ,       
         */  
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);  
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);  
        int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);  
        int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);  
  
  
        //       childView      
        measureChildren(widthMeasureSpec, heightMeasureSpec);  
        /** 
         *      wrap_content        
         */  
        int width = 0;  
        int height = 0;  
  
        int cCount = getChildCount();  
  
        int cWidth = 0;  
        int cHeight = 0;  
        MarginLayoutParams cParams = null;  
  
        //         childView     
        int lHeight = 0;  
        //         childView   ,             
        int rHeight = 0;  
  
        //         childView     
        int tWidth = 0;  
        //         childiew   ,             
        int bWidth = 0;  
  
        /** 
         *   childView        ,     margin        ,       warp_content  
         */  
        for (int i = 0; i < cCount; i++)  
        {  
            View childView = getChildAt(i);  
            cWidth = childView.getMeasuredWidth();  
            cHeight = childView.getMeasuredHeight();  
            cParams = (MarginLayoutParams) childView.getLayoutParams();  
  
            //     childView  
            if (i == 0 || i == 1)  
            {  
                tWidth += cWidth + cParams.leftMargin + cParams.rightMargin;  
            }  
  
            if (i == 2 || i == 3)  
            {  
                bWidth += cWidth + cParams.leftMargin + cParams.rightMargin;  
            }  
  
            if (i == 0 || i == 2)  
            {  
                lHeight += cHeight + cParams.topMargin + cParams.bottomMargin;  
            }  
  
            if (i == 1 || i == 3)  
            {  
                rHeight += cHeight + cParams.topMargin + cParams.bottomMargin;  
            }  
  
        }  
          
        width = Math.max(tWidth, bWidth);  
        height = Math.max(lHeight, rHeight);  
  
        /** 
         *    wrap_content          
         *   :             
         */  
        setMeasuredDimension((widthMode == MeasureSpec.EXACTLY) ? sizeWidth  
                : width, (heightMode == MeasureSpec.EXACTLY) ? sizeHeight  
                : height);  
    }  

10 - 14 줄, 이 ViewGroup 부모 용 기 를 설정 한 계산 모드 와 사 이 즈 를 가 져 옵 니 다.
대부분의 경우 wrap 만 아니라면content, 부모 용 기 는 모두 그 사 이 즈 를 정확하게 계산 할 수 있 습 니 다.그래서 저희 가 계산 을 해 야 돼 요. wrap 로 설정 하면...content 시의 너비 와 높이 는 어떻게 계산 합 니까?그것 은 바로 childView 의 너비 와 높이 를 통 해 계산 하 는 것 이다.
17 줄, View Group 의 measureChildren 방법 을 통 해 모든 아이들 에 게 너비 와 높이 를 설정 합 니 다. 이 줄 을 실행 한 후에 childView 의 너비 와 높이 는 모두 정확하게 계산 되 었 습 니 다.
43 - 71 줄, childView 의 너비 와 높이, 그리고 margin 에 따라 View Group 이 wrapcontent 의 너비 와 높이.
80 - 82 줄, 너비 가 높 으 면 속성 치가 wrapcontent 는 43 - 71 줄 에서 계 산 된 값 으로 설정 합 니 다. 그렇지 않 으 면 부모 용기 에 들 어 오 는 너비 와 높이 입 니 다.
3. onLayout 는 모든 childView 를 위치 추적 합 니 다 (childView 의 그리 기 영역 설정)

// abstract method in viewgroup
	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b)
	{
		int cCount = getChildCount();
		int cWidth = 0;
		int cHeight = 0;
		MarginLayoutParams cParams = null;
		/**
		 *     childView      ,  margin    
		 */
		for (int i = 0; i < cCount; i++)
		{
			View childView = getChildAt(i);
			cWidth = childView.getMeasuredWidth();
			cHeight = childView.getMeasuredHeight();
			cParams = (MarginLayoutParams) childView.getLayoutParams();

			int cl = 0, ct = 0, cr = 0, cb = 0;

			switch (i)
			{
			case 0:
				cl = cParams.leftMargin;
				ct = cParams.topMargin;
				break;
			case 1:
				cl = getWidth() - cWidth - cParams.leftMargin
						- cParams.rightMargin;
				ct = cParams.topMargin;

				break;
			case 2:
				cl = cParams.leftMargin;
				ct = getHeight() - cHeight - cParams.bottomMargin;
				break;
			case 3:
				cl = getWidth() - cWidth - cParams.leftMargin
						- cParams.rightMargin;
				ct = getHeight() - cHeight - cParams.bottomMargin;
				break;

			}
			cr = cl + cWidth;
			cb = cHeight + ct;
			childView.layout(cl, ct, cr, cb);
		}

	}

코드 는 쉽게 알 수 있 습 니 다. 모든 childView 를 옮 겨 다 니 며 childView 의 너비 와 높이, margin 에 따라 각각 0, 1, 2, 3 위치의 childView 를 왼쪽 위, 오른쪽 위, 왼쪽 아래, 오른쪽 아래 위치 로 순서대로 설정 합 니 다.
첫 번 째 View (index = 0) 라면 childView. layot (cl, ct, cr, cb);cl 는 childView 의 left Margin 이 고, ct 는 topMargin 이 며, cr 은 cl + cWidth 이 며, cb 는 ct + cHeight 이다.
두 번 째 View (index = 1) 라면 childView. layot (cl, ct, cr, cb);
cl 는 getWidth () - cWidth - cParams. leftMargin - cParams. rightMargin;
ct 는 topMargin, cr 은 cl + cWidth, cb 는 ct + cHeight
나머지 두 개 는 비슷 해 요.
이렇게 하면 완 성 됩 니 다. 우리 의 ViewGroup 코드 의 작성 은 다음 에 테스트 를 진행 합 니 다. 각각 너비 와 높이 를 고정 값 으로 설정 합 니 다. wrapcontent,match_parent
다음으로 이동:http://blog.csdn.net/lmj623565791/article/details/38339817

좋은 웹페이지 즐겨찾기