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);
}
Related
This is onMeasure() on CustomView which extend FrameLayout. After investigate onMeasure(), heigh size is always zero. How could I know what is the height size of this CustomView to manipulate child view later.
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int viewHeightMode = MeasureSpec.getMode(heightMeasureSpec);
int viewWidthMode = MeasureSpec.getMode(widthMeasureSpec);
int viewHeight = MeasureSpec.getSize(heightMeasureSpec);
int viewWidth = MeasureSpec.getSize(widthMeasureSpec);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
First of all please read this question. It is about measuring of View.
Main difference about ViewGroup that you should measure in your code all your childs.
for(int i=0; i<getChildCount(); i++) {
View child = getChildAt(i);
LayoutParams lp = child.getLayoutParams();
int widthMeasureMode = lp.width == LayoutParams.WRAP_CONTENT ? MeasureSpec.AT_MOST : MeasureSpec.EXACTLY,
heightMeasureMode = lp.height == LayoutParams.WRAP_CONTENT ? MeasureSpec.AT_MOST : MeasureSpec.EXACTLY;
int widthMeasure = MeasureSpec.makeMeasureSpec(getWidth() - left, widthMeasureMode),
heightMeasure = MeasureSpec.makeMeasureSpec(getHeight() - top, heightMeasureMode);
child.measure(widthMeasure, heightMeasure);
int childWidth = child.getMeasuredWidth(),
childHeight = child.getMeasuredHeight();
//make something with that
}
That shows how to get size of all childs. May be you want to calculate sum of heights, may be just find maximum value - it is your own goal.
By the way. If your base class is not ViewGroup, but FrameLayout for example, measuring childs could be done in onLayout method. In this case in your onMeasure method you can do nothing about measuring childs - just take sizes. But it is just a guess - better to check that.
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);
I have a TableLayout with multiple TableRow views inside it. I wish to specify the height of the row programatically. E.g.
int rowHeight = calculateRowHeight();
TableLayout tableLayout = new TableLayout(activity);
TableRow tableRow = buildTableRow();
TableLayout.LayoutParams rowLp = new TableLayout.LayoutParams(
LayoutParams.FILL_PARENT, rowHeight);
tableLayout.addView(tableRow, rowLp);
But this isn't working and is defaulting to WRAP_CONTENT. Digging around in the Android source code, I see this in TableLayout (triggered by the onMeasure() method):
private void findLargestCells(int widthMeasureSpec) {
final int count = getChildCount();
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child instanceof TableRow) {
final TableRow row = (TableRow) child;
// forces the row's height
final ViewGroup.LayoutParams layoutParams = row.getLayoutParams();
layoutParams.height = LayoutParams.WRAP_CONTENT;
Seems like any attempt to set the row height will be overridden by the TableLayout. Anyone know a way around this?
OK, I think I've got the hang of this now. The way to set the height of the row is not to fiddle with the TableLayout.LayoutParams attached to the TableRow, but the TableRow.LayoutParams attached to any of the cells. Simply make one cell the desired height and (assuming its the tallest cell) the entire row will be that height. In my case, I added an extra 1 pixel wide column set to the desired height which did the trick:
View spacerColumn = new View(activity);
//add the new column with a width of 1 pixel and the desired height
tableRow.addView(spacerColumn, new TableRow.LayoutParams(1, rowHeight));
First of all, You should convert it from dps to pixels using the display factor formula.
final float scale = getContext().getResources().getDisplayMetrics().density;
int trHeight = (int) (30 * scale + 0.5f);
int trWidth = (int) (67 * scale + 0.5f);
ViewGroup.LayoutParams layoutpParams = new ViewGroup.LayoutParams(trWidth, trHeight);
tableRow.setLayoutParams(layoutpParams);
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
{ January 14, 2011... I have given up to use setListViewHeightBasedOnChildren(ListView listView},
instead, I don't put my listview in a scrollview, and then just put other contents
into a listview by using ListView.addHeaderView() and ListView.addFooterView().
http://dewr.egloos.com/5467045 }
ViewGroup(the ViewGroup is containing TextViews having long text except line-feed-character).getMeasuredHeight returns wrong value... that is smaller than real height.
how to get rid of this problem?
here is the java code:
/*
I have to set my listview's height by myself. because
if a listview is in a scrollview then that will be
as short as the listview's just one item.
*/
public static void setListViewHeightBasedOnChildren(ListView listView) {
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) {
// pre-condition
return;
}
int totalHeight = 0;
int count = listAdapter.getCount();
for (int i = 0; i < count; i++) {
View listItem = listAdapter.getView(i, null, listView);
listItem.measure(View.MeasureSpec.AT_MOST, View.MeasureSpec.UNSPECIFIED);
totalHeight += listItem.getMeasuredHeight();
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
listView.setLayoutParams(params);
}
and here is the list_item_comments.xml:
The question is rather old, but I had similar problem, so I'll describe what was wrong.
Actually, parameters in listItem.measure() are used wrong, you should set something like this:
listItem.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED))
However, be careful with unspecified width measure spec, it will ignore all layout params and even screen dimensions, so to get correct height, first get maximum width View can use and call measure() this way:
listItem.measure(MeasureSpec.makeMeasureSpec(maxWidth, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
This is the only solution i have found so far.
http://syedrakibalhasan.blogspot.com/2011/02/how-to-get-width-and-height-dimensions.html
It also gives wrong value when Your xml file of listview item has padding. Remove padding, try using margin and it will work perfectly.