我什么时候可以先测量视图? [英] When Can I First Measure a View?

查看:24
本文介绍了我什么时候可以先测量视图?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我在尝试设置视图显示的背景可绘制时有点困惑.代码依赖于知道视图的高度,所以我不能从 onCreate()onResume() 调用它,因为 getHeight() 返回 0. onResume() 似乎是我能得到的最接近的.我应该在哪里放置如下代码,以便在向用户显示时背景会发生变化?

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

推荐答案

我不知道ViewTreeObserver.addOnPreDrawListener(),我在一个测试项目中尝试过.

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 = tv.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;
   }
});
}

在我的测试项目中,onPreDraw() 被调用了两次,我认为在你的情况下它可能会导致无限循环.

In my test project onPreDraw() has been called twice, and I think in your case it may cause an infinite loop.

您可以尝试仅在 TextView 的高度发生变化时调用 setBackgroundDrawable() :

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.

由 kcoppock 编辑

这是我从这段代码中得到的结果.Gautier 的回答让我走到了这一步,所以我宁愿修改后接受这个答案,也不愿自己回答.我最终使用了 ViewTreeObserver 的 addOnGlobalLayoutListener() 方法,就像这样(这是在 onCreate() 中):

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

似乎工作完美;我检查了 LogCat 并没有看到任何异常活动.希望就是这样!谢谢!

Seems to work perfectly; I checked LogCat and didn't see any unusual activity. Hopefully this is it! Thanks!

这篇关于我什么时候可以先测量视图?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