android: How to force TableRows to have the same height? - android

I have searched google and stackoverflow thoroughly, but the only answer I get is: set each Tablerow with layout weight = "1". This doesnt work.
Now I have eight rows in a TableLayout, and each contains 5 LinearLayouts. Each of the LinearLayouts contains 2 TextViews, and the FontSizes vary from TextView to TextView.
It turns out that the TableRows vary in height, depending on the Fontsizes of the contained TextViews.
Strangely enough, it doesnt have any impact on the layout whether I set the layout_height of the TableRows to "0dp" or to "match_parent" or "fill_parent".
How can I force the TableRows to have the same height? I dont want to use a specific pts value as height, because the tableRows must divide the whole screen equally between themselves.
Here is part of the xml, the actual file is huge:
<TableLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="6"
android:weightSum="8"
tools:context=".MainActivity" >
<TableRow
android:layout_width="match_parent"
android:layout_weight="1"
tools:context=".MainActivity">
<LinearLayout
android:clickable="true"
android:orientation="vertical"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginTop="#dimen/btnmargintop"
android:layout_marginBottom="#dimen/btnmarginbot"
android:layout_marginLeft="#dimen/btnmarginleft"
android:layout_marginRight="#dimen/btnmarginright"
android:layout_weight="1"
android:background="#drawable/bg" >
<myapp.TypefacedTextView
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="#integer/layoutweight1"
android:layout_gravity="center"
stevens:typeface="myfont.otf"
android:clickable="false"
android:textSize="#dimen/fontsize1" />
<myapp.TypefacedTextView
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="#integer/layoutweight2"
android:layout_gravity="center"
stevens:typeface="myfont.otf"
android:clickable="false"
android:textSize="#dimen/fontsize2" />
</LinearLayout>

According to the Android developer Documentation of TableLayout, you cannot do that.
The children of a TableLayout cannot specify the layout_width
attribute. Width is always MATCH_PARENT. However, the layout_height
attribute can be defined by a child; default value is
ViewGroup.LayoutParams.WRAP_CONTENT. If the child is a TableRow, then
the height is always ViewGroup.LayoutParams.WRAP_CONTENT.
However, you can use a vertical LinearLayout to achieve a similar effect.

You are probably letting the layout of your tab to automatically adjust to the size of the content inside. There are two ways, to settle things down:
Make sure all the elements share the same size - that being said, don't worry about the table as a whole, just make sure, that the dimensions of the elements inside are the same
Or simply set the height of the parent layout and don't let the elements make a difference. Problem with this solution is, that if you get bigger inside, you'll be out of space, so you may want to stick with the first option

Related

LinearLayout clipping children with TextView width set to wrap_content

I have a LinearLayout which contains a TextView and an ImageView. The TextView width is set to wrap_content, but the issue is when the width reaches the parent width. The text content will correctly wrap to 2 or more lines, but the TextView and ImageView will be clipped on the left and right sides. The most similar question I could find was this one, which is from 2013 and has no solution.
Specifically, I'm experiencing the issue on this view, but I've created the following simpler view to exemplify the problem:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/card_top_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal">
<TextView
android:id="#+id/card_top_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="One Two Three Four Five"
android:textSize="40sp"/>
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:src="#drawable/ic_volume_up_black_48dp"/>
</LinearLayout>
Here is the problem:
Here is the layout normally:
When the layout overlaps another view, setting android:clipChildren="false" on the LinearLayout doesn't even prevent the clipping.
And here is one final image to prove it's happening on a real device and not just the layout viewer:
I'm basically out of ideas. Any thoughts? Is this an issue with the Android layout system? Thanks for the help and consideration!
You can achieve the desired result using android:layout_weight
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/card_top_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal">
<TextView
android:id="#+id/card_top_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="One Two Three Four Five"
android:textSize="40sp"/>
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:src="#drawable/ic_volume_up_black_48dp"/>
</LinearLayout>
Edit: A little quote from the docs about how layout_weight works
LinearLayout also supports assigning a weight to individual children with the android:layout_weight attribute. This attribute assigns an "importance" value to a view in terms of how much space it should occupy on the screen. A larger weight value allows it to expand to fill any remaining space in the parent view. Child views can specify a weight value, and then any remaining space in the view group is assigned to children in the proportion of their declared weight. Default weight is zero.
For example, if there are three text fields and two of them declare a weight of 1, while the other is given no weight, the third text field without weight will not grow and will only occupy the area required by its content. The other two will expand equally to fill the space remaining after all three fields are measured. If the third field is then given a weight of 2 (instead of 0), then it is now declared more important than both the others, so it gets half the total remaining space, while the first two share the rest equally.

