I have a custom View
to represent an ImageView with a parallax effect, adapted from the one found in the answer to this SO question: How to have a wider image scrolling in the background.
The View
has a setBackgroundDrawable()
method to set its background image that does some calculations to know the size that the bitmap should have in order to be wide enough to be scrolled with a parallax effect, if cropping is needed to keep the aspect ratio, etc.
I'm getting an "IllegalArgumentException: width and height must be > 0
" in
(...)
int width = this.getWidth();
int height = this.getHeight();
Bitmap mCurrentBackground=Bitmap.createBitmap((int) (width*FACTOR), height, Config.ARGB_8888);
(...)
because getWidth()
and getHeight()
are returning zero.
I understand that this is happening because the View doesn't know its own size yet when I call the said function, for example, in an Activity's onCreate
method. Same thing happens if I try to set the background in onStart
or onResume
...
I've managed to set the background if I call the function in onWindowFocusChanged()
, but I still get the error sometimes (e.g. if I switch the screen orientation when an EditText
is focused).
Is there a way to get around this? Any kind of callback or phase in the lifecycle where the whole View was created (like the onViewCreated from the Fragment class)? I can only call my custom View's setBackgroundDrawable
after the View has been assigned a height and a width.
EDIT:
I have also tried adding a GlobalLayoutListener
to the View's 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);
}
}
});
but it results in the same behavior I get from setting the background in the onWindowFocusChanged()
method. I.e. the gedtWidth()
/getHeight()
return zero inside the listener's onGlobalLayout
if I switch the phone's orientation when an EditText
is selected.
EDIT 2:
It probably has something to do with the keyboard as I observed some behavior like the height being calculated taking the keyboard's existence into account.
Deleting:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
obs.removeOnGlobalLayoutListener(this);
} else {
obs.removeGlobalOnLayoutListener(this);
}
from my onGlobalLayout
shown in the first EDIT seems to do the trick.