[android] 뷰의 치수를 검색하는 방법은 무엇입니까?

보기로 구성되어 TableLayout, TableRow and TextView있습니다. 그리드처럼 보이기를 원합니다. 이 그리드의 높이와 너비를 가져와야합니다. 방법 getHeight()getWidth()항상 내가이 XML 버전을 사용할 때 동적으로도 그리드를 포맷 할 때 발생 0으로 돌아갑니다.

뷰의 치수를 검색하는 방법은 무엇입니까?


결과를 확인하기 위해 디버그에서 사용한 테스트 프로그램은 다음과 같습니다.

import android.app.Activity;
import android.os.Bundle;
import android.widget.TableLayout;
import android.widget.TextView;

public class appwig extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.maindemo);  //<- includes the grid called "board"
      int vh = 0;
      int vw = 0;

      //Test-1 used the xml layout (which is displayed on the screen):
      TableLayout tl = (TableLayout) findViewById(R.id.board);
      tl = (TableLayout) findViewById(R.id.board);
      vh = tl.getHeight();     //<- getHeight returned 0, Why?  
      vw = tl.getWidth();     //<- getWidth returned 0, Why?   

      //Test-2 used a simple dynamically generated view:        
      TextView tv = new TextView(this);
      tv.setHeight(20);
      tv.setWidth(20);
      vh = tv.getHeight();    //<- getHeight returned 0, Why?       
      vw = tv.getWidth();    //<- getWidth returned 0, Why?

    } //eof method
} //eof class



답변

OP가 오랫동안 사라 졌다고 생각하지만이 답변이 향후 검색자를 도울 수있는 경우 내가 찾은 솔루션을 게시 할 것이라고 생각했습니다. 이 코드를 onCreate()메소드에 추가했습니다 .

편집 : 의견의 코드를 포함하도록 07/05/11 :

final TextView tv = (TextView)findViewById(R.id.image_test);
ViewTreeObserver vto = tv.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {

    @Override
    public void onGlobalLayout() {
        LayerDrawable ld = (LayerDrawable)tv.getBackground();
        ld.setLayerInset(1, 0, tv.getHeight() / 2, 0, 0);
        ViewTreeObserver obs = tv.getViewTreeObserver();

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            obs.removeOnGlobalLayoutListener(this);
        } else {
            obs.removeGlobalOnLayoutListener(this);
        }
    }

});

먼저 내 방법 TextView에 대한 최종 참조를 얻습니다 onGlobalLayout(). 다음으로, 내가 얻을 ViewTreeObserver내에서 TextView, 그리고 추가 OnGlobalLayoutListener, 오버라이드 (override) onGLobalLayout이 청취자로보기의 측정 값을 알 필요 내 코드를 추가 (… 여기에 호출하는 슈퍼 클래스의 방법이 될 것 같지 않습니다). 모든 것이 예상대로 작동하므로 이것이 도움이되기를 바랍니다.


답변

대안 솔루션을 추가하고 활동의 onWindowFocusChanged 메소드를 재정의하면 getHeight (), getWidth () 값을 얻을 수 있습니다.

@Override
public void onWindowFocusChanged (boolean hasFocus) {
        // the height will be set at this point
        int height = myEverySoTallView.getMeasuredHeight();
}


답변

아직 그려지지 않은 요소의 너비와 높이를 얻으려고합니다.

디버그를 사용하고 어느 시점에서 멈 추면 장치 화면이 여전히 비어 있습니다. 요소가 아직 그려지지 않았기 때문에 아직 너비와 높이를 얻을 수 없기 때문입니다. 있다.

그리고, 내가 틀렸을 수도 있지만 setWidth()항상 존중되는 것은 아니며, Layout아이들을 배치하고 그들을 측정하는 방법을 결정 ()하는 방법을 결정합니다 child.measure(). 따라서 설정 setWidth()하면 요소를 그린 후에이 너비를 얻을 수 없습니다.

필요한 getMeasuredWidth()것은 뷰가 실제로 그려진 후 어딘가에 (가장 최근의 뷰 측정) 사용하는 것입니다.

Activity최고의 순간을 찾기 위해 수명주기를 살펴보십시오 .

http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle

다음 OnGlobalLayoutListener과 같이 사용하는 것이 좋습니다 .

yourView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            if (!mMeasured) {
                // Here your view is already layed out and measured for the first time
                mMeasured = true; // Some optional flag to mark, that we already got the sizes
            }
        }
    });

이 코드를에 직접 onCreate()배치 할 수 있으며 뷰가 배치 될 때 호출됩니다.


답변

이와 같이 View의 post 메소드를 사용하십시오.

post(new Runnable() {
    @Override
    public void run() {
        Log.d(TAG, "width " + MyView.this.getMeasuredWidth());
        }
    });


답변

나는 onGlobalLayout()몇 가지 사용자 정의 형식을 수행하는 데 사용하려고TextView 있지만, @George 베일리 눈치로, onGlobalLayout()실제로 두 번 호출되어 초기 레이아웃 경로에 한 번, 그리고 두 번째 텍스트를 수정 한 후.

View.onSizeChanged()거기에서 텍스트를 수정하면 메소드가 한 번만 호출되기 때문에 (레이아웃 패스 중에) 더 잘 작동합니다. 이를 위해서는 서브 클래 싱이 필요합니다.TextView 했지만 API 레벨 11+ View. addOnLayoutChangeListener()에서는 서브 클래 싱을 피할 수 있습니다.

한 가지 더,에 뷰의 정확한 폭을 얻기 위하여 View.onSizeChanged()layout_width에 설정해야합니다 match_parent,하지 wrap_content.


답변

생성자 또는 실제 그림을 얻기 전에 실행되는 다른 방법으로 크기를 얻으려고합니까?

모든 구성 요소가 실제로 측정되기 전에 치수를 얻지 못합니다 (xml이 디스플레이 크기, 부모 위치 등을 알지 못하기 때문에)

onSizeChanged () 후에 값을 가져 오거나 (0으로 호출 할 수 있음) 실제 이미지를 얻을 때까지 기다리십시오.


답변

FX가 언급했듯이, 당신은 OnLayoutChangeListener당신이 추적하고자하는보기에 사용할 수 있습니다

view.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
    @Override
    public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
        // Make changes
    }
});

초기 레이아웃 만 원하는 경우 콜백에서 리스너를 제거 할 수 있습니다.