How to get height and width of Button - android

I have created an array of buttons. Now I want to find the height and width of the button, and for that, I have used getWidth() and getHeight(). But the thing is that it always returns 0. Why is this happening? I have send my code, please check if anything is wrong.
LinearLayout layoutVertical = (LinearLayout) findViewById(R.id.liVLayout);
LinearLayout rowLayout = null;
LayoutParams param = new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT, 1);
public static void main(String[] args)
{
DBFacade dbFacade = new DBFacade();
dbFacade.pick();
}
//Create Button
for(int i=0;i<6;i++)
{
rowLayout=new LinearLayout(this);
rowLayout.setWeightSum(7);
layoutVertical.addView(rowLayout,param);
for(int j=0;j<7;j++)
{
m_pBtnDay[i][j]=new Button(this);
rowLayout.addView(m_pBtnDay[i][j],param);
m_pBtnDay[i][j].setOnLongClickListener(this);
m_pBtnDay[i][j].setGravity(Gravity.CENTER_HORIZONTAL|Gravity.CENTER_VERTICAL);
m_pBtnDay[i][j].setTextSize(12);
}
}
x=m_pBtnDay[i][j].getWidth();
y=m_pBtnDay[i][j].getHeight();
Log.d("width",Integer.toString(x));
Log.d("Height",Integer.toString(y));
return true;

Probably you are calling getWidth() and getHeight() too early: I think the UI has not been sized and laid out on the screen yet...
You can try to put that code inside this:
#Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
// Call here getWidth() and getHeight()
}

Another way
ViewTreeObserver vto = button.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
width = button.getWidth();
height = button.getHeight();
}
});

put this in your loop
x = m_pBtnDay[i][j].getWidth();
y = m_pBtnDay[i][j].getHeight();
Log.d("width", Integer.toString(x));
Log.d("Height", Integer.toString(y));
try it

You try to use the count-variable "i" and "j" to use outside from both for-loops. That should raise an exception because the are only availabil in each for-block.
Try to make the output in the second for-loop...
for (int i = 0; i<6; i++)
{
...
for(int j=0; j<7; j++)
{
....
x = m_pBtnDay[i][j].getWidth();
y = m_pBtnDay[i][j].getHeight();
Log.d("width", Integer.toString(x));
Log.d("Height", Integer.toString(y));
}
}

You can override the following View method, called during the layout phase.
protected void onSizeChanged (int w, int h, int oldw, int oldh)
This seems more appropriate, as it expressly accounts for the zero width and height you're observing:
This is called during layout when the size of this view has changed.
If you were just added to the view hierarchy, you're called with the
old values of 0.
Parameters w Current width of this view. h Current height of this
view. oldw Old width of this view. oldh Old height of this view.
See here.

Try this can also work:
btn.getDrawingCache().getHeight() and btn.getDrawingCache().getWidth()

Related

Android layaout Params

I have a button with dimensions:
btn1.width = 100;
btn2.height = 150;
I used the following code to resize:
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) btn1.getLayoutParams();
layoutParams.width = 200;
layoutParams.height = 300;
btn1.setLayoutParams(layoutParams);
When I did this:
int newSize = btn1.getWidth;
The newSize has value 100, but not 200. It resized the button well, but after the resize, btn1.getWidth still holds the previous value. How can I instantly get the set size?
The actual width of the View does not get updated immediately.
Your best bet is to cache the size when you set it.
You will not directly get the height/width after setting to a view. If you want then you can get in "post" method:
btn1.setWidth(200);
btn1.setHeight(300)
btn1.post(new Runnable() {
#Override
public void run() {
Log.i("Tag", "Width:"+ btn1.getWidth() + " Height:" + btn1.getHeight());
}
});

Difference in height of root Layout calculated from two methods

I am calculating the height of a root Layout ( RelativeLayout) with height and width as 'fill_parent' using this method and it returns 690
final RelativeLayout rootLayout=(RelativeLayout)findViewById(R.id.root_layout);
ViewTreeObserver vto = rootLayout.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
rootLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
mRootLayoutHeight=rootLayout.getHeight();
Toast.makeText(MyActivity.this,""+mRootLayoutHeight,Toast.LENGTH_LONG).show();
}
});
This layout has a Listview so i calculate the calculate the 'bottom' of individual rows using this
for(int i = 0; i <= month_listview.getLastVisiblePosition() - month_listview.getFirstVisiblePosition(); i++){
View v=month_listview.getChildAt(i);
if(v!=null) {
Rect rectf = new Rect();
v.getGlobalVisibleRect(rectf);
Log.d("bottom :", String.valueOf(rectf.bottom));
}
}
The bottom of the last row should come as 690 but its coming as 776. Why is there a difference?

Getting end position of the textview and imageview with respect to top of the screen

