我有一个由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

当前回答

我试图使用onGlobalLayout()做一些自定义格式的TextView,但@乔治贝利注意到,onGlobalLayout()确实被调用两次:一次在初始布局路径上,第二次修改文本后。

View.onSizeChanged()对我来说工作得更好,因为如果我在那里修改文本,该方法只被调用一次(在布局传递期间)。这需要子类化TextView,但在API级别11+视图。addOnLayoutChangeListener()可以用来避免子类化。

还有一件事,为了在view . onsizechanged()中获得正确的视图宽度,layout_width应该设置为match_parent,而不是wrap_content。

其他回答

我猜这就是你需要看的:使用视图的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响应

您是否试图在构造函数中获取大小,或在获得实际图片之前运行的任何其他方法?

在所有组件实际测量之前,你不会得到任何尺寸(因为你的xml不知道你的显示大小,父节点位置等等)

尝试在onSizeChanged()之后获取值(尽管它可以用零调用),或者只是简单地等待,当你得到一个实际的图像。

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

开发者指南:视图

即使建议的解决方案有效,但它可能不是针对每种情况的最佳解决方案,因为根据ViewTreeObserver的文档。OnGlobalLayoutListener

当全局布局状态或视图树中视图的可见性发生变化时,将调用回调的接口定义。

这意味着它会被多次调用,并不总是测量视图(它的高度和宽度是确定的)

另一种方法是使用ViewTreeObserver。OnPreDrawListener只在视图准备好绘制并拥有所有测量值时被调用。

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

    @Override
    public void onPreDraw() {
        tv.getViewTreeObserver().removeOnPreDrawListener(this);
        // Your view will have valid height and width at this point
        tv.getHeight();
        tv.getWidth();
    }

});