Android: Measuring child with sizes defined in its xml - android

I would like to know how to measure child view with width and height value which are defined in child's xml file.
I know that in onMeasure() method of my custom ViewGroup I should call:
child.measure(MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.EXACTLY));
But how to get childWidth and childHeight from xml code?

I know this is an old question. Essentially you want to use measureChild function provided by the ViewGroup. This function will take care of measuring it properly.

You can get them from LayoutParams of the child:
LayoutParams l = child.getLayoutParams();
childWidth = l.width;
childHeight = l.height;
ViewGroup's constructors are capable of reading the layout_height and layout_width parameters from xml.

Try this
RelativeLayout.LayoutParams params =
(android.widget.RelativeLayout.LayoutParams)child.getLayoutParams();
childWidth = params.width;
childHeight = params.height;
in the above code replace the RelativeLayout with the your parent layout

Related

widthMeasureSpec is 0 when in HorizontalScrollView

I'm writing a custom view in Android. Since I need precise size management, I've overridden onMeasure. Its documentation says, that View.MeasureSpec.getMode returns one of three values, defined as constants. But when my view was placed inside HorizontalScrollView, widthMeasureSpec was 0 - I was unable to get both mode and size from it.
What is even weirder is that this parameter was 0 even if I explicitly defined width for my view.
Why does it happen, how should I interpret the 0 value and what should I do in this particular case?
0 means the mode is UNSPECIFIED. This means you can be as big as you want, which makes sense since it is a ScrollView...intended for a View bigger than your actual screen.
Being unspecified, you don't have to care about the size, this is why it is 0.
If you look at the source of HorizontalScrollView you can also see that it just passes width: 0, UNSPECIFIED to the child:
#Override
protected void measureChild(View child, int parentWidthMeasureSpec, int parentHeightMeasureSpec) {
ViewGroup.LayoutParams lp = child.getLayoutParams();
int childWidthMeasureSpec;
int childHeightMeasureSpec;
childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec, mPaddingTop
+ mPaddingBottom, lp.height);
childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
}
To get the child view as big as the parent you can use fillViewPort from xml or java which will lead to a call with mode EXACTLY:
if (!mFillViewport) {
return;
}
// ...
int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
This is one way to handle your child view being as big as the ScrollView.

Android calculate height of child View When overflow

I have nested LinearLayouts where Parent height is 90 but the child view may have different heights according to the text set inside it and may overflow its parent. I Want to animate Parent to final Height of child but both methods of getHeight() on child and getMeasuredHeight() on parent, return 90 not 400.
parent.measure(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
targetHeight = parent.getMeasuredHeight();
//returns 90
and also
View child=((ViewGroup) parent).getChildAt(0);
int targetHeight=child.getHeight();
//returns 90
Try this code. Hope it'll work.
ViewGroup.LayoutParams params = yourView.getLayoutParams();
int height = params.height;
LayoutParams paramsChild = child.getLayoutParams();
LayoutParams paramsParent = parent.getLayoutParams();
paramsParent.height = paramsChild.height;
parent.setLayoutParams(paramsParent);

In custom layout in onMeasure(), should textview handle its layout_height?

I have a custom layout that includes some TextView and other widgets. The TextViews have an XML attribute android:layout_height="".
The problem is that the layout_height is being ignored and, I think, treated as wrap_content.
I thought that the child views are supposed to handle their own layout_width & layout_height params. Do I need to do something in my custom layout's onMeasure() or is the problem elsewhere?
Thanks.
Apparently the layout_width and layout_height params need to be handled by the container, not the TextView. So, a little piece of code like this seems to do the trick (I'm just showing the height calculation in this example):
for (int i = 0, count = getChildCount(); i < count; i++)
{
View child = getChildAt(i);
ViewGroup.LayoutParams params = child.getLayoutParams();
int heightSpec;
if (params.height == ViewGroup.LayoutParams.MATCH_PARENT)
heightSpec = heightMeasureSpec;
else if (params.height == ViewGroup.LayoutParams.WRAP_CONTENT)
heightSpec = MeasureSpec.makeMeasureSpec (Integer.MAX_VALUE, MeasureSpec.UNSPECIFIED);
else
heightSpec = MeasureSpec.makeMeasureSpec (params.height, MeasureSpec.EXACTLY);
child.measure (widthSpec, heightSpec);
}

Setting LayoutParams programmatically

I want to set my LinearLayout's parameters after all of the views' parameters are calculated.
I am trying to set LinearLayout's height related to the parent view's height. And parent view's height is calculated according to its layout_weight, so I get the height by getMeasuredHeight();
My code :
#Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
RelativeLayout lay = (RelativeLayout) findViewById(R.id.alt);
LinearLayout bar = (LinearLayout) findViewById(R.id.barLay);
int layH = lay.getMeasuredHeight();
int barH = layH / 4;
LinearLayout.LayoutParams params = (LayoutParams) bar.getLayoutParams();
params.height = barH;
bar.setLayoutParams(params);
}
Eclipse Debugger stops the program at this line;
LinearLayout.LayoutParams params = (LayoutParams) bar.getLayoutParams();
I can't find what could be the problem? Am I doing something wrong to set params?
The type of LayoutParams are actually set by the parent of the view, so bar.getLayoutParams() should be returning an object of type RelativeLayout.LayoutParams. With an explicit cast to LinearLayout.LayoutParams I'd expect your logcat to contain a line like this:
Caused by: java.lang.ClassCastException: android.widget.RelativeLayout$LayoutParams cannot be cast to android.widget.LinearLayout$LayoutParams
Changing it to this should do the trick:
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) bar.getLayoutParams();
or, since height is in the base class, don't cast it at all:
ViewGroup.LayoutParams params = bar.getLayoutParams();
Try changing this
LinearLayout.LayoutParams params = (LayoutParams) bar.getLayoutParams();
to this
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) bar.getLayoutParams();
After #LocHa asked me the type of the layouts, I try changing the parent layout's type to LinearLayout which was RelativeLayout, and finally it worked for me.

Android: Set minimum height of a view programmatically

I'm trying to set minimum height for an imageview programmatically but had no luck so far. My code is below
int width = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 160, getResources().getDisplayMetrics());
int minHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 100, getResources().getDisplayMetrics());
LayoutParams params = new LayoutParams(width,LayoutParams.MATCH_PARENT);
SmartImageView siv = new SmartImageView(getActivity());
siv.setMinimumHeight(minHeight);
siv.setLayoutParams(sivParams);
siv.setAdjustViewBounds(true);
siv.setScaleType(ScaleType.FIT_XY);
siv.setImageUrl(url);
ll.addView(siv);
I also tried to put the setMinimumWidth method after the setLayoutParams method but that didn't worked either. Please help
Thanks
The answer by #Ashok Damani is incorrect as pointed out by #Gustavo Baiocchi Costa in the comments:
this sets the height or width not the minimum width or height
The correct method to set the minimum height of a view in Android:
Property access way(in Kotlin):
yourView.minimumHeight = minHeight
Setter method way:
yourView.setMinimumHeight(minHeight);
Android Documentation says:
Sets the minimum height of the view. It is not guaranteed the view
will be able to achieve this minimum height (for example, if its
parent layout constrains it with less available height).
try this--->
siv.getLayoutParams().height = minHeight;
or u can also try--->
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(width , minHeight);
siv.setLayoutParams(layoutParams);

Categories

Resources