I have a bitmap and below it is a time line.
As an example consider the right side layout of the FIGURE.
All the bottom timelines (1, 2, 3...) are in the same height from top.
The timeline is a textview which has fixed layout height and width as it is defined in xml
like timeline 1 is defined as:
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/HView"
android:layout_marginLeft="18dp"
android:layout_marginTop="345dp"
android:textSize="14sp"
android:text="1"
android:textColor="#000000" />
However the bitmap height and width can vary as it is done programatically.
So in certain cases, the bitmap height increases enough to overlap the timeline. In other words,
the vertical position of bitmap increases with respect to the vertical position of the timeline.
I want to get:
1) the ended vertical position of bitmap with respect to top of the screen.
2) the ended vertical position of timeline with respect to top of the screen.
I tried to do the following:
TextView bottomTimeLine = (TextView) view.findViewById(R.id.textView1);
bottomTimeLine.getHeight(); //returns 0.
bottomTimeLine.getBottom(); //returns 0.
ImageView img = new ImageView(getActivity());
img.setImageDrawable(getResources().getDrawable(R.drawable.disp_bg));
img.getHeight(); //returns 0.
img.getBottom(); //returns 0.
As seen from the code, both the methods, getHeight() and getBottom() are returning height as 0.
How to get the height (view end position) of both with respect to top of the cell display ?
Hope this helps
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
this.setMeasuredDimension(
parentWidth / 2, parentHeight);
}
This is how it can be done:
final TextView bottomTimeLine = (TextView) view.findViewById(R.id.textView1);
final int[] timelineCoord = new int[2];
final int[] imgCoord = new int[2];
ViewTreeObserver vto = bottomTimeLine.getViewTreeObserver();
vto.addOnGlobalLayoutListener((new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
bottomTimeLine.getLocationOnScreen(timelineCoord);
Log.d(" bottomTimeLine H ", ""+timelineCoord[1]);
timelineHeight = timelineCoord[1];
}
}));
ViewTreeObserver vt1 = img.getViewTreeObserver();
vt1.addOnGlobalLayoutListener((new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
img.getLocationOnScreen(imgCoord);
imgHeight = imgCoord[1] + img.getHeight();
Log.d("Img H ", ""+imgHeight);
if(imgHeight < timelineHeight)
{
int heightDiff = imgHeight - timelineHeight ;
heightDiff = heightDiff + 3;
img.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, heightDiff));
}
}
}));

In Android how to get the width of the Textview which is set to Wrap_Content

