如何检索视图的维度?
我有一个由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状态。
ViewTreeObserver
和onWindowFocusChanged()
根本不需要。
如果将TextView
充气为布局和/或放置一些内容并设置LayoutParams
则可以使用getMeasuredHeight()
和getMeasuredWidth()
。
但是你必须小心LinearLayouts
(也可能是其他ViewGroups
)。 问题在于,你可以在onWindowFocusChanged()
之后获得宽度和高度,但是如果你尝试在其中添加一些视图,那么直到所有内容都被绘制完毕,你将无法得到这些信息。 我试图添加多个TextViews
到LinearLayouts
来模仿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
就是这样。