如何检索视图的维度?

我有一个由tablelayout,tablerows和textviews组成的视图。 我希望它看起来像一个网格。 我需要得到这个网格的高度和宽度。 方法getheight()和getwidth()总是返回0.这种情况发生时,我dynamic格式化网格,也是当我使用xml版本。

如何检索视图的尺寸?


这里是我在Debug中使用的testing程序来检查结果:

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已经走了,但是如果这个答案能够帮助未来的search者,我想我会发布一个我find的解决scheme。 我已经添加了这个代码到我的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()方法中访问)。 接下来,我从我的TextView获取ViewTreeObserver ,并添加一个OnGlobalLayoutListener ,覆盖onGLobalLayout (似乎没有超类方法来调用这里…),并添加需要知道视图的度量值的代码。 所有的工作如我所料,所以我希望这能够提供帮助。

我只是添加一个替代解决scheme,重写您的活动的onWindowFocusChanged方法,您将能够从那里获取getHeight(),getWidth()的值。

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

你正试图获得一个元素的宽度和高度,还没有绘制。

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

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

你需要的是在实际绘制视图之后的某个地方使用getMeasuredWidth() (你的视图的最新度量)。

查看Activity生命周期以find最佳时刻。

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()放置这段代码,并且在布置视图时调用它。

使用视图的post方法是这样的

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

我尝试使用onGlobalLayout()来做一些自定义格式的TextView ,但正如@George Bailey所注意到的, onGlobalLayout()确实被调用了两次:一次在初始布局path,第二次在修改文本后。

View.onSizeChanged()对我更好,因为如果我修改那里的文本,该方法只被调用一次(在布局过程中)。 这需要对TextView进行子分类,但在API Level 11+ View. addOnLayoutChangeListener() View. addOnLayoutChangeListener()可以用来避免子分类。

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

如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 } }); 

如果您只想要初始布局,则可以在callback中删除该侦听器。

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

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

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

尝试获取onSizeChanged()之后的值(尽pipe可以用零调用),或者只是简单地等待何时获得实际的图像。

你应该看看视图生命周期: http : //developer.android.com/reference/android/view/View.html通常你不应该知道宽度和高度,直到你的活动进入onResume状态。

ViewTreeObserveronWindowFocusChanged()根本不需要。

如果将TextView充气为布局和/或放置一些内容并设置LayoutParams则可以使用getMeasuredHeight()getMeasuredWidth()

但是你必须小心LinearLayouts (也可能是其他ViewGroups )。 问题在于,你可以在onWindowFocusChanged()之后获得宽度和高度,但是如果你尝试在其中添加一些视图,那么直到所有内容都被绘制完毕,你将无法得到这些信息。 我试图添加多个TextViewsLinearLayouts来模仿FlowLayout (包装样式),所以不能使用Listeners 。 一旦进程启动,它应该继续同步。 所以在这种情况下,您可能希望将宽度保留在一个variables中,以便稍后使用它,因为在将视图添加到布局时,您可能需要使用它。

您可以使用在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响应

简单的回应:这对我来说没有问题。 看起来关键是要确保View在getHeight之前已经聚焦等。通过使用hasFocus()方法,然后使用getHeight()方法来执行此操作。 只需要3行代码。

ImageButton myImageButton1 =(ImageButton)findViewById(R.id.imageButton1); myImageButton1.hasFocus();

int myButtonHeight = myImageButton1.getHeight();

Log.d("Button Height: ", ""+myButtonHeight );//Not required

希望它有帮助。

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

开发者指南:查看

更正:我发现上述解决scheme是可怕的。 特别是当你的手机速度很慢时。 在这里,我find了另一个解决scheme:计算出元素的px值,包括边距和填充:dp to px: https : //stackoverflow.com/a/6327095/1982712

或者dimens.xml到px: https ://stackoverflow.com/a/16276351/1982712

SP到PX: https : //stackoverflow.com/a/9219417/1982712 (扭转解决scheme)

或维度px: https ://stackoverflow.com/a/16276351/1982712

就是这样。