Get weight in android - android

I am new Android development, and I have a question about get width of View in Android.
I set weight of view = 1
<TextView
android:id="#+id/tvSTT"
android:layout_width="0dp"
android:layout_weight="1dp"
android:layout_height="match_parent"/>
And I try to find way to get width of this in java code. How should I do?
Sorry about my English.

Your TextView will get a width at the moment it is drawn. Before that moment, it is not clear what its actual width will be (because of many different screen sizes).
You can add an OnGlobalLayoutListener to the viewTreeObserver to be notified when it is drawn.
You can perform getWidth() in the listener and it should not be 0 anymore.
Add an OnGlobalLayoutListener like so
final TextView tvSTTtextView = (TextView)findViewById(R.id.tvSTT);
textView.getViewTreeObserver().addOnGlobalFocusChangeListener(new ViewTreeObserver.OnGlobalFocusChangeListener() {
#Override
public void onGlobalFocusChanged(View view, View view2) {
int width = tvSTTtextView.getWidth(); //width should not be 0
}
});

#Override
public void onWindowFocusChanged(boolean hasFocus) {
// TODO Auto-generated method stub
super.onWindowFocusChanged(hasFocus);
//Here you can get the width! use `getWidth()`
}

You have to get the view's layout params and cast it to TableLayout.LayoutParams, one you have it you can access to the view weight
((TableLayout.LayoutParams) view.getLayoutParams()).weight;// this is the weight

Related

Programmatically get a view's dimension that's been set to wrap_content in the xml layout

For a dropdown animation, I need to get the actual dp height of a view that has been set to wrap_content, thus depending on the number and sizes of its contained views.
The code sample shows the LinearLayout that I need to know the height of, inside a relative layout with a height of 0. The animation is supposed to increase the RelativeLayout's height to the height value of the inner LinearLayout:
<RelativeLayout
android:id="#+id/new_device_wrpr"
android:layout_width="wrap_content"
android:layout_height="#dimen/zero_size"
android:layout_alignLeft="#id/new_device_dd_button_knob"
android:layout_below="#id/new_device_dd_button_knob" >
<LinearLayout
android:id="#+id/new_device_spawn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#android:color/holo_orange_light"
android:orientation="vertical" >
</LinearLayout>
</RelativeLayout>
An implementation like the following only returns 0:
LinearLayout lL = (LinearLayout) findViewById(R.id.new_device_knob_spawn);
lL.getHeight();
As Christian stated you need to wait for layout to occur before you can retrieve the size of the view. If you're attempting to do this in onCreate I would recommend using a global layout listener to execute a callback once layout is complete.
final LinearLayout lL = (LinearLayout) findViewById(R.id.new_device_knob_spawn);
lL.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
int h = lL.getHeight();
// Do whatever you want with h
// Remove the listener so it is not called repeatedly
ViewHelper.removeOnGlobalLayoutListener(lL, this);
}
});
In order not to use a deprecated method I have this static helper method to remove global layout listeners. This is due to a renamed method in Jellybean.
public static void removeOnGlobalLayoutListener(View v, ViewTreeObserver.OnGlobalLayoutListener victim) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
removeLayoutListenerJB(v, victim);
} else removeLayoutListener(v, victim);
}
#SuppressWarnings("deprecation")
private static void removeLayoutListenerJB(View v, ViewTreeObserver.OnGlobalLayoutListener victim) {
v.getViewTreeObserver().removeGlobalOnLayoutListener(victim);
}
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
private static void removeLayoutListener(View v, ViewTreeObserver.OnGlobalLayoutListener victim) {
v.getViewTreeObserver().removeOnGlobalLayoutListener(victim);
}
getWidth() or getHeight() will work , but it depends "WHEN" you call it!
It always return 0 if you're calling it in "onCreate" event (that's because the view was not measured yet).

Android: How to get a view's height

For example, this is mButton:
<Button
android:id="#+id/mbtn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="mButton" />
This is how I tried to get the height:
int height = mButton.getLayoutParams.height;
But when I logged it, it says the height is -2. I think this might be the int value of "wrap_content". So how can I get the actual height? Thx!
If you want to get the width or height of a view in activty
you can get in this method..
yourview.getHeight();
returns zero(0) after initialization of the button because after adding it to the window only it has a width..in the below method you can height and width of a view..
#Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
yourview.getHeight();
yourview.getWidth();
}
After layout has happened call View.getHeight():
public final int getHeight()
Return the height of your view.
Returns
The height of your view, in pixels.
As you guessed, layoutParams.height is just the value of wrap_content in your case, which is -2. You could set layoutParams.height to a desired height, but even then it's not necessarily the height that the view will actually end up with after all layout is done.
override the method onWindowFocusChanged(boolean hasFocus);
inside write your code,
#Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
mbtn.getHeight();
mbtn.getWidth();
}
it will give the correct result of the view dimensions.

Android: get width of Layout programatically having fill_parent in its xml

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

Getting width during build of an Activity

