I have an ImageView which has layout_width of fill_parent. I want to get the width of this ImageView in order to calculate the size of the thumbnail. The problem is that imageView.getWidth() and imageView.getHeight() both return 0 because the layout hasn't been sat yet.
My question is, does the ImageView has some kind of SizeChanged event or something of the kind? How do I react as soon as the ImageView width has been established?
Update:
I solved my problem this way. As I actually only needed the width of the ImageView which is set to fill_parent, what I actually needed was the device window size:
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
int targetW = metrics.widthPixels;
You can hook into a number of View tree events using a ViewTreeObserver. Specifically, either an OnGlobalLayoutListener or an OnPreDrawListener should work for you depending on what you are doing with the size.
Here's an example of using a ViewTreeObserverto get a View's width once everything has been laid out:
final ImageView myImageView = (ImageView) findViewById(R.id.image);
final ViewTreeObserver observer = myImageView.getViewTreeObserver();
observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
int height = myImageView.getHeight();
// Do something with the height
// Remove the layout listener so we don't waste time on future passes
observer.removeOnGlobalLayoutListener(this);
}
});
According to this post's answer:
ImageView.getWidth() returns 0
You will need to call it from the following function:
public void onWindowFocusChanged(boolean hasFocus)
This is because the window has not yet been attached and as you have noticed your imageview will have no dimensions yet.
Related
When I set an ImageView bitmap on create of an Activity. At what point can I read the final width of the ImageView?
What seems to happen is the bitmap is set in the onCreate() method and immediately is assigned the width of 965 which I can see when entering the onLayout method of the ImageView, then more of the layout/creation occurs and the ImageView width changes to 909 (I guess this is due to the adjustment to the screen size?).
What I want to do is read the final value of 909 to set the width of another view programmatically.
I've tried the addOnGlobalLayoutListener of the ImageView to try to listen of the completion of the layout, however reading the getMeasuredWidth() method of the ImageView still returns the 965 value.
What is the final event called once the layout calculations are completing which will allow me to set the width of another view during the creation.
You need to wait for Activity window to be attached and then get the ImageView width. To do that, you can override onWindowFocusChanged() method of the Activity:
#Override
public void onWindowFocusChanged(boolean hasFocus){
int imageWidth = yourImageView.getWidth();
}
As a second suggestion:
You can also add a OnPreDrawListener and use his onPreDraw() method
At this point, all views in the tree have been measured and given a
frame
ViewTreeObserver vto = yourImageView.getViewTreeObserver();
vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
public boolean onPreDraw() {
int imageWidth = yourImageView.getMeasuredWidth();
return true;
}
});
You can access the final width in the onStart() once the onCreate() has finished.
I want to get width and height of ImageView.
myimgbg = (ImageView) findViewById(R.id.myimggb);
myimgbg.setBackgroundResource(R.drawable.dudu_1);
The other answers demonstrate how to get the dimensions, but you are trying to do it too early, before the layout has been measured. This is how you do this but I am pretty sure you should never need to do this - there is almost always a better way that does not require you to know the pixel dimensions of anything.
myimgbg.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
myimgbg.getViewTreeObserver().removeGlobalOnLayoutListener(this);
int width = myimgbg.getWidth();
}
});
Just to emphasize again, if you are doing something that requires knowing the exact pixel size of a view, you should probably take a step back and reconsider how to do what you want.
Check this :
image_view.getLayoutParams().height
image_view.getLayoutParams().width
Hope this helps.
try myimgbg.getWidth() and myimgbg.getHeight()
This is simple way to get width and height from imageview
ImageView img = (ImageView) findViewById(R.id.img);
Log.d(TAG, "width : " + img.getWidth());
Just try,
after your view is drawn
yourView.getHeight()
yourView.getWidth()
or
LayoutParams params=yourView.getLayoutParams();
params.height //is your views height
Try this:
int width=image.getWidth();
int Height=image.getHeight();
I have the a LinearLayout with width set in xml as fill_parent , now i need its width at runtime programatically. So i did this:
LinearLayout layoutGet=(LinearLayout) findViewById(R.id.GameField1);
LayoutParams layParamsGet= layoutGet.getLayoutParams();
int width=layParamsGet.width;
But width value on debugging was found to be -1, anybody with idea why can't i get the exact width at runtime for LinearLayout with fill_parent set in layout xml.
I got a simple approach working.
myLayout = (RelativeLayout) findViewById(R.id.my_layout);
myLayout.post(new Runnable()
{
#Override
public void run()
{
Log.i("TEST", "Layout width : "+ myLayout.getWidth());
}
});
Jens Vossnack's approach mentioned below works fine. However, I found that the onGlobalLayout() method of GlobalLayoutListener is called repeatedly, which may not be appropriate in certain cases.
You can try to listen to the globalLayout event, and get the width in there. You probably get the -1 because you are trying to get the width before the views are layed-out.
vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
//Do it here
LinearLayout layoutGet=(LinearLayout) findViewById(R.id.GameField1);
LayoutParams layParamsGet= layoutGet.getLayoutParams();
int width=layParamsGet.width;
removeOnGlobalLayoutListener(layoutGet, this); // Assuming layoutGet is the View which you got the ViewTreeObserver from
}
});
#SuppressLint("NewApi")
public static void removeOnGlobalLayoutListener(View v, ViewTreeObserver.OnGlobalLayoutListener listener){
if (Build.VERSION.SDK_INT < 16) v.getViewTreeObserver().removeGlobalOnLayoutListener(listener);
else v.getViewTreeObserver().removeOnGlobalLayoutListener(listener);
}
(vto is the view you want to get the width of)
If you look at the value for FILL_PARENT (you should be using MATCH_PARENT since FILL_PARENT is now deprecated) you will notice the value for it is -1. LayoutParams are simply attributes for how your view should look. Once the view is inflated and looks the way the params specify, the view does not go back and change those Params to reflect the actual values of the view (width/height/etc).
If you wanted to get the actual width of your view you would have to call getWidth() on your view once the layout has been inflated and displayed. Calling getWidth() before your layout has been displayed will result in 0.
LinearLayout layoutGet=(LinearLayout) findViewById(R.id.GameField1);
int width = layoutGet.getWidth();
First of all, you should use match_parent instead of fill_parent (deprecated).
When you do int width=layParamsGet.width;, you take the right result which is -1 corresponding at fill_parent.
If you wan't to get the real width, you need to wait onMesure() call and use
LinearLayout layoutGet=(LinearLayout) findViewById(R.id.GameField1);
int width = layoutGet. getMeasuredHeight();
layoutGet.getWidth() should work out
if I have a layout with fill_parent at height and width, is there a way to get his height and width in onCreate method? if not, when his dimensions are available? I need this because I need to add at runtime some views and I need to know how many views fill in the layout.
You can do that:.
Suppose you have the layout view in onCreate method
layout.post(new Runnable() {
#Override
public void run() {
height= getHeight();
width=getWidth();
//pupulate other views now that you know the parent size
}
}
});
You can use the onSizeChanged method to get the information when it has been calculated, but this may also help to at least get the dimensions of the display.
Display display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
int width = display.getWidth();
You may find this useful:
when is onSizeChanged() called?
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);
}
}
});
}
}
Please try this:
Display display = getWindowManager().getDefaultDisplay();
Log.e("", "" + display.getHeight() + " " + display.getWidth());