自定义视图的getHeight和getWidth返回0

时间:2014-02-12 17:56:56

标签: android android-activity android-view activity-lifecycle

我有一个自定义View来表示具有视差效果的ImageView,它改编自这个SO问题答案中的How to have a wider image scrolling in the background

View有一个setBackgroundDrawable()方法来设置其背景图像,进行一些计算以了解位图应具有的大小,以便足够宽以使用视差效果滚动,如果需要裁剪以保持纵横比等。

我在

中收到了“IllegalArgumentException: width and height must be > 0
(...)

int width = this.getWidth();
int height = this.getHeight();

Bitmap mCurrentBackground=Bitmap.createBitmap((int) (width*FACTOR), height, Config.ARGB_8888);

(...)

因为getWidth()getHeight()返回零。

我理解这种情况正在发生,因为当我调用所述函数时,View还不知道它自己的大小,例如,在Activity的onCreate方法中。如果我尝试在onStartonResume ...

中设置背景,也会发生同样的事情

如果我在onWindowFocusChanged()中调用该函数,我已设法设置背景,但有时我仍然会收到错误(例如,如果我在关注EditText时切换屏幕方向)。< / p>

有没有办法解决这个问题?生命周期中创建整个View的任何类型的回调或阶段(如Fragment类中的onViewCreated)?在为视图指定了高度和宽度后,我只能调用自定义视图setBackgroundDrawable

修改

我还尝试在视图GlobalLayoutListener中添加ViewTreeObserver

ViewTreeObserver vto = parallaxBackground.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {

    @SuppressLint("NewApi")
    @Override
    public void onGlobalLayout() {

                    ...

        parallaxBackground.setBackgroundDrawable(d1);

            ViewTreeObserver obs = parallaxBackground.getViewTreeObserver();

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                obs.removeOnGlobalLayoutListener(this);
            } else {
                obs.removeGlobalOnLayoutListener(this);
            }
        }

    });

但它会导致我在onWindowFocusChanged()方法中设置背景时获得的相同行为。即如果我在选择gedtWidth()时切换手机的方向,则getHeight() / onGlobalLayout会在听众的EditText内返回零。

编辑2:

它可能与键盘有关,因为我观察到一些行为,例如考虑到键盘存在而计算的高度。

删除:

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                obs.removeOnGlobalLayoutListener(this);
            } else {
                obs.removeGlobalOnLayoutListener(this);
            }
来自第一个EDIT中显示的onGlobalLayout

似乎可以解决问题。

1 个答案:

答案 0 :(得分:1)

我不确定你的情况,但我前段时间使用过这个。只需使用ViewObserver即可。就我而言,我使用过这样的东西:

final ViewTreeObserver treeObs = dataView.getViewTreeObserver();

treeObs.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
  @Override
  public void onGlobalLayout() {
    // This will be called when the layout is finished, just before displaying
    ...
  }
}