Understanding android:layout_weight

Why the following listing shows only the second TextView (red)?
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="11111"
android:background="#00FF00" />
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="0"
android:background="#FF0000"
android:text="00000"/>
</LinearLayout>
I know that if I set android:layout_height="0px" it will only show the first TextView (green), and I understand this behavior.
But why when I set android:layout_height="match_parent", the first TextView disappear completely from the screen.
From https://developer.android.com/guide/topics/ui/layout/linear.html
It disappers because it second one acquires full space as it is given
android:layout_weight="0"
and
android:layout_height="match_parent"** as mentioned in above link.
LinearLayout also supports assigning a weight to individual children
with the android:layout_weight attribute. This attribute assigns an
"importance" value to a view in terms of how much space it should
occupy on the screen. A larger weight value allows it to expand to
fill any remaining space in the parent view. Child views can specify a
weight value, and then any remaining space in the view group is
assigned to children in the proportion of their declared weight.
Default weight is zero.
For example, if there are three text fields and two of them declare a
weight of 1, while the other is given no weight, the third text field
without weight will not grow and will only occupy the area required by
its content. The other two will expand equally to fill the space
remaining after all three fields are measured.
If the third field is then given a weight of 2 (instead of 0), then it
is now declared more important than both the others, so it gets half
the total remaining space, while the first two share the rest equally.
android:layout_weight="1" means you are assigning the remaining space which is not occupied by other views to that view.. so here in your case second TextView is match_parent so no space is left blank thats why first TextView is not visible
P.S: Pass weightsum to the parent layout and distribute that weight among child Views according to your need.
Thanks
android:layout_weight means how u want these views to be showed comparing to each other and the parent view
for exampel, if u these codes:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Button2"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Button1"/>
</LinearLayout>
the result will be this image
if i change android:layout_weight of Button1 from 1 to 2 while Button2's weight is still 1, then Button1's Width will be 2times bigger than Button2's
Your code is basically saying, give my first text view all the space and my second text view none, try giving the children each a weight of 1, this should give them equal spacing. Also as you have a vertical oriented parent, setting the layout height in the children to match the parent is contradicting to the weight attribute. So remove it and replace with wrap content.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="11111"
android:background="#00FF00" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#FF0000"
android:text="00000"/>
</LinearLayout>
https://developer.android.com/guide/topics/ui/layout/linear.html
https://developer.android.com/reference/android/view/ViewGroup.LayoutParams.html
https://ugia.io/2012/01/19/android-linearlayout-distribution-explained-weight-and-sizes/
match_parent is different from wrap_content or specific sizes(0px, 1px, 100px etc.), it will take all space of parent view till the size of LinearLayout in your case.
layout_weight is for balancing, and it depends on your layout_width
But why, if I set in the second TextView:
android: layout_weight = "0.1"
the second component of the TextView will take less space than if I set:
android: layout_weight = "0"
And if I set in the second TextView
android: layout_weight = "0.2"
the second component of the TextView will take even less space than if I set
android: layout_weight = "0.1"
So if I set higher the value of android:layout_weight, that it occupies a smaller size.
You have set the weight value of the first button to 1 and the second to 0,
so button one will cover the whole space
You should give a weight total to the parent layout and distribute the total between the children according to the desired proportion.

Android RelativeLayout: Rightmost child takes all the extra space no matter what I do

