안 드 로 이 드 사용자 정의 viewgroup 의 어 려 운 점 을 알 아 보 는 글

본문의 목적
뷰 그룹 을 어떻게 사용자 정의 하고 레이아웃 을 사용자 정의 하 며 사용자 정의 측정 을 어떻게 쓰 는 지 알려 주 는 것 이 목적 이다.많은 인터넷 에서 마음대로 검색 하 는 개념 과 절차 도
여기 서 더 이상 설명 하지 않 겠 습 니 다.본 고 를 보기 전에 기본 적 인 사용자 정의 view group 절 차 를 살 펴 보고 마음 속 에 대략적인 것 이 있 으 면 됩 니 다.본문 은 실천 을 중시한다.
viewgroup 의 측정 레이아웃 프로 세 스 기본 정리
기본 적 인 viewgroup 그리 기와 레이아웃 프로 세 스 의 중점 을 살 펴 보 겠 습 니 다.
1.view 는 onMeasure()방법 에서 자체 측정 과 보존 을 한다.즉,view(view group 아 닙 니 다)에 있어 서 반드시 onMeasure 방법 에서 자신의 사 이 즈 를 계산 하여 저장 해 야 한다.
2.viewgroup 은 실제 적 으로 위 크기 에서 하위 view 를 호출 하 는 measure 방법 이기 도 합 니 다.하위 view 의 measure 가 실제 적 으로 하위 view 의 onMeasure 방법 을 호출 하 는 것 을 주의 하 십시오.그래서 우 리 는 이 과정 을 다음 과 같이 이해한다.
view group 순환 은 모든 하위 view 의 onmeasure 방법 을 호출 하고 onmeasure 방법 으로 계 산 된 크기 를 이용 하여 이 하위 view 가 최종 적 으로 사용 할 수 있 는 크기 와 배치 위 치 를 확인 합 니 다.
3.measure 방법 은 final 방법 으로 측정 작업 준비 작업 으로 이해 할 수 있 습 니 다.final 방법 이기 때문에 우 리 는 그것 을 다시 쓸 수 없습니다.너무 많이 필요 하지 않 습 니 다.
그 를 주목 하 라.measure 가 최종 적 으로 onmeasure 를 호출 해 야 하기 때문에 이 onmeasure 는 우리 가 다시 쓸 수 있다.이거 지 켜 봐 야 돼.layot 와 onlayout 은 같은 관계 입 니 다.
4.부모 view 가 하위 view 의 layot 방법 을 호출 할 때 이전 measure 단계 에서 확 정 된 위치 와 크기 를 하위 view 에 전달 합 니 다.
5.사용자 정의 view/viewgroup 에 있어 우 리 는 다음 세 가지 수요 에 만 관심 을 가 져 야 합 니 다.
4.567917.기 존의 안 드 로 이 드 자체 view 에 대해 우 리 는 그의 onMeasure 방법 만 다시 쓰 면 된다.이 사 이 즈 를 수정 하면 수 요 를 완성 할 수 있 습 니 다
  • 안 드 로 이 드 시스템 에 없 는 것 은 우리 가 사용자 정의 view 에 속 합 니 다.위 에 있 는 것 보다 복잡 하고 onMeasure 방법 을 완전히 다시 써 야 합 니 다
  • 4.567917.세 번 째 가장 복잡 한 것 은 onmeasure 와 onlayout 2 가지 방법 을 다시 써 서 복잡 한 view group 의 측정 과 구 조 를 완성 해 야 합 니 다6.onMeasure 방법의 특수 설명:

    7.부모 view 가 자식 view 에 대한 제한 을 어떻게 이해 합 니까?
    onMeasure 의 두 매개 변 수 는 부모 view 의 하위 view 에 대한 제한 이 므 로 이 제한 값 은 도대체 어디에서 나 온 것 입 니까?
    실제로 부모 view 의 하위 view 에 대한 제한 은 대부분 우리 개발 자가 설정 한 layot 에서 시작 하 는 속성 입 니 다.
    예 를 들 어 우 리 는 imageview 에 그의 layot 를 설정 했다.width 와 layotheight 이 두 가지 속성,그럼 이 두 가지 속성 은 사실 우리 개발 자 입 니 다.
    기대 하 는 넓 고 높 은 속성,하지만 주의해 야 합 니 다.
    설정 한 이 두 가지 속성 은 부모 view 에 보 여 주 는 것 입 니 다.실제 대부분의 layot 시작 속성 에 대해 서 는 부모 view 에 보 여 주 는 것 입 니 다.
    왜 아버지 께 보 여 드 려 야 합 니까?부모 view 는 이러한 속성 을 알 아야 하위 view 의 측정 에 어떤 제한 을 가 해 야 하 는 지 알 수 있 기 때 문 입 니까?
    도대체 무제 한(UNSPECIFIED)인가요?아니면 최대 치 제한(ATMOST),하위 뷰 가 이 값 을 초과 하지 않도록?아니면 죽음 을 직접 제한 하 든 내 가 시 키 는 대로 해 야 돼(EXACTLY).
    Banner ImageView 수정 onMeasure 방법 사용자 정의
    banner Imageview 란 많은 전자상거래 업 체 들 이 광고 도 를 방영 하 는 것 입 니 다.이 광고 도의 너비 와 높이 는 모두 가 변 적 입 니 다.우 리 는 일상적인 개발 과정 에서
    또한 이러한 수 요 를 자주 접 할 수 있 습 니 다.imageview 의 너비 와 높이 는 하이파이 어 에 표 시 된 것 보다 높 지만 많은 핸드폰 의 화면 너비 나 높이 를 고려 하여 확실 하지 않 습 니 다.
    그래서 우 리 는 보통 수 동 으로 이 imageview 의 높이 나 너 비 를 계산 한 다음 에 width 나 height 의 값 을 동적 으로 바 꿔 야 한다.이런 방법 은 쓸 수 있 지만 매우 번거롭다.
    사용자 정의 imageview 를 보 여 줍 니 다.ratio 의 속성 을 설정 하면 iv 의 높이 를 동적 으로 설정 할 수 있 습 니 다.매우 편리 하 다

    효 과 를 보다

    마지막 으로 코드 를 보 세 요.중요 한 부분 은 주석 에 적 혀 있 습 니 다.더 이상 말 하지 않 겠 습 니 다.
    
    public class BannerImageView extends ImageView {
    
     //   
     float ratio;
    
     public BannerImageView(Context context) {
     super(context);
     }
    
     public BannerImageView(Context context, AttributeSet attrs) {
     super(context, attrs);
    
     TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.BannerImageView);
     ratio = typedArray.getFloat(R.styleable.BannerImageView_ratio, 1.0f);
     typedArray.recycle();
     }
    
     public BannerImageView(Context context, AttributeSet attrs, int defStyleAttr) {
     super(context, attrs, defStyleAttr);
     }
    
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
     //                ,           setMeasuredDimension          
     //                               
     super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    
     //     
     int mWidth = getMeasuredWidth();
    
     int mHeight = (int) (mWidth * ratio);
    
     //     , view             。         。
     setMeasuredDimension(mWidth, mHeight);
     }
    }
    사용자 정의 view,완전 자기 쓰기 onMeasure 방법
    먼저 명확 한 결론 을 내린다.
    완전히 사용자 정의 view,완전히 자신 이 쓴 onMeasure 방법 에 있어 서,당신 이 저장 한 너비 와 높이 는 부모 view 의 제한 에 부합 되 어야 합 니 다.그렇지 않 으 면 bug 가 발생 합 니 다.
    부모 view 의 하위 view 에 대한 제한 을 저장 하 는 방법 도 간단 합 니 다.resolve Size 방법 을 직접 호출 하면 됩 니 다.


    그래서 완전히 사용자 정의 view onMeasure 방법 도 어렵 지 않 습 니 다.
    4.567917.먼저 자신 이 원 하 는 너비 와 높이 를 계산한다.예 를 들 어 네가 원 을 그 렸 다 면 너비 와 높이 는 반지름 의 두 배 크기 일 것 이다.만약 에 원 아래 에 글자 가 있다 면4.567917.그러면 높이 는 반지름 의 두 배 를 제외 하고 글씨체 의 크기 가 있 을 것 이다.그렇지?간단 해.이것 은 순 전 히 사용자 정의 view 가 어떤 것 인지 에 달 려 있다.
    4.567917.자신 이 원 하 는 너비 와 높이 를 계산 한 후에 resolve Size 방법 으로 처리 하면 됩 니 다마지막 setMeasured Dimension 저장.범례:
    
    public class LoadingView extends View {
    
     //     
     int radius;
    
     //      rect   
     int left = 10, top = 30;
    
    
     Paint mPaint = new Paint();
    
     public LoadingView(Context context) {
     super(context);
     }
    
     public LoadingView(Context context, AttributeSet attrs) {
     super(context, attrs);
     TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.LoadingView);
     radius = typedArray.getInt(R.styleable.LoadingView_radius, 0);
     }
    
     public LoadingView(Context context, AttributeSet attrs, int defStyleAttr) {
     super(context, attrs, defStyleAttr);
     }
    
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
     super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    
    
     int width = left + radius * 2;
     int height = top + radius * 2;
    
     //    resolveSize          view   ,      layout           bug 。
     //              view           
     width = resolveSize(width, widthMeasureSpec);
     height = resolveSize(height, heightMeasureSpec);
    
     setMeasuredDimension(width, height);
     }
    
     @Override
     protected void onDraw(Canvas canvas) {
     super.onDraw(canvas);
    
     RectF oval = new RectF(left, top,
      left + radius * 2, top + radius * 2);
     mPaint.setColor(Color.BLUE);
     canvas.drawRect(oval, mPaint);
     //    
     mPaint.setColor(Color.RED);
     mPaint.setStyle(Paint.Style.STROKE);
     mPaint.setStrokeWidth(2);
     canvas.drawArc(oval, -90, 360, false, mPaint);
     }
    }
    레이아웃 파일:
    
    <LinearLayout
      android:layout_width="200dp"
      android:layout_height="200dp"
      android:background="#000000"
      android:orientation="horizontal">
    
      <com.example.a16040657.customviewtest.LoadingView
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:src="@mipmap/dly"
       app:radius="200"></com.example.a16040657.customviewtest.LoadingView>
    
      <com.example.a16040657.customviewtest.LoadingView
       android:layout_marginLeft="10dp"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:src="@mipmap/dly"
       app:radius="200"></com.example.a16040657.customviewtest.LoadingView>
     </LinearLayout>
    마지막 효과:

    viewgroup 사용자 정의
    이것 은 사실 조금 복잡 하지만 따라 갈 만 한 흔적 이 있 습 니 다.다만 약간의 추가 적 인 인내심 이 필요 합 니 다.
    viewgroup 에서 주의해 야 할 점 은 다음 과 같 습 니 다.
    4
  • 반드시 onMeasure 를 다시 써 서 하위 view 의 너비 와 자신의 너비 가 높 은 지 확인 한 후에 야 onlayout 을 계속 써 서 이 하위 view 를 배치 할 수 있 습 니 다.
  • viewgroup 의 onMeasure 는 사실 자신의 view 를 옮 겨 다 니 며 자신의 모든 키 view 를 measure 하 는 것 입 니 다.절대 다수의 경우 하위 view 의 measure 는 measure Child()라 는 방법 으로 대체 할 수 있 습 니 다.우리 의 쓰기 방법 을 간소화 할 수 있 습 니 다.만약 에 view group 이 복잡 하 다 면 measure Child 를 사용 하 는 것 이 아니 라 스스로 measure Child 를 한 번 쓸 수 없습니다
  • view group 의 자신의 사 이 즈 를 계산 하고 저장 하 는 방법 은 어떤 set Measured Dimension 인지 잊 지 마 세 요
  • 부득이 하 게 measure Child 방법 을 다시 쓰 려 고 할 때 도 어렵 지 않 습 니 다.부모 view 의 측정 과 자 view 의 측정 에 대해 취사선택 관 계 를 만 드 는 것 일 뿐 입 니 다.기본 적 인 measure Child 방법 을 알 게 되면 앞으로 자신의 복잡 한 measure Child 방법 을 쓸 것 입 니 다
  • 다음은 아주 간단 한 예 입 니 다.아주 간단 한 flow layot 의 실현 은 margin padding 을 처리 하지 않 았 고 모든 tag 의 높이 를 가설 하 였 습 니 다.
    고정 적 이 고 매우 간단 하 다 고 할 수 있 지만 참 새 는 작 지만 오장 이 모두 갖 추어 져 있 기 때문에 사용자 정의 viewgroup 의 관건 을 잘 이해 할 수 있 습 니 다.
    
    /**
     *       flowlayout        layout,               layout
     *             ,        ,             flowlayout
     *       ,          viewgroup      。
     * <p>
     *          padding  margin     ,     viewgroup                 
     *                          。。。。。。
     */
    public class SimpleFlowLayout extends ViewGroup {
     public SimpleFlowLayout(Context context) {
      super(context);
     }
    
     public SimpleFlowLayout(Context context, AttributeSet attrs) {
      super(context, attrs);
     }
    
     public SimpleFlowLayout(Context context, AttributeSet attrs, int defStyleAttr) {
      super(context, attrs, defStyleAttr);
     }
    
     /**
      * layout                                        ,
      *         ,                
      *          ,      onMeasure             view               
      *
      * @param changed
      * @param l
      * @param t
      * @param r
      * @param b
      */
    
     @Override
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
      int childTop = 0;
      int childLeft = 0;
      int childRight = 0;
      int childBottom = 0;
    
      //    width
      int usedWidth = 0;
    
    
      //customlayout         
      int layoutWidth = getMeasuredWidth();
      Log.v("wuyue", "layoutWidth==" + layoutWidth);
      for (int i = 0; i < getChildCount(); i++) {
       View childView = getChildAt(i);
       //     view        
       int childWidth = childView.getMeasuredWidth();
       int childHeight = childView.getMeasuredHeight();
    
       //               
       if (layoutWidth - usedWidth < childWidth) {
        childLeft = 0;
        usedWidth = 0;
        childTop += childHeight;
        childRight = childWidth;
        childBottom = childTop + childHeight;
        childView.layout(0, childTop, childRight, childBottom);
        usedWidth = usedWidth + childWidth;
        childLeft = childWidth;
        continue;
       }
       childRight = childLeft + childWidth;
       childBottom = childTop + childHeight;
       childView.layout(childLeft, childTop, childRight, childBottom);
       childLeft = childLeft + childWidth;
       usedWidth = usedWidth + childWidth;
    
      }
     }
    
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    
      //   SimpleFlowLayout  view  SimpleFlowLayout              。
      //                 view   
      int widthMode = MeasureSpec.getMode(widthMeasureSpec);
      int heightMode = MeasureSpec.getMode(heightMeasureSpec);
      int widthSize = MeasureSpec.getSize(widthMeasureSpec);
      int heightSize = MeasureSpec.getSize(heightMeasureSpec);
    
    
      int usedWidth = 0;  //      
      int remaining = 0;  //      
      int totalHeight = 0; //   
      int lineHeight = 0;  //    
    
      for (int i = 0; i < getChildCount(); i++) {
       View childView = getChildAt(i);
       LayoutParams lp = childView.getLayoutParams();
    
       //    view
       measureChild(childView, widthMeasureSpec, heightMeasureSpec);
       //                             
       remaining = widthSize - usedWidth;
    
       //        ,       view                                
       if (childView.getMeasuredWidth() > remaining) {
        //         ,             0
        usedWidth = 0;
        //                   ,        
        totalHeight = totalHeight + lineHeight;
       }
    
       //    width      
       usedWidth = usedWidth + childView.getMeasuredWidth();
       //   view    
       lineHeight = childView.getMeasuredHeight();
      }
    
      //  SimpleFlowLayout      wrap cotent             ,  ,      view   SimpleFlowLayout      
      if (heightMode == MeasureSpec.AT_MOST) {
       heightSize = totalHeight;
      }
      setMeasuredDimension(widthSize, heightSize);
     }
    }
    마지막 으로 효 과 를 보 겠 습 니 다.

    총결산
    이상 은 이 글 의 전체 내용 입 니 다.본 논문 의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 참고 학습 가치 가 있 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 댓 글 을 남 겨 주 셔 서 저희 에 대한 지지 에 감 사 드 립 니 다.

    좋은 웹페이지 즐겨찾기