I have a problem, and I can't seem to figure out what to do about it.
I'm new to developing with Android, but I have experience with Java.
During the onCreate(bundle), onPostCreate(bundle) or any other similar method, I can't get the correct width of a View. It returns 0. I also made a simple button for debug purposses, and that button returns the correct value.
How do I call a method that gets the width of a View after the onCreate method?
If that's not possible, what is a workaround?
Thanks in advance,
Gerralt
The problem is because, you are trying to find out the width as soon as you you start your activity.
But at this position the actual transformation of your view wouldn't have occurred. Android provides a special callback to find the width and height of all individual views. To access it, you have to override the onWindowFoucsChanged() method. Here is a sample,
#Override
public void onWindowFocusChanged(boolean hasFocus)
{
// TODO Auto-generated method stub
super.onWindowFocusChanged(hasFocus);
System.out.println("...Height..."+textview.getMeasuredWidth());
}
This line textview.getMeasuredWidth() helps you to find the actual width of the textView at runtime. Similarly you can find the width and height for any view using this method.
As i think, you are in the onCreate(Bundle) method:
public void onCreate(Bundle xxx) {
super(xxx);
// init some stuff here
setContentView(R.layout.my_layout);
// from THIS point you can get sizes of Views
}
Sorry if i'm wrong, but on my project it works. OK, i have to say i use often
custom views and use sizes not in my activity code but in View code.
Do this is onWindowFocusChanged() like this:
#Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if(hasFocus && llfullscreen!=null){
int layoutHeight = llfullscreen.getHeight();
ViewGroup.LayoutParams params = lv.getLayoutParams();
params.height = lv/2; //Set to half the screens size
this.lv.setLayoutParams(params);
this.lv.invalidate();
}
}

How to retrieve the dimensions of a view?

