我有一个由tableelayout, TableRow和TextView组成的视图。我想让它看起来像一个网格。我需要得到这个网格的高度和宽度。方法getHeight()和getWidth()总是返回0。当我动态格式化网格和使用XML版本时,就会发生这种情况。

如何检索视图的维度?


下面是我在调试中用来检查结果的测试程序:

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

当前回答

为视图使用getMeasuredWidth()和getMeasuredHeight()。

开发者指南:视图

其他回答

我猜这就是你需要看的:使用视图的onSizeChanged()。下面是一个关于如何使用onSizeChanged()来动态获取布局或视图的高度和宽度的扩展代码片段http://syedrakibalhasan.blogspot.com/2011/02/how-to-get-width-and-height-dimensions.html

你可以使用OnResume()中调用的广播

例如:

int vh = 0;   
int vw = 0;

public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.maindemo);  //<- includes the grid called "board"

      registerReceiver(new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                TableLayout tl = (TableLayout) findViewById(R.id.board);  
                tl = (TableLayout) findViewById(R.id.board);
                vh = tl.getHeight();       
                vw = tl.getWidth();               
            }
      }, new IntentFilter("Test"));
}

protected void onResume() {
        super.onResume();

        Intent it = new Intent("Test");
        sendBroadcast(it);

}

你不能在OnCreate (), onStart(),甚至在onResume()中获得视图的高度,原因是kcoppock响应

像这样使用视图的post方法

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

正如F.X.提到的,你可以使用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
    }
});

如果只需要初始布局,可以在回调中删除侦听器。

你试图得到一个元素的宽度和高度,这些元素还没有被画出来。

如果你使用调试并在某个点停止,你会看到,你的设备屏幕仍然是空的,那是因为你的元素还没有绘制,所以你不能得到宽度和高度,那还不存在。

而且,我可能是错的,但setWidth()并不总是尊重,布局布局它的孩子,并决定如何测量他们(调用child.measure()),所以如果你设置setWidth(),你不保证得到这个宽度后的元素将被绘制。

您需要的是在视图实际绘制之后的某个位置使用getMeasuredWidth()(视图的最新测量值)。

查看活动生命周期以找到最佳时刻。

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()中,当视图被布局时,它将被调用。