I have a RelativeLayout with three child views laid out horizontally. I want the leftmost one to take up any extra space and the other two to take up only the space needed to wrap their content. The documentation says this can be done, but I can't make it work. Here's what I have:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="6dp"
android:textStyle="bold"
android:layoutDirection="rtl">
<TextView
android:id="#+id/nodeLabel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="#dimen/text_size"
android:gravity="fill_horizontal"
android:layout_alignParentLeft="true" />
<Button
android:id="#+id/launch"
android:text="#string/launch_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#id/nodeLabel"
android:gravity="left" />
<Button
android:id="#+id/kill"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#id/launch"
android:layout_alignParentRight="true"
android:text="#string/kill_label"
android:gravity="left" />
</RelativeLayout>
The result is the TextView takes up all the space, and the two Buttons are not rendered at all. If I change android:layout_width on the TextView from match_parent to wrap_content, then all three Views show up, but the third one, the Button, takes the extra space, which is not what I want. I also tried setting layout_width on the Buttons to 0dp, and experimented with other settings values, all to no avail.
How can I make the two Buttons no bigger than needed to wrap their content, and have the TextView take up the extra space?
add the propery android:layout_weight="x".
It works like this:
if there are 4 views in a row and every one has a weight of 1. Then every view occupies 1/4 of the space. If one has a weight of 2 then it occupies 2/5 and so on. If one has a weight of 0 or no weight, then it just occupies as much space as its content does. The system adds all the weights together and then sets every view the proportional width.
In your case you have to weigh them something like 1, 0, 0.

Why is 0dp considered a performance enhancement?