I am trying to add a text to the textview for which i have set the width as Wrap_content. I am trying to get the width of this textview. But its showing 0 in all the cases. How Can i get the width of the textview after setting the text into it.
the code is as:
LinearLayout ll= new LinearLayout(this);
ll.setOrientation(LinearLayout.VERTICAL);
TextView tv = new TextView(this);
tv.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT));
ll.addView(tv);
tv.setText("Hello 1234567890-0987654321qwertyuio787888888888888888888888888888888888888888888888888");
System.out.println("The width is == "+tv.getWidth());// result is 0
this.setContentView(ll);
Please suggest.
Thanks in advance.
Views with the dynamic width/height get their correct size only after a layout process was finished (http://developer.android.com/reference/android/view/View.html#Layout).
You can add OnLayoutChangeListener to your TextView and get it's size there:
tv.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
public void onLayoutChange(View v, int left, int top, int right, int bottom,
int oldLeft, int oldTop, int oldRight, int oldBottom) {
final int width = right - left;
System.out.println("The width is == " + width);
});
You can not get the width of a View with dynamic size before the layout is completely built. That means there is no way you can get it in onCreate(). One way would be to create a class that inherits from TextView and overrides onSizeChanged().
When are you calling this? Has it already been drawn to the screen?
It sounds like you are calling getWidth() too early.
You can also take a look at this question.
You should use this:
textView.getMeasuredWidth();
this works for me:
RelativeLayout.LayoutParams mTextViewLayoutParams = (RelativeLayout.LayoutParams) mTextView.getLayoutParams();
mTextView.setText(R.string.text);
mTextView.measure(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
int width = mShareTip.getMeasuredWidth();
//use the width to do what you want
mShareTip.setLayoutParams(mShareTipLayoutParams);
you can try this:
textView.measure(0,0);
int width = textView.getMeasuredWidth();
hello use this method:
textview.post(new Runnable() {
#Override
public void run() {
int width = textview.getWidth();
int height = textview.getHeight();
textview.setText( String.valueOf( width +","+ height ));
}
});
source: https://gist.github.com/omorandi/59e8b06a6e81d4b8364f
You can use this library to schedule the task of perform calculation on the width to the correct time after the view had been completely drawn
https://github.com/Mohamed-Fadel/MainThreadScheduler
Sample of use:
MainThreadScheduler.scheduleWhenIdle(new Runnable() {
#Override
public void run() {
int width = textview.getWidth();
int height = textview.getHeight();
textview.setText( String.valueOf( width +","+ height ));
}
});

How to resize a custom view programmatically?

I am coding a custom view, extended from RelativeLayout, and I want to resize it programmatically, How can I do?
the custom view Class is something like:
public ActiveSlideView(Context context, AttributeSet attr){
super(context, attr);
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if(inflater != null){
inflater.inflate(R.layout.active_slide, this);
}
Android throws an exception if you fail to pass the height or width of a view.
Instead of creating a new LayoutParams object, use the original one, so that all other set parameters are kept. Note that the type of LayoutParams returned by getLayoutParams is that of the parent layout, not the view you are resizing.
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) someLayout.getLayoutParams();
params.height = 130;
someLayout.setLayoutParams(params);
this.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, theSizeIWant));
Problem solved!
NOTE: Be sure to use the parent Layout's LayoutParams. Mine is LinearLayout.LayoutParams!
This works for me:
ViewGroup.LayoutParams params = layout.getLayoutParams();
params.height = customHeight;
layout.requestLayout();
In Kotlin, you can use the ktx extensions:
yourView.updateLayoutParams {
height = <YOUR_HEIGHT>
}
For what it's worth, let's say you wanted to resize the view in device independent pixels (dp): -
You need to use a method called applyDimension, that's a member of the class TypedValue to convert from dp to pixels. So if I want to set the height to 150dp (say) - then I could do this:
float pixels = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 150, getResources().getDisplayMetrics());
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) someLayout.getLayoutParams();
params.height = (int) pixels;
someLayout.setLayoutParams(params);
where the expression: getResources().getDisplayMetrics() gets the screen density/resolution
Here's a more generic version of the solution above from #herbertD :
private void resizeView(View view, int newWidth, int newHeight) {
try {
Constructor<? extends LayoutParams> ctor = view.getLayoutParams().getClass().getDeclaredConstructor(int.class, int.class);
view.setLayoutParams(ctor.newInstance(newWidth, newHeight));
} catch (Exception e) {
e.printStackTrace();
}
}
try a this one:
...
View view = inflater.inflate(R.layout.active_slide, this);
view.setMinimumWidth(200);
I used this way to increase width of custom view
customDrawingView.post(new Runnable() {
#Override
public void run() {
View view_instance = customDrawingView;
android.view.ViewGroup.LayoutParams params = view_instance
.getLayoutParams();
int newLayoutWidth = customDrawingView
.getWidth()
+ customDrawingView.getWidth();
params.width = newLayoutWidth;
view_instance.setLayoutParams(params);
screenWidthBackup = params.width;
}
});
With Kotlin and using dp unit:
myView.updateLayoutParams {
val pixels = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 200f, context.resources.displayMetrics)
height = pixels.toInt()
}
I solved it this way.. I have basically a simple view inside xml file.
View viewname = findViewById(R.id.prod_extra);
prodExtra.getLayoutParams().height=64;
If you have only two or three condition(sizes) then you can use #Overide onMeasure like
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
And change your size for these conditions in CustomView class easily.
This is how it can be done in Kotlin:
updateLayoutParams:
val view = layoutInflater.inflate(R.layout.cell, binding.ssss, false).apply {
id = View.generateViewId()
updateLayoutParams {
height = 200
width = 400
}
}
binding.ssss.addView(view)
OR
layoutParams:
val view = layoutInflater.inflate(R.layout.cell, binding.ssss, false).apply {
id = View.generateViewId()
layoutParams.width = 200
layoutParams.height = 200
}
binding.ssss.addView(view)
if you are overriding onMeasure, don't forget to update the new sizes
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(newWidth, newHeight);
}
This is how I achieved this. In Sileria answer he/she did the following:
ViewGroup.LayoutParams params = layout.getLayoutParams();
params.height = customHeight;
layout.requestLayout();
This is correct, but it expects us to give the height in pixels, but I wanted to give the dp I want the height to be so I added:
public int convertDpToPixelInt(float dp, Context context) {
return (int) (dp * (((float) context.getResources().getDisplayMetrics().densityDpi) / 160.0f));
}
So it will look like this:
ViewGroup.LayoutParams params = layout.getLayoutParams();
params.height = convertDpToPixelInt(50, getContext());
layout.requestLayout();
This is what I did:
View myView;
myView.getLayoutParams().height = 32;
myView.getLayoutParams().width = 32;
If there is a view group that this view belongs to, you may also need to call yourViewGroup.requestLayout() for it to take effect.
fun View.setSize(width: Int, height: Int) {
updateLayoutParams {
this.width = width
this.height = height
}
}

Categories

Resources