I have a view made up of TableLayout, TableRow and TextView. I want it to look like a grid. I need to get the height and width of this grid. The methods getHeight() and getWidth() always return 0. This happens when I format the grid dynamically and also when I use an XML version.
How to retrieve the dimensions for a view?
Here is my test program I used in Debug to check the results:
import android.app.Activity;
import android.os.Bundle;
import android.widget.TableLayout;
import android.widget.TextView;
public class appwig extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.maindemo); //<- includes the grid called "board"
int vh = 0;
int vw = 0;
//Test-1 used the xml layout (which is displayed on the screen):
TableLayout tl = (TableLayout) findViewById(R.id.board);
tl = (TableLayout) findViewById(R.id.board);
vh = tl.getHeight(); //<- getHeight returned 0, Why?
vw = tl.getWidth(); //<- getWidth returned 0, Why?
//Test-2 used a simple dynamically generated view:
TextView tv = new TextView(this);
tv.setHeight(20);
tv.setWidth(20);
vh = tv.getHeight(); //<- getHeight returned 0, Why?
vw = tv.getWidth(); //<- getWidth returned 0, Why?
} //eof method
} //eof class
I believe the OP is long gone, but in case this answer is able to help future searchers, I thought I'd post a solution that I have found. I have added this code into my onCreate() method:
EDITED: 07/05/11 to include code from comments:
final TextView tv = (TextView)findViewById(R.id.image_test);
ViewTreeObserver vto = tv.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
LayerDrawable ld = (LayerDrawable)tv.getBackground();
ld.setLayerInset(1, 0, tv.getHeight() / 2, 0, 0);
ViewTreeObserver obs = tv.getViewTreeObserver();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
obs.removeOnGlobalLayoutListener(this);
} else {
obs.removeGlobalOnLayoutListener(this);
}
}
});
First I get a final reference to my TextView (to access in the onGlobalLayout() method). Next, I get the ViewTreeObserver from my TextView, and add an OnGlobalLayoutListener, overriding onGLobalLayout (there does not seem to be a superclass method to invoke here...) and adding my code which requires knowing the measurements of the view into this listener. All works as expected for me, so I hope that this is able to help.
I'll just add an alternative solution, override your activity's onWindowFocusChanged method and you will be able to get the values of getHeight(), getWidth() from there.
#Override
public void onWindowFocusChanged (boolean hasFocus) {
// the height will be set at this point
int height = myEverySoTallView.getMeasuredHeight();
}
You are trying to get width and height of an elements, that weren't drawn yet.
If you use debug and stop at some point, you'll see, that your device screen is still empty, that's because your elements weren't drawn yet, so you can't get width and height of something, that doesn't yet exist.
And, I might be wrong, but setWidth() is not always respected, Layout lays out it's children and decides how to measure them (calling child.measure()), so If you set setWidth(), you are not guaranteed to get this width after element will be drawn.
What you need, is to use getMeasuredWidth() (the most recent measure of your View) somewhere after the view was actually drawn.
Look into Activity lifecycle for finding the best moment.
http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle
I believe a good practice is to use OnGlobalLayoutListener like this:
yourView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
if (!mMeasured) {
// Here your view is already layed out and measured for the first time
mMeasured = true; // Some optional flag to mark, that we already got the sizes
}
}
});
You can place this code directly in onCreate(), and it will be invoked when views will be laid out.
Use the View's post method like this
post(new Runnable() {
#Override
public void run() {
Log.d(TAG, "width " + MyView.this.getMeasuredWidth());
}
});
I tried to use onGlobalLayout() to do some custom formatting of a TextView, but as #George Bailey noticed, onGlobalLayout() is indeed called twice: once on the initial layout path, and second time after modifying the text.
View.onSizeChanged() works better for me because if I modify the text there, the method is called only once (during the layout pass). This required sub-classing of TextView, but on API Level 11+ View. addOnLayoutChangeListener() can be used to avoid sub-classing.
One more thing, in order to get correct width of the view in View.onSizeChanged(), the layout_width should be set to match_parent, not wrap_content.
Are you trying to get sizes in a constructor, or any other method that is run BEFORE you get the actual picture?
You won't be getting any dimensions before all components are actually measured (since your xml doesn't know about your display size, parents positions and whatever)
Try getting values after onSizeChanged() (though it can be called with zero), or just simply waiting when you'll get an actual image.
As F.X. mentioned, you can use an OnLayoutChangeListener to the view that you want to track itself
view.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
#Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
// Make changes
}
});
You can remove the listener in the callback if you only want the initial layout.
I guess this is what you need to look at: use onSizeChanged() of your view. Here is an EXTENDED code snippet on how to use onSizeChanged() to get your layout's or view's height and width dynamically http://syedrakibalhasan.blogspot.com/2011/02/how-to-get-width-and-height-dimensions.html
ViewTreeObserver and onWindowFocusChanged() are not so necessary at all.
If you inflate the TextView as layout and/or put some content in it and set LayoutParams then you can use getMeasuredHeight() and getMeasuredWidth().
BUT you have to be careful with LinearLayouts (maybe also other ViewGroups). The issue there is, that you can get the width and height after onWindowFocusChanged() but if you try to add some views in it, then you can't get that information until everything have been drawn. I was trying to add multiple TextViews to LinearLayouts to mimic a FlowLayout (wrapping style) and so couldn't use Listeners. Once the process is started, it should continue synchronously. So in such case, you might want to keep the width in a variable to use it later, as during adding views to layout, you might need it.
Even though the proposed solution works, it might not be the best solution for every case because based on the documentation for ViewTreeObserver.OnGlobalLayoutListener
Interface definition for a callback to be invoked when the global layout state or the visibility of views within the view tree changes.
which means it gets called many times and not always the view is measured (it has its height and width determined)
An alternative is to use ViewTreeObserver.OnPreDrawListener which gets called only when the view is ready to be drawn and has all of its measurements.
final TextView tv = (TextView)findViewById(R.id.image_test);
ViewTreeObserver vto = tv.getViewTreeObserver();
vto.addOnPreDrawListener(new OnPreDrawListener() {
#Override
public void onPreDraw() {
tv.getViewTreeObserver().removeOnPreDrawListener(this);
// Your view will have valid height and width at this point
tv.getHeight();
tv.getWidth();
}
});
Height and width are zero because view has not been created by the time you are requesting it's height and width . One simplest solution is
view.post(new Runnable() {
#Override
public void run() {
view.getHeight(); //height is ready
view.getWidth(); //width is ready
}
});
This method is good as compared to other methods as it is short and crisp.
You should rather look at View lifecycle: http://developer.android.com/reference/android/view/View.html Generally you should not know width and height for sure until your activity comes to onResume state.
You can use a broadcast that is called in OnResume ()
For example:
int vh = 0;
int vw = 0;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.maindemo); //<- includes the grid called "board"
registerReceiver(new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
TableLayout tl = (TableLayout) findViewById(R.id.board);
tl = (TableLayout) findViewById(R.id.board);
vh = tl.getHeight();
vw = tl.getWidth();
}
}, new IntentFilter("Test"));
}
protected void onResume() {
super.onResume();
Intent it = new Intent("Test");
sendBroadcast(it);
}
You can not get the height of a view in OnCreate (), onStart (), or even in onResume () for the reason that kcoppock responded
Simple Response: This worked for me with no Problem.
It seems the key is to ensure that the View has focus before you getHeight etc. Do this by using the hasFocus() method, then using getHeight() method in that order. Just 3 lines of code required.
ImageButton myImageButton1 =(ImageButton)findViewById(R.id.imageButton1);
myImageButton1.hasFocus();
int myButtonHeight = myImageButton1.getHeight();
Log.d("Button Height: ", ""+myButtonHeight );//Not required
Hope it helps.
Use getMeasuredWidth() and getMeasuredHeight() for your view.
Developer guide: View
CORRECTION:
I found out that the above solution is terrible. Especially when your phone is slow.
And here, I found another solution:
calculate out the px value of the element, including the margins and paddings:
dp to px:
https://stackoverflow.com/a/6327095/1982712
or dimens.xml to px:
https://stackoverflow.com/a/16276351/1982712
sp to px:
https://stackoverflow.com/a/9219417/1982712 (reverse the solution)
or dimens to px:
https://stackoverflow.com/a/16276351/1982712
and that's it.

Categories

Resources