LinearLayout clipping children with TextView width set to wrap_content - android

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.

Related

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.

match_parent not performing as expected

I imagine this should be a fairly easy one to answer, if you understand XML Layouts better than I do that is. I don't seem to get what I was thinking I should when using the match_parent layout_height.
I have a LinearLayout root element with android:orientation="vertical". Inside this LinearLayout I want three elements:
- TextView
- ListView
- TextView
For both the TextViews I set android:layout_height="wrap_content" so that they will be only as tall as is necessary to display their contents. The thing is, I want the one TextView to sit at the top of the form, the other one to sit at the bottom of the form while the ListView fills up whatever space is available on the form. So here is what my xml layout looks like:
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="30sp"
android:text="Top TextView" />
<ListView
android:id="#+id/listView_Species"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="30sp"
android:text="Bottom TextView" />
But it doesn't work. Here's what I get. I've selected the ListView so that it will be highlighted. Notice how it extends all the way to the bottom of the form, pushing the bottom TextView off the form.
When I change the layout_height property of the ListView to some fixed value, like 180dp, this is what the form looks like. I'm just posting this to prove that the bottom TextView is there but I still don't know how to get it to be fixed to the bottom of the screen while the ListView takes up whatever space remains, but in between the two TextViews.
Thanks in advance.
While the other answers try to fix your problem (which they don't actually--they suggest you do something that looks similar but may or may not look good on different devices), no one has filled in the gaps in your knowledge of LinearLayouts and match_parent. And these gaps are very common--Google's documentation is still far below stellar.
First, how do Views work within a LinearLayout? Let's go through the process of drawing a LinearLayout, using orientation="vertical" for simplicity.
Examine the height of the first child of the LinearLayout (LL for short). If the height is match_parent or fill_parent (old name for the same thing) then the height of the View is stretched to fill the entire viewing area. If the height is wrap_content, then measure the vertical space the View takes and use that space for the View. If the height is a non-zero number, use exactly that many pixels for the View's height (may clip if too small). If the height is 0 see below.
Put the next view below the view in 1. Check its height and act accordingly.
Continue for all the Views. If a View is pushed off the bottom, go ahead and stop calculating because no one will see it or any succeeding Views (assuming no ScrollView).
If the height of a View is 0, check it's gravity. This requires a second pass, storing the gravity of all the views and then allocating their heights proportionally. As you can guess, the second pass doubles the time layout takes, which isn't significant for simple layouts.
Explanation of your example: The first child of the LL (the first TextView) is measured and takes a certain amount of pixels. Then your ListView takes all the remaining space (via match_parent). And then your second TextView is not drawn at all as it's off the bottom of the screen. Which is pretty much what you observed, but now you understand why.
Solution: Use RelativeLayout. Works perfectly in this case.
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/top_tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:textSize="30sp"
android:text="Top TextView" />
<TextView
android:id="#+id/bottom_tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:textSize="30sp"
android:text="Bottom TextView" />
<ListView
android:id="#+id/listView_Species"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/top_tv"
android:layout_above="#id/bottom_tv"
/>
</RelativeLayout>
The RelativeLayout tells the layout inflater to draw the first TextView at the top, then draw the second TextView at the bottom, and then fill the rest of the space with your ListView. I believe this is exactly what you want.
Welcome to Android. You'll be using this pattern a LOT!
Change the ListView height to 0dp and add weight=1
i.e.:
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="30sp"
android:text="Top TextView" />
<ListView
android:id="#+id/listView_Species"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="30sp"
android:text="Bottom TextView" />
use android:layout_weight to define weights to your widgets inside the outermost layout. Declare their height as 0dp and then define android:layout_weight to each one of them .
Total weigh sum of the three of them should be 1. According to your need you can deine 0.1 weight to both top and bottom TextView's and define 0.8 to ListView.
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight = "0.1"
android:textSize="30sp"
android:text="Top TextView" />
<ListView
android:id="#+id/listView_Species"
android:layout_width="match_parent"
android:layout_weight = "0.8"
android:layout_height="0dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:textSize="30sp"
android:layout_weight = "0.1"
android:text="Bottom TextView" />

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

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

Not able to see views on screen

My Login screen layout seems like this:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/login_layout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#ffffff">
<include
android:id="#+id/headerlayout"
layout="#layout/headerview"
android:layout_height="50dip"
android:layout_width="fill_parent" />
<ImageView
android:id="#+id/imgIcon"
android:src="#drawable/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/txtUserName"
android:layout_width="fill_parent"
android:layout_height="80dip"
android:lines="1"
android:textColor="#000000"
android:textStyle="bold"
android:textSize="16dip"
android:text="User Name"/>
</LinearLayout>
However I am not able to see ImageView and TextView. Only headerview is visible and white layout below it. Why is it so?
Thanks,
Stone
just add
android:orientation="vertical"
in your <LinearLayout> tag.
Edit:
By default the orientation is set to Horizontal means every component will be added horizontally, since you are using "fill_parent" to the header, so it covers all the place(width) and leave no room for other components to appear. So when you add vertical all components are placed vertically. So enough room is available for components to layout themselves.More detail here
Bydefault LinearLayout aligns all children in a single direction horizontally (if you dont specify android:orientation ) .
So here in your case it was adding views horizontally. Your header portion took full width of the screen (as you have specified android:layout_width="fill_parent" in include tag)and no space is left for that TextView and ImageView.
You just have to add orientation tag in LinearLayout and set its value to vertical.
ie android:orientation="vertical".
LinearLayout from Android Docs says
LinearLayout aligns all children in a single direction — vertically or horizontally, depending on how you define the orientation attribute. All children are stacked one after the other, so a vertical list will only have one child per row, no matter how wide they are, and a horizontal list will only be one row high (the height of the tallest child, plus padding). A LinearLayout respects margins between children and the gravity (right, center, or left alignment) of each child.

Categories

Resources