How do I compute the width and height of an inflated View if the parent is a PopupWindow, not a ViewGroup? I cannot use LayoutInflator.inflate(int resId, ViewGroup parent, attachToRoot boolean)
because PopupWindow is not a ViewGroup, so I use LayoutInflator.inflate(int resId)
instead, but after that I getWidth() and getHeight() return zero :(
I need to resize the PopupWindow to fit the View, but cannot do so until the View has a parent. Do I have a chicken-and-egg problem?
By the way the View is a subclass of RelativeView so calculating it manually is essentially out of the question.
Thanks in advance, Barry
Actually popupWindow supports "wrap content" constans, so if you want popup be exact as your view - use this:
popup = new PopupWindow(context);
popup.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);
popup.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
--other options--
getWidth()
and getHeight()
returns zero, because view have size only after drawing on the screen. You can try to get values from LayoutParams
of inflated view.
If there is fill_parent
value - you are in egg-chicken situation.
If there is values in px
or dp
you can manually calculate size in pixels:
Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpSize, context.getResources().getDisplayMetrics()));
If there is wrap_content
value - you can use view.measure()
method - all children and view itself will be measured, and you can get view.getMeasuredHeight()
and view.getMeasuredWidth()
.
As Jin35 said, your problem was that the view's width and height haven't been calculated yet...the dimensions aren't calculated until after the layout pass.
Using a fixed width and height from dimension resources (e.g. from a values/dimens.xml file) is one workaround, since then you don't need to wait for the view's onMeasure to occur -- you can get the value of the same dimension resource you used for the view you're interested in, and use that.
A better solution is to just delay your calculations until after the onMeasure happens. You can do that by overriding onMeasure, but a more elegant solution is to use a temporary OnGlobalLayoutListener like this:
View popup = LayoutInflator.inflate(int resId);
if(popup != null) {
// set up an observer that will be called once the listView's layout is ready
android.view.ViewTreeObserver viewTreeObserver = listView.getViewTreeObserver();
if (viewTreeObserver.isAlive()) {
viewTreeObserver.addOnGlobalLayoutListener(new android.view.ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
// This will be called once the layout is finished, prior to displaying.
View popup = findViewById(resId);
if(popup != null) {
int width = popup.getMeasuredWidth();
int height = popup.getMeasuredHeight();
// don't need the listener any more
popup.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
}
});
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With