An answer at the end of this question has been filled out, combining remarks and solutions.
Question
I searched around but haven't found anything that really explains why Android Lint as well as some Eclipse hints suggest replacing some layout_height and layout_width values with 0dp.
For example, I have a ListView that was suggested to be changed
Before
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1">
</ListView>
After
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
</ListView>
Similarly, it suggested changes to a ListView item. These all look the same before and after the changes, but I'm interested in understanding why these are performance boosters.
Anyone have an explanation of why? If it helps, here is general layout with the ListView.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ImageView
android:id="#+id/logo_splash"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</ImageView>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:background="#color/background"
android:layout_below="#id/logo_splash">
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
</ListView>
<TextView
android:id="#android:id/empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/no_upcoming" />
</LinearLayout>
</RelativeLayout>
Answer
I'm putting in an answer here because it's really a combination of answers and referenced links below. If I'm wrong on something, do let me know.
From What is the trick with 0dip layout_height or layouth_width?
There are 3 general layout attributes that work with width and height
android:layout_height
android:layout_width
android:layout_weight
When a LinearLayout is vertical, then the layout_weight will effect the height of the child Views (ListView). Setting the layout_height to 0dp will cause this attribute to be ignored.
Example
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
</ListView>
</LinearLayout>
When a LinearLayout is horizontal, then the layout_weight will effect the width of the child Views (ListView). Setting the layout_width to 0dp will cause this attribute to be ignored.
Example
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal">
<ListView
android:id="#android:id/list"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1">
</ListView>
</LinearLayout>
The reason to want to ignore the attribute is that if you didn't ignore it, it would be used to calculate the layout which uses more CPU time.
Additionally this prevents any confusion over what the layout should look like when using a combination of the three attributes. This is highlighted by #android developer in an answer below.
Also, Android Lint and Eclipse both say to use 0dip. From that answer below, you can use 0dip, 0dp, 0px, etc since a zero size is the same in any of the units.
Avoid wrap_content on ListView
From Layout_width of a ListView
If you've ever wondered why getView(...) is called so many times like I have, it turns out to be related to wrap_content.
Using wrap_content like I was using above will cause all child Views to be measured which will cause further CPU time. This measurement will cause your getView(...) to be called. I've now tested this and the number of times getView(...) is called is reduced dramatically.
When I was using wrap_content on two ListViews, getView(...) was called 3 times for each row on one ListView and 4 times for each row on the other.
Changing this to the recommended 0dp, getView(...) was called only once for each row. This is quite an improvement, but has more to do with avoiding wrap_content on a ListView than it does the 0dp.
However the suggestion of 0dp does substantially improve performance because of this.
First of all you have this,
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1">
</ListView>
Never take the ListView's height as wrap_content, that will lead into troubles. Here is the reason for that and this answer.
Further more,
I searched around but haven't found anything that really explains why
Android Lint as well as some Eclipse hints suggests replacing some
layout_height and layout_width values with 0dp.
Its because you are using layout_weight = "1" that means your ListView with take the height as much as is available to it. So, in that case there is no need of using layout_height = "wrap_content" just change it to android:layout_height="0dp" and ListView's height will be managed by layout_weight = "1".
So when android:layout_weight is used on View X and LinearLayout is horizontal, then X's android:layout_width is simply ignored.
Similar, when android:layout_weight is used on View X and LinearLayout is vertical, then X's android:layout_height is ignored.
This actually means, that you can put anything in those ignored fields: 0dp or fill_parent or wrap_content. It doesn't matter. But it's recommended to use 0dp so View's do not do extra calculation of their height or width (which is then ignored). This small trick simply saves CPU cycles.
from :
What is the trick with 0dip layout_height or layouth_width?
as far as i know , there is a difference between using 0dp (or 0px btw, it's the same since 0 is 0 no matter what is the unit here ) and the wrap_content or fill_parent (or match_parent, it's the same).
it depends on the weight you use . if you only use weight of 1 , they all look the same , but the meaning is always different , and it is important for performance.
in order to show this , try the following:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:orientation="vertical">
<TextView android:id="#+id/textView1" android:layout_width="match_parent"
android:layout_height="0px" android:text="1" android:background="#ffff0000"
android:layout_weight="1" android:gravity="center"
android:textColor="#ffffffff" android:textSize="20sp" />
<TextView android:id="#+id/textView2" android:layout_width="match_parent"
android:layout_height="0px" android:text="2" android:background="#ff00ff00"
android:layout_weight="2" android:gravity="center"
android:textColor="#ffffffff" android:textSize="20sp" />
<TextView android:id="#+id/textView3" android:layout_width="match_parent"
android:layout_height="0px" android:text="3" android:background="#ff0000ff"
android:layout_weight="3" android:gravity="center"
android:textColor="#ffffffff" android:textSize="20sp" />
</LinearLayout>
and then try to replace the 0px with match_parent . you will see that the result is very different.
usually , for both better understanding and for better performance , you would want to use 0px.
LinearLayout measures all the children according to the layout_width/layout_height values, then divides up the leftover space (which may be negative) according to the layout_weight values.
0dp is more efficient than wrap_content in this case because it's more efficient to just use zero for the original height and then split the parent's full height based on the weight than to measure the child first and then split the remainder based on the weight.
So the efficiency comes from not measuring the child. 0dp should be exactly as efficient (and produce exactly the same result) as match_parent, or 42px, or any other fixed number.
Caution re using android:layout_height="0dp"
I have found that in a ListView
(with the recommended View recycling using convertView, see e.g. http://lucasr.org/2012/04/05/performance-tips-for-androids-listview/),
setting android:layout_height="0dp" for the row TextView can lead to text truncation for multi-line text content.
Whenever a TextView object that was previously used to display a text that fitted in a single line is recycled to display a longer text that needs more than one line, that text is truncated to a single line.
The problem is cured by using android:layout_height="wrap_content"

Android - fill_parent not behaving as expected in RelativeLayout

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/frameLayout1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/background_gradient" >
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center" >
<ImageButton
android:id="#+id/buttonLog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/log"
android:onClick="log" />
</RelativeLayout>
</FrameLayout>
I was expecting my button to appear in the center of the screen. However, it appears on the TOP center of the screen (that is, the button is center horizontally, but not vertically).
It seems to me that the RelativeLayout is behaving like it was defined with "wrap_content" instead of "fill_parent".
The funny thing is that, if I give an actual value to my RelativeLayout height property (android:layout_height), like:
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="100dp"
android:gravity="center" >
Then the button behaves correctly (i.e. the button is also centred vertically). But I don`t want to use actual values. I want to use fill_parent! Why doesn't it work with "fill_parent" ??
Does anybody know what's going on?
Thank you in advance!
RelativeLayout requires you to specify the position of the elements in the Layout. I don't see any layout_below or layout_toLeftOf tags. Gravity works on LinearLayouts. In general, LinearLayouts are easier to work with, and they scale much better to different screen sizes. I suggest you replace the RelativeLayout by a LinearLayout, and also the FrameLayout by a LinearLayout. You use a FrameLayout typically if you want to use multiple overlapping layouts, which you don't do.
I recommend you read up on using layouts in the Android sdk reference documentation, like here: http://bit.ly/djmnn7
You specified fill_parent for both the layout_width and layout_height of your RelativeLayout, therefore it fills up it's parent view.
By default, a relative layout arranges it's children to the top-left corner, regardless you use fill_parent for the size.
You should achieve the desired aspect by taking advantage of the RelativeLayout's own attribute set, which helps you arrange the child views relatively to each other or to their parent:
<ImageButton
android:id="#+id/buttonLog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:background="#drawable/log"
android:onClick="log" />
Using the android:layout_centerInParent you can achieve this. This attribute if set true, centers this child horizontally and vertically within its parent.

Categories

Resources