我什么时候可以测量一个视图? [英] When Can I First Measure a View?
问题描述
所以我有一个有点混乱,试图建立一个视图的背景绘制的,因为它是显示。在code依靠知道观的高度,所以我不能从的onCreate()
或 onResume()叫它code>,因为
的getHeight()
返回0 onResume()
似乎是最接近我能得到虽然。我应该在哪里把code如下面,这样在显示背景的变化给用户?
TextView的电视=(TextView中)findViewById(R.id.image_test);
LayerDrawable LD =(LayerDrawable)tv.getBackground();
INT高= tv.getHeight(); //当调用此以免得到0?
INT topInset =身高/ 2;
ld.setLayerInset(1,0,topInset,0,0);
tv.setBackgroundDrawable(LD);
我不知道 ViewTreeObserver.addOn preDrawListener()
,我试了一下在一个测试项目。
使用您的code就应该是这样的:
公共无效的onCreate(){
的setContentView(R.layout.main);
最后的TextView电视=(TextView中)findViewById(R.id.image_test);
最后LayerDrawable LD =(LayerDrawable)tv.getBackground();
最终ViewTreeObserver观测值= mTv.getViewTreeObserver();
obs.addOn preDrawListener(新ViewTreeObserver.On preDrawListener(){
@覆盖
在preDraw公共布尔(){
Log.d(TAG,在preDraw电视高度+ tv.getHeight()); //不好的表现,除去生产
INT高= tv.getHeight();
INT topInset =身高/ 2;
ld.setLayerInset(1,0,topInset,0,0);
tv.setBackgroundDrawable(LD);
返回true;
}
});
}
在我的测试项目在preDraw()
已叫了两声,我认为你的情况可能会导致一个无限循环。
您可以尝试调用 setBackgroundDrawable()
只有当的的TextView
的高度变化:
私人INT mLastTvHeight = 0;
公共无效的onCreate(){
的setContentView(R.layout.main);
最后的TextView电视=(TextView中)findViewById(R.id.image_test);
最后LayerDrawable LD =(LayerDrawable)tv.getBackground();
最终ViewTreeObserver观测值= mTv.getViewTreeObserver();
obs.addOn preDrawListener(新ViewTreeObserver.On preDrawListener(){
@覆盖
在preDraw公共布尔(){
Log.d(TAG,在preDraw电视高度+ tv.getHeight()); //不好的表现,除去生产
INT高= tv.getHeight();
如果(高度!= mLastTvHeight){
mLastTvHeight =高度;
INT topInset =身高/ 2;
ld.setLayerInset(1,0,topInset,0,0);
tv.setBackgroundDrawable(LD);
}
返回true;
}
});
}
不过,这听起来有点复杂,你要实现的目标和业绩不是很好的东西。
修改通过kcoppock
下面是我最终从这个code做的事情。戈蒂埃的回答让我到这一点,所以我宁愿接受这个答案与修改回答比我自己。最后我用了ViewTreeObserver的addOnGlobalLayoutListener()方法来代替,像这样(这是的onCreate()):
最后的TextView电视=(TextView中)findViewById(R.id.image_test);
ViewTreeObserver VTO = tv.getViewTreeObserver();
vto.addOnGlobalLayoutListener(新OnGlobalLayoutListener(){
@覆盖
公共无效onGlobalLayout(){
LayerDrawable LD =(LayerDrawable)tv.getBackground();
ld.setLayerInset(1,0,tv.getHeight()/ 2,0,0);
}
});
似乎很好地工作;我检查LogCat中,并没有看到任何异常活动。但愿这是它!谢谢!
So I have a bit of confusion with trying to set the background drawable of a view as it is displayed. The code relies upon knowing the height of the view, so I can't call it from onCreate()
or onResume()
, because getHeight()
returns 0. onResume()
seems to be the closest I can get though. Where should I put code such as the below so that the background changes upon display to the user?
TextView tv = (TextView)findViewById(R.id.image_test);
LayerDrawable ld = (LayerDrawable)tv.getBackground();
int height = tv.getHeight(); //when to call this so as not to get 0?
int topInset = height / 2;
ld.setLayerInset(1, 0, topInset, 0, 0);
tv.setBackgroundDrawable(ld);
I didn't know about ViewTreeObserver.addOnPreDrawListener()
, and I tried it in a test project.
With your code it would look like this:
public void onCreate() {
setContentView(R.layout.main);
final TextView tv = (TextView)findViewById(R.id.image_test);
final LayerDrawable ld = (LayerDrawable)tv.getBackground();
final ViewTreeObserver obs = mTv.getViewTreeObserver();
obs.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw () {
Log.d(TAG, "onPreDraw tv height is " + tv.getHeight()); // bad for performance, remove on production
int height = tv.getHeight();
int topInset = height / 2;
ld.setLayerInset(1, 0, topInset, 0, 0);
tv.setBackgroundDrawable(ld);
return true;
}
});
}
In my test project onPreDraw()
has been called twice, and I think in your case it may cause an infinite loop.
You could try to call the setBackgroundDrawable()
only when the height of the TextView
changes :
private int mLastTvHeight = 0;
public void onCreate() {
setContentView(R.layout.main);
final TextView tv = (TextView)findViewById(R.id.image_test);
final LayerDrawable ld = (LayerDrawable)tv.getBackground();
final ViewTreeObserver obs = mTv.getViewTreeObserver();
obs.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw () {
Log.d(TAG, "onPreDraw tv height is " + tv.getHeight()); // bad for performance, remove on production
int height = tv.getHeight();
if (height != mLastTvHeight) {
mLastTvHeight = height;
int topInset = height / 2;
ld.setLayerInset(1, 0, topInset, 0, 0);
tv.setBackgroundDrawable(ld);
}
return true;
}
});
}
But that sounds a bit complicated for what you are trying to achieve and not really good for performance.
EDIT by kcoppock
Here's what I ended up doing from this code. Gautier's answer got me to this point, so I'd rather accept this answer with modification than answer it myself. I ended up using the ViewTreeObserver's addOnGlobalLayoutListener() method instead, like so (this is in onCreate()):
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);
}
});
Seems to work perfectly; I checked LogCat and didn't see any unusual activity. Hopefully this is it! Thanks!
这篇关于我什么时候可以测量一个视图?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!