보기 그리 기 2 - onMeasure
역할.
onMeasure () - 외부 호출 패키지
|
setMeasured Dimension () - 측 정 된 점용 크기 를 View 에 설정 합 니 다.
|
getDefaultSize () - Min 크기 와 측량 크기 를 비교 하여 선택
|
getSuggest Minimum Width () - Min 크기 받 기
각각의 실현 코드 는 다음 과 같다.
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// widthMeasureSpec heightMeasureSpeac
setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
}
구체 적 인 실현 방법 은
setMeasuredDimension()
에 봉인 되 어 있다. protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
// ....
mMeasuredWidth = measuredWidth;
mMeasuredHeight = measuredHeight;
mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
}
public static int getDefaultSize(int size, int measureSpec) {
//size
int result = size;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
switch (specMode) {
//
case MeasureSpec.UNSPECIFIED:
result = size;
break;
//
case MeasureSpec.AT_MOST:
case MeasureSpec.EXACTLY:
result = specSize;
break;
}
return result;
}
getDefaultSize () 방법 은 MeasureSpec 의 specSize 를 되 돌려 줍 니 다. 이 specSize 는 View 의 측정 크기 입 니 다. View 의 최종 크기 는
layout()
에서 확 정 된 것 이지 만 specSize 의 크기 는 거의 모든 시간 layout()
에서 확 정 된 최종 크기 와 같 기 때 문 입 니 다. protected int getSuggestedMinimumWidth() {
//mMinWidth xml android:minSize , View.SetMinSize
return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
}
getSuggested MinimumWidth () 방법,
android:minWidth
설정 이 있 으 면 이 값 으로 폭 을 설정 하지만 Background 를 설정 한 경우 도 있 습 니 다. 이 경우 Background 와 minWidth 의 크기 를 비교 해 야 합 니 다.위 는 width Measure Spec 과 height Measure Spec 을 통 해 공간 크기 를 차지 하 는 과정 입 니 다. 본 소 원 width Measure Spec 과 height Measure Spec 는 어디에서 왔 습 니까?MeasureSpec 이 뭐 예요?
측정 규격, MeasureSpec 는 32 비트 int 수 표시, 역할
public static class MeasureSpec {
private static final int MODE_SHIFT = 30;
/** */
private static final int MODE_MASK = 0x3 << MODE_SHIFT;
/** */
public static final int UNSPECIFIED = 0 << MODE_SHIFT;
/** */
public static final int EXACTLY = 1 << MODE_SHIFT;
/** */
public static final int AT_MOST = 2 << MODE_SHIFT;
/** * */
public static int getMode(int measureSpec) {
return (measureSpec & MODE_MASK);
}
/** * */
public static int getSize(int measureSpec) {
return (measureSpec & ~MODE_MASK);
}
/** * */
public static int makeMeasureSpec(int size, int mode) {
if (sUseBrokenMakeMeasureSpec) {
return size + mode;
} else {
return (size & ~MODE_MASK) | (mode & MODE_MASK);
}
}
static int adjust(int measureSpec, int delta) {
return makeMeasureSpec(getSize(measureSpec + delta),
getMode(measureSpec));
}
}
이곳 의 소스 코드 는 이해 하기 쉬 운 삭 제 를 했다.MODE 로 표 시 를 정 의 했 습 니 다.MASK=3<<30;측정 모드 가 져 오기
public static int getMode(int measureSpec) {
return (measureSpec & MODE_MASK);
}
측정 데이터 가 져 오기
public static int getSize(int measureSpec) {
return (measureSpec & ~MODE_MASK);
}
이 int 형식의 데 이 터 는 32 비트 이 고 앞의 2 위 는 측정 모드 를 나타 내 며 뒤의 30 위 는 측정 데 이 터 를 나타 낸다.
MeasureSpec.UNSPECIFIED
는 부모 레이아웃 이 하위 레이아웃 에 대해 어떠한 제한 도 하지 않 는 다 는 것 을 나타 낸다. 하위 컨트롤 이 크 고 싶 은 만큼 큰 모델 은 일반적으로 깊이 연구 하지 않 고 일반 시스템 은 ListView 와 ScrollView 등 컨트롤 에 사용 된다.MeasureSpec.EXACTLY
View 의 크기 를 정확하게 제어 하 는 것 이 getSize () 가 되 돌아 오 는 값 임 을 나타 낸다 MeasureSpec.AT_MOST
는 하위 레이아웃 에서 자신 이 가리 키 지만 getSize () 의 참고 치 ViewGroup 에서 MeasureSpec 을 얻 는 과정
measureChildWithMargins
방법 으로 볼 때 protected void measureChildWithMargins(View child,
int parentWidthMeasureSpec, int widthUsed,
int parentHeightMeasureSpec, int heightUsed) {
final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec,
mPaddingLeft + mPaddingRight + lp.leftMargin + lp.rightMargin
+ widthUsed, lp.width);
final int childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec,
mPaddingTop + mPaddingBottom + lp.topMargin + lp.bottomMargin
+ heightUsed, lp.height);
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
}
5 개의 매개 변 수 를 포함 합 니 다: 자 View, 아버지
WidthMeasureSpec
, 아버지 HeightMeasureSpec
, 이미 사용 한 너비, 이미 사용 한 높이 의 실행 과정: 1. 먼저 LayoutParams
2. View 를 얻 는 WidthMeasureSpec
3. View 를 얻 는 HeightMeasureSpec
4. 측량 child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
public static int getChildMeasureSpec(int spec, int padding, int childDimension) {
int specMode = MeasureSpec.getMode(spec);
int specSize = MeasureSpec.getSize(spec);
int size = Math.max(0, specSize - padding);
int resultSize = 0;
int resultMode = 0;
switch (specMode) {
// Parent has imposed an exact size on us
case MeasureSpec.EXACTLY:
if (childDimension >= 0) {
resultSize = childDimension;
resultMode = MeasureSpec.EXACTLY;
} else if (childDimension == LayoutParams.MATCH_PARENT) {
// Child wants to be our size. So be it.
resultSize = size;
resultMode = MeasureSpec.EXACTLY;
} else if (childDimension == LayoutParams.WRAP_CONTENT) {
// Child wants to determine its own size. It can't be
// bigger than us.
resultSize = size;
resultMode = MeasureSpec.AT_MOST;
}
break;
// Parent has imposed a maximum size on us
case MeasureSpec.AT_MOST:
if (childDimension >= 0) {
// Child wants a specific size... so be it
resultSize = childDimension;
resultMode = MeasureSpec.EXACTLY;
} else if (childDimension == LayoutParams.MATCH_PARENT) {
// Child wants to be our size, but our size is not fixed.
// Constrain child to not be bigger than us.
resultSize = size;
resultMode = MeasureSpec.AT_MOST;
} else if (childDimension == LayoutParams.WRAP_CONTENT) {
// Child wants to determine its own size. It can't be
// bigger than us.
resultSize = size;
resultMode = MeasureSpec.AT_MOST;
}
break;
// Parent asked to see how big we want to be
case MeasureSpec.UNSPECIFIED:
if (childDimension >= 0) {
// Child wants a specific size... let him have it
resultSize = childDimension;
resultMode = MeasureSpec.EXACTLY;
} else if (childDimension == LayoutParams.MATCH_PARENT) {
// Child wants to be our size... find out how big it should
// be
resultSize = 0;
resultMode = MeasureSpec.UNSPECIFIED;
} else if (childDimension == LayoutParams.WRAP_CONTENT) {
// Child wants to determine its own size.... find out how
// big it should be
resultSize = 0;
resultMode = MeasureSpec.UNSPECIFIED;
}
break;
}
return MeasureSpec.makeMeasureSpec(resultSize, resultMode);
}
실행 과정 1. 부모 specMode 와 specSize 가 져 오기 2. 수평 (수직) 방향 최대 사용 가능 한 공간 size 가 져 오기 3. specMode 와 childDimension (view 의 공간 크기) 을 통 해 하위 View 의 MeasureSpec 를 확인 합 니 다. 하위 View 컨트롤 의 점용 크기 는 하위 View 와 그의 ViewGroup 이 공동으로 결정 한 것 임 을 알 고 있 습 니 다. 구체 적 인 관 계 는 다음 표를 참고 하 십시오.
parentSpecMode & childViewSize
EXACTLY
AT_MOST
UNSPECIFIED
확 정 된 값: 100 dp
EXACTILY & childSize
AT_MOST& childSize
AT_MOST& childSize
match_parent
EXACTILY & parentLeftSize
AT_MOST& parentLeftSize
UNSPECIFIED & 0
wrap_content
AT_MOST& parentLeftSize
AT_MOST& parentLeftSize
UNSPECIFIED & 0
시 계 를 통 해 제거 할 수 있 습 니 다. 하위 View 가 구체 적 인 값 이 라면 부모 View Group 의 측정 모드 에 관 계 없 이 그 는
EXACTILY + View
입 니 다.사용자 정의 View 우리 가 뭘 더 해 야 하 는 지
parentSpecMode & childViewSize
EXACTLY
AT_MOST
UNSPECIFIED
확 정 된 값: 100 dp
EXACTILY & childSize
AT_MOST& childSize
AT_MOST& childSize
match_parent
EXACTILY & parentLeftSize
AT_MOST& parentLeftSize
UNSPECIFIED & 0
wrap_content
AT_MOST& parentLeftSize
AT_MOST& parentLeftSize
UNSPECIFIED & 0
원본 코드 에서 얻 은 표 에 굵 은 기울 임 꼴 두 가 지 를 추가 하 는 것 은 논리 적 으로 문제 가 있 습 니 다. 예 를 들 어 하나의 컨트롤 이 그의 높이 를
android:height=wrap_content
로 지정 하면 아버지 View Group 의 크기 와 일치 하 는 것 이 아니 라 그 자신 이 높이 를 설정 해 야 합 니 다.AT_MOST& parentLeftSize
wrap 로 설정content 와 matchparent 는 다 르 지 않 습 니 다. 실제로 시스템 사용자 정의 컨트롤 TextView ImageView
의 onMeasure
방법 도 바 뀌 었 습 니 다. wrap_content
모드 에서 하위 View 가 자신의 크기 를 가리 키 도록 합 니 다.다시 쓰기 onMeasure()
구현 코드:protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// ,
super.onMeasure(widthMeasureSpec , heightMeasureSpec);
int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSpceSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSpecMode=MeasureSpec.getMode(heightMeasureSpec);
int heightSpceSize=MeasureSpec.getSize(heightMeasureSpec);
// At_Most if(widthSpecMode==MeasureSpec.AT_MOST&&heightSpecMode==MeasureSpec.AT_MOST){
setMeasuredDimension(mWidth, mHeight);
}else if(widthSpecMode==MeasureSpec.AT_MOST){
setMeasuredDimension(mWidth, heightSpceSize);
}else if(heightSpecMode==MeasureSpec.AT_MOST){
setMeasuredDimension(widthSpceSize, mHeight);
}
}
위의 코드 에서 wrap콘 텐 츠 를 설정 할 때
mWidth mHeight
에 기본 높이 를 설정 하면 됩 니 다. 구체 적 인 값 은 구체 적 으로 분석 해 야 합 니 다.논리 적 으로 아직도 잘못된 점 이 존재 한다
parentSpecMode & childViewSize
EXACTLY
AT_MOST
UNSPECIFIED
확 정 된 값: 100 dp
EXACTILY & childSize
AT_MOST& childSize
AT_MOST& childSize
match_parent
EXACTILY & parentLeftSize
AT_MOST& parentLeftSize
UNSPECIFIED & 0
wrap_content
AT_MOST& parentLeftSize
AT_MOST& parentLeftSize
UNSPECIFIED & 0
분석 자 View 가
math_parent
아버지 View Group 이 AT 라면모스 트 의 경 우 는 존재 하 는가?마지막.
measure 과정 은 View 3 대 절차 중 가장 복잡 한 것 으로 measure 가 완 성 된 후에
getWidthMeasure() getHeightMeasure()
방법 을 통 해 정확 한 너비 와 높이 를 얻 을 수 있다.그러나 일부 특수 한 상황 에서 시스템 은 여러 번 measure 를 해 야 최종 너비 와 높이 를 확정 할 수 있 고 상황 에 따라 onMeasure 방법 에서 얻 은 측정 너비 가 정확 하지 않 을 수 있다.좋 은 습관 은 onLayout()
에서 View 의 측정 너비 와 최종 너비 와 높이 를 얻 는 것 이다.Activity 가 시작 되 자마자 View 의 너비 와 높이 를 가 져 오 는 것 이 필요 합 니 다.라 이 프 사이클 방법 onCreate()/onStart()/onResume()
에서 생각 할 수 있 지만 measure 와 라 이 프 사이클 방법 이 일치 하지 않 습 니 다. 특정한 라 이 프 사이클 방법 에서 얻 고 measure 가 아직 실행 되 지 않 았 을 때 받 은 값 은 0 일 가능성 이 높 습 니 다. onWindowFocusChanged()
View 를 통 해 그 려 진 후에 초점 이 바 뀔 것 입 니 다. 또한 onResume 과 onPause 를 자주 진행 하면 onWindowFocusChanged()
코드 도 실행 합 니 다: @Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
int width = view.getMeasuredWidth();
int height = view.getMeasuredHeight();
}
}
view 에서 스 레 드 post 메 시 지 를 끝 에 그립 니 다. view 그리 기 가 완료 되면 이 runnable 을 실행 합 니 다.
@Override
protected void onStart() {
super.onStart();
view.post(new Runnable() {
@Override
public void run() {
int width = view.getMeasuredWidth();
int height = view.getMeasuredHeight();
}
});
}
참고: - 임 옥 강
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Getting Started with Zend Framework 2 - ViewBy default, the action and view in the controller are one-to-one correspondence, such as HellowordController::indexActio...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.