207 layout lifecycle android android-widget measure
我有一个观点TableLayout, TableRow and TextView.我希望它看起来像一个网格.我需要得到这个网格的高度和宽度.这些方法getHeight()和getWidth()总是返回0.这发生在我和动态也格式化网格时我使用XML版本.
如何检索视图的尺寸?
这是我在Debug中用来检查结果的测试程序:
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
Run Code Online (Sandbox Code Playgroud)
kco*_*ock 415
我相信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);
}
}
});
Run Code Online (Sandbox Code Playgroud)
首先,我得到了对我的最终引用TextView(要在onGlobalLayout()方法中访问).接下来,我ViewTreeObserver从my 获取TextView,并添加一个OnGlobalLayoutListener覆盖onGLobalLayout(似乎没有超级类方法在这里调用...)并添加我的代码,这需要知道视图的测量值到这个监听器.一切都按预期的方式进行,所以我希望能够提供帮助.
Jus*_*yul 82
我将添加一个替代解决方案,覆盖您的活动的onWindowFocusChanged方法,您将能够从那里获取getHeight(),getWidth()的值.
@Override
public void onWindowFocusChanged (boolean hasFocus) {
// the height will be set at this point
int height = myEverySoTallView.getMeasuredHeight();
}
Run Code Online (Sandbox Code Playgroud)
Ale*_*lov 19
您正在尝试获取尚未绘制的元素的宽度和高度.
如果你在某些时候使用调试并停止,你会看到你的设备屏幕仍然是空的,那是因为你的元素还没有被绘制,所以你不能得到某些东西的宽度和高度,这还没有存在.
并且,我可能是错的,但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
}
}
});
Run Code Online (Sandbox Code Playgroud)
您可以直接放置此代码onCreate(),并在布局视图时调用它.
Bor*_*sev 15
像这样使用View的post方法
post(new Runnable() {
@Override
public void run() {
Log.d(TAG, "width " + MyView.this.getMeasuredWidth());
}
});
Run Code Online (Sandbox Code Playgroud)
我试图用来onGlobalLayout()做一些自定义格式化TextView,但正如@George Bailey注意到的那样,onGlobalLayout()确实被调用了两次:一次是在初始布局路径上,第二次是在修改文本之后.
View.onSizeChanged()对我来说效果更好,因为如果我在那里修改文本,该方法只被调用一次(在布局传递期间).这需要进行子类化TextView,但在API Level 11+ View. addOnLayoutChangeListener()上可以用来避免子类.
还有一件事,为了获得正确的视图宽度View.onSizeChanged(),layout_width应该设置为match_parent,而不是wrap_content.
您是否试图在构造函数或在获得实际图片之前运行的任何其他方法中获取尺寸?
在实际测量所有组件之前,您不会获得任何尺寸(因为您的 xml 不知道您的显示尺寸、父位置等)
尝试在 onSizeChanged() 之后获取值(尽管可以用零调用),或者只是等待获取实际图像。