[android] onMeasure ()를 재정의하는 권위있는 방법?

onMeasure ()를 재정의하는 올바른 방법은 무엇입니까? 다양한 접근 방식을 보았습니다. 예를 들어, Professional Android Development 는 MeasureSpec을 사용하여 차원을 계산 한 다음 setMeasuredDimension ()에 대한 호출로 끝납니다. 예를 들면 :

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
this.setMeasuredDimension(parentWidth/2, parentHeight);
}

반면 에이 게시물 에 따르면 “올바른”방법은 MeasureSpec을 사용하고 setMeasuredDimensions () 를 호출 한 다음 setLayoutParams ()를 호출 한 다음 super.onMeasure () 를 호출하는 것입니다. 예를 들면 :

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
this.setMeasuredDimension(parentWidth/2, parentHeight);
this.setLayoutParams(new *ParentLayoutType*.LayoutParams(parentWidth/2,parentHeight));
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

그렇다면 올바른 방법은 무엇입니까? 어느 쪽도 100 % 효과가 없었습니다.

나는 정말로 내가 묻는 것은 onMeasure (), 레이아웃, 자식 뷰의 크기 등을 설명하는 자습서를 아는 사람이 있습니까?



답변

다른 솔루션은 포괄적이지 않습니다. 어떤 경우에는 작동 할 수 있으며 시작하기에 좋은 곳이지만 작동이 보장되지 않을 수 있습니다.

onMeasure가 호출되면 크기를 변경할 수있는 권한이있을 수도 있고 없을 수도 있습니다. onMeasure ( widthMeasureSpec, heightMeasureSpec)에 전달되는 값 에는 자식보기에서 수행 할 수있는 작업에 대한 정보가 포함됩니다. 현재 세 가지 값이 있습니다.

  1. MeasureSpec.UNSPECIFIED -원하는만큼 커질 수 있습니다.
  2. MeasureSpec.AT_MOST-원하는만큼 크게 (사양 크기까지), 이것은 parentWidth귀하의 예입니다.
  3. MeasureSpec.EXACTLY– 선택의 여지가 없다. 부모가 선택했습니다.

이는 Android가 각 항목에 적합한 크기를 찾기 위해 여러 번 통과 할 수 있도록 하기위한 것입니다. 자세한 내용 은 여기 를 참조하세요.

이러한 규칙을 따르지 않으면 접근 방식이 제대로 작동하지 않을 수 있습니다.

예를 들어 크기 변경이 허용되는지 확인하려면 다음을 수행 할 수 있습니다.

final int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
final int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
boolean resizeWidth = widthSpecMode != MeasureSpec.EXACTLY;
boolean resizeHeight = heightSpecMode != MeasureSpec.EXACTLY;

이 정보를 사용하면 코드에서와 같이 값을 수정할 수 있는지 여부를 알 수 있습니다. 또는 다른 일을해야하는 경우. 원하는 크기를 확인하는 빠르고 쉬운 방법은 다음 방법 중 하나를 사용하는 것입니다.

int resolveSizeAndState (int 크기, int measureSpec, int childMeasuredState)

int resolveSize (int size, int measureSpec)

첫 번째는 Honeycomb에서만 사용할 수 있지만 두 번째는 모든 버전에서 사용할 수 있습니다.

참고 : resizeWidth또는 resizeHeight항상 거짓 임을 알 수 있습니다 . 내가 요청한 경우이 사실을 알았습니다 MATCH_PARENT. WRAP_CONTENT부모 레이아웃 을 요청한 다음 UNSPECIFIED 단계에서 크기를 요청 하여이 문제를 해결할 수있었습니다 Integer.MAX_VALUE. 이렇게하면 부모가 onMeasure를 통과 할 때 허용하는 최대 크기가 제공됩니다.


답변

문서는이 문제에 대한 권한입니다 : http://developer.android.com/guide/topics/ui/how-android-draws.htmlhttp://developer.android.com/guide/topics/ui/custom -components.html

요약하면 : 재정의 된 onMeasure메서드 의 끝에서 setMeasuredDimension.

을 (를) 호출 super.onMeasure한 후 호출 하면 안됩니다 setMeasuredDimension. 설정 한 내용이 지워집니다. 어떤 상황에서는를 super.onMeasure먼저 호출 한 다음을 호출하여 결과를 수정할 수 setMeasuredDimension있습니다.

호출하지 마십시오 setLayoutParams에서 onMeasure. 레이아웃은 측정 후 두 번째 단계에서 발생합니다.


답변

나는 그것이 당신이 무시하는 부모에 달려 있다고 생각합니다.

예를 들어 FrameLayout과 같은 ViewGroup을 확장하는 경우 크기를 측정 할 때 아래와 같이 호출해야합니다.

super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
                MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));

ViewGroup이 나머지 작업을 수행하기를 원할 수 있기 때문입니다 (자식보기에서 일부 작업 수행).

View를 확장하는 경우 (예 : ImageView) this.setMeasuredDimension(width, height); . 부모 클래스는 일반적으로했던 것과 같은 작업을 수행하기 때문입니다.

한마디로, 부모 클래스가 무료로 제공하는 일부 기능을 원한다면 호출해야합니다 super.onMeasure()(보통 MeasureSpec.EXACTLY 모드 측정 스펙 통과). 그렇지 않으면 호출 this.setMeasuredDimension(width, height);로 충분합니다.


답변

문제를 해결 한 방법은 다음과 같습니다.

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        ....

        setMeasuredDimension( measuredWidth, measuredHeight );

        widthMeasureSpec = MeasureSpec.makeMeasureSpec( measuredWidth, MeasureSpec.EXACTLY );
        heightMeasureSpec = MeasureSpec.makeMeasureSpec( measuredHeight, MeasureSpec.EXACTLY);

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

}

또한 ViewPager 구성 요소가 필요했습니다.


답변

내부에서보기 크기를 변경하는 경우 onMeasure 하면 필요한 모든 것이 setMeasuredDimension호출됩니다. 외부에서 크기를 변경 onMeasure하려면을 호출해야합니다 setLayoutParams. 예를 들어 텍스트가 변경 될 때 텍스트보기의 크기를 변경합니다.


답변

사용중인 컨트롤에 따라 다릅니다. 설명서의 지침은 일부 컨트롤 (TextView, Button, …)에 대해서는 작동하지만 다른 컨트롤 (LinearLayout, …)에는 작동하지 않습니다. 나를 위해 아주 잘 작동하는 방법은 내가 끝나면 수퍼를 부르는 것이 었습니다. 아래 링크의 기사를 기반으로합니다.

http://humptydevelopers.blogspot.in/2013/05/android-view-overriding-onmeasure.html


답변

setLayoutParams 및 측정 값 재계 산은 일반적으로 파생 클래스의 onMeasure에서 수행되므로 자식 뷰의 크기를 올바르게 조정하는 해결 방법이라고 생각합니다.

그러나 이것은 거의 올바르게 작동하지 않습니다 (어떤 이유로 든 …), measureChildren을 더 잘 호출하거나 (ViewGroup을 파생시킬 때) 필요할 때 비슷한 것을 시도하십시오.