I try to get a FrameLayout's height in onGlobalLayout(), this piece of code is in the onCreate() method:
final FrameLayout layout = (FrameLayout)findViewById(R.id.detail_frame);
ViewTreeObserver vto = layout.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
layout.getViewTreeObserver().removeOnGlobalLayoutListener (this);
ViewGroup.LayoutParams lPF = layout.getLayoutParams();
int gg = layout.getHeight();
int hh = lPF.height;
}
});
The XML file:
<FrameLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/detail_frame">
...
...
</FrameLayout>
but when I was debugging, 'gg' got the right height value, 'hh' got -1. I'm doing this because I want to set the layout's height. How can I get the right value of LayoutParams?
Anyway to know if it's finished laying out?
You already did, onGlobalLayout is called when the view finishes laying out, that's why getHeight return non-zero pixel in height. If it's not drawn yet, getHeight will return 0
How can I get the right value of LayoutParams?
Nothing is wrong here, it's a right value. You get -1 from LayoutParams.height because it's MATCH_PARENT placeholder value, just like WRAP_CONTENT = -2. Android read this layout params value, then calculate the real size in pixel, which will be the value you get when calling getHeight.
I'm doing this because I want to set the layout's height
Just set the height value to the LayoutParams: layout.getLayoutParams().height = 100
Related
I have 2 views - a container view, and a gauge view. I want to programmatically change the height of the gauge view. The problem is that when I get the height of the container view - it always comes back as 2.0 - even though the height is full-screen!
int fullHeight = containerView.getLayoutParams().height;
Number height = fullHeight * (thisTank.getTankTotalVolume().doubleValue()/thisTank.getTankMaxVolume().doubleValue());
Number width = gaugeView.getWidth();
//gaugeView.setLayoutParams(new LinearLayout.LayoutParams(width.intValue(), height.intValue()));
gaugeView.getLayoutParams().height = height.intValue() * fullHeight;
gaugeView.requestLayout();
Actually, if you set the view's height to WRAP_CONTENT or MATCH_PARENT in XML, the containerView.getLayoutParams().height should be equals to 2, its a default value...!
You have to two options,
First, you can defined a fix value in the XML file
Second, and recommended, you can use a tree observer for this purpose. Please see the below code...!
final View layout = (View)findViewById(R.id.YOUR_VIEW_ID);
ViewTreeObserver vto = layout.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
this.layout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
int width = layout.getMeasuredWidth();
int height = layout.getMeasuredHeight();
}
});
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
Here is the deal:
I have a GridView with android:numColumns="2". The items in the GridView are ImageViews with android:layout_weight="1", so they are half the screen width. The problem is the heightproperty, it should be equal to the width. I tried to play with scaleype, so far without success.
How can I set the width of the GridView elements to fill half the screen and set their height to be equal to their width?
You have to get the ImageViews width programmatically and then set the height.
But if you just use img.getWidth(); eg. in OnCreate(), it will return 0 because it hasn't been drawn yet.
So you have to do something like this in OnCreate():
ImageView img = (ImageView) findViewById(R.id.img);
ViewTreeObserver vto = img.getViewTreeObserver();
vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
public boolean onPreDraw() {
int x;
img.getViewTreeObserver().removeOnPreDrawListener(this);
x = img.getMeasuredWidth();
img.setLayoutParams(new LinearLayout.LayoutParams(x,x));
return true;
}
});
This will get your Imageview's width after its been drawn and set its height equal to it.
To set your ImageView equal to half the screen, you need to add the following to your XML for the ImageView:
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:scaleType="fitXY"
android:adjustViewBounds="true"/>
To then set the height equal to this width, you need to do it in code. In the getView method of your GridView adapter, set the ImageView height equal to its measured width:
int measuredImageWidth = mImageView.getMeasuredWidth();
mImageView.getLayoutParams().height = measuredImageWidth;
Hope this helps!
okay here's my issue I want to create a scroll view that fills down to a set of two buttons that are right at the bottom of the screen. knowing i can't just set the scroll view to fill parent I thought I'd go and get the height of the linear layout with the buttons in it and then the height of the scroll view that I set to fill parent. then subtract one from the other and then reset the scroll view height. I figured out how to get and set the scroll view height. and I found a way to that works to measure all of the other views in the activity but with this one it always returns a zero and I'm at a loss as to how to get the height of it.
final LinearLayout tv = (LinearLayout)findViewById(R.id.thebuttons);
ViewTreeObserver vto = tv.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
public void onGlobalLayout() {
Integer grr = tv.getHeight();
Log.e("the h", grr.toString());
ViewTreeObserver obs = tv.getViewTreeObserver();
obs.removeGlobalOnLayoutListener(this);
}
});
now if I set it to any of my other layouts I get the height of it as I expect but set it to this one and I get 0; and this is the one I'm trying to measure! I've also tried to measure the button directly to no avail
<LinearLayout
android:id="#+id/thebuttons"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="5sp"
>
<Button
android:id="#+id/saveit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Save" />
<Button
android:id="#+id/clearit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Save" />
</LinearLayout>
I finally Figured it out myself
if the widgets do not appear on screen they do not get created. so thus the button elements where still at zero because they where never rendered; and they where never rendered because the scroll view pushed them off screen.
so I attacked the problem from a different angle this time what I did was set the scroll view to an arbitrary small number so the buttons stay on screen, get the size of the top level layout stored that to "int totalsize", then I get the sizes of all the elements except the scroll view and got the margins for each view as well and totaled them all up into "int used", then I set the scroll view height to "totalsize-used" and that is what worked. found it I totaled up the margins manually that doesn't work when the screen size changes the margins also change so discovering them along with the view sizes works best.
in my on create method I got this:
final Button tv = (Button)findViewById(R.id.saveit);
ViewTreeObserver vto = tv.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
public void onGlobalLayout() {
ViewGroup.MarginLayoutParams vlp = (MarginLayoutParams) tv.getLayoutParams();
int btnsize =tv.getMeasuredHeight()+vlp.topMargin;
sizeit(btnsize);
ViewTreeObserver obs = tv.getViewTreeObserver();
obs.removeGlobalOnLayoutListener(this);
}
});
and then the size it function
private void sizeit(Integer thebuttons)
{
View v = findViewById(R.id.viewmain);
int total = v.getHeight();
v = findViewById(R.id.view1);
ViewGroup.MarginLayoutParams vlp = (MarginLayoutParams) v.getLayoutParams();
int used=v.getHeight()+vlp.topMargin;
v = findViewById(R.id.view2);
vlp = (MarginLayoutParams) v.getLayoutParams();
used+=v.getHeight()+vlp.topMargin;
v = findViewById(R.id.fonttext);
vlp = (MarginLayoutParams) v.getLayoutParams();
used+=v.getHeight()+vlp.topMargin;
v = findViewById(R.id.infolabel);
vlp = (MarginLayoutParams) v.getLayoutParams();
used+=v.getHeight()+vlp.topMargin;
Integer scrsize=total-used-thebuttons;
v = findViewById(R.id.scrview);
ScrollView scr = (ScrollView)findViewById(R.id.scrview);
ViewGroup.LayoutParams scrlprams = scr.getLayoutParams();
scrlprams.height=scrsize;
scr.setLayoutParams(scrlprams);
}
hope this helps someone also fighting with the same issue
These methods return correct values when retrieved dynamically for eg. in onCreate() , but the only exception is when the dimension is specified in the xml layout file as undefined ,
like 'wrap content' etc. Is there a way to retrieve such values too ???
This should return the correct width and height. onCreate is called before the layout of the child views are done. So the width and height is not calculated yet. To get the height and width. Put this on the onCreate method
LinearLayout layout = (LinearLayout)findViewById(R.id.YOUD VIEW ID);
ViewTreeObserver vto = layout.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
hs.getViewTreeObserver().removeGlobalOnLayoutListener(this);
int width = layout.getMeasuredWidth();
int height = layout.getMeasuredHeight();
}
});