I'm looking for some insights into the layout system. Is anyone aware of a method in the Android layout system that allows peer View elements (meaning Views grouped together in the same container) to match their height and width attributes without creating an interstitial container just to govern their sizes?
For example: A layout has two TextView elements. The first should always wrap width to its text content, but the second should match the width of the first. A solution that WORKS is this:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="#+id/textOne"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/textTwo"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</RelativeLayout>
However, I had to create a special container for both views to ensure they both match the width of whatever text is in the first; adding unnecessary complexity to the hierarchy. What I would love to know is if there is a layout attribute I could use to do something like this:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:id="#+id/textOne"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/textTwo"
android:layout_widthMatchPeer="#id/textOne" <!-- An attribute like this -->
android:layout_height="wrap_content"
android:layout_below="#id/textOne" />
</RelativeLayout>
Creating a hard dimension as the width is defeating the purpose of letting the primary element wrap. Is there a technique someone is aware of, or an attribute I've missed, to accomplish this? Could be in any standard layout, I just chose RelativeLayout as an example.
Additionally, what if the elements are not located near each other?
Cheers.
I think the RelativeLayout class can do what you want:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:id="#+id/textOne"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/textTwo"
android:layout_alignLeft="#id/textOne"
android:layout_alignRight="#id/textOne"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/textOne" />
</RelativeLayout>
since the views are in a relatve layout, use android:layout_below="id/firsttv" android:layout_alignLeft="id/firsttv" and android:layout_alightRight="id/firsttv"
Related
I have the following Android layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="16dp"
android:orientation="vertical" >
<TextView
android:id="#+id/slideTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="10dip"
android:padding="#dimen/px20"
android:text="#string/login_message"
android:textSize="#dimen/px25"
android:textStyle="bold" />
<TextView
android:id="#+id/slideDescription"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableLeft="#drawable/password"
android:drawablePadding="#dimen/px20"
android:drawableStart="#drawable/password"
android:padding="#dimen/px20"
android:text="#string/login_message_body"
android:textSize="#dimen/px20" />
<TextView
android:id="#+id/swipeMessage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:text="" />
</RelativeLayout>
But all the elements are positioned at the top of the screen one on top of the other, like if they didn't occupy any space.
That's not what what it seems to happen in the RelativeLayout documentation, where all elements are vertically positioned one below the other.
What's going on here?
So you need to use the id of the other components to align then properly.
For example the TextView with the id #+id/slideDescription should also have
android:layout_below="#+id/slideTitle" as one of the properties of the xml.
And the TextView with the id #+id/swipeMessage should also have
android:layout_below="#+id/slideDescription" as one of the properties of the xml.
In order to place one view below another in RelativeLayout you have to use layout_below property and set the ID of View you want to be above the specified one. But actually in order to place views vertically below each other it is more convenient to use LinearLayout with orientation set to vertical
layout_below is missed in the above xml code.I replaced the code with that please use that.
In Relative layout elemnets will be arranged relative to other elements in order to do this we should use id values of individual view elments
android:layout_below="#id/slideTitle" should be placed in description text view
android:layout_below="#id/slideDescription" should be placed in message text view
in order to get the output you desired please use the below code
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="16dp" >
<TextView
android:id="#+id/slideTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="10dip"
android:padding="#dimen/px20"
android:text="#string/login_message"
android:textSize="#dimen/px25"
android:textStyle="bold" />
<TextView
android:id="#+id/slideDescription"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/slideTitle"
android:drawableLeft="#drawable/password"
android:drawablePadding="#dimen/px20"
android:drawableStart="#drawable/password"
android:padding="#dimen/px20"
android:text="#string/login_message_body"
android:textSize="#dimen/px20" />
<TextView
android:id="#+id/swipeMessage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_below="#id/slideDescription"
android:text="" />
Before someone says that I should google this, I want to point out that I did and then i tried all the different methods to see what would work and nothing did for me. So, now that ugly business is out of the way on with my questions.... :)
I cannot seem to get a text view to wrap for me. Dont know why. Here is my XML code for the layout. It is a table layout that will be used for a listview in another xml layout.
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TableRow
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/ot_color_priority"
android:layout_height="fill_parent"
android:layout_width="20dp"
android:gravity="center_vertical"/>
<RelativeLayout>
<TextView
android:id="#+id/ot_ticket_number"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:gravity="center"
android:textStyle="bold"/>
<TextView
android:id="#+id/ot_ticket_details"
android:layout_alignParentBottom="#id/ot_ticket_number"
android:layout_height="wrap_content"
android:layout_width="300dp"
android:layout_marginTop="15dp"
android:scrollHorizontally="false"
android:ellipsize="none"
android:maxLines="10"
android:text="This is a long dang string that never wants to freaking wrap worth a crap!"/>
</RelativeLayout>
</TableRow>
</TableLayout>
The data that is in the textview just continues to write off the screen to the right. I cannot get it to wrap. The only way I can seem to get it to work is if I set a DP value to the layout_width. I dont want to do that because it will be used on different devices screen resolutions and I am afraid that may cause some problems later on.
So please someone help me :(
You should set android:shrinkColumns="1" to your TableLayout.
It will shrink the second column which is occupied by RelativeLayout.
It's probably your RelativeLayout which does not have any width specified, so it is defaulting to "WRAP_CONTENT" :
http://developer.android.com/reference/android/widget/RelativeLayout.html#generateDefaultLayoutParams()
I should also point out that inside that TextView you have a child with a "match_parent" width, but the relative layout will sit next to an element with a "20dp" width.
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TableRow
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/ot_color_priority"
android:layout_height="fill_parent"
android:layout_width="20dp"
android:gravity="center_vertical"/>
<!-- this is the problem, the layout has no parameters set -->
<RelativeLayout>
<TextView
android:id="#+id/ot_ticket_number"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:gravity="center"
android:textStyle="bold"/>
<TextView
android:id="#+id/ot_ticket_details"
android:layout_alignParentBottom="#id/ot_ticket_number"
android:layout_height="wrap_content"
android:layout_width="300dp"
android:layout_marginTop="15dp"
android:scrollHorizontally="false"
android:ellipsize="none"
android:maxLines="10"
android:text="This is a long dang string that never wants to freaking wrap worth a crap!"/>
</RelativeLayout>
</TableRow>
</TableLayout>
In a layout resource XML, I have 3 RelativeLayout(s) which are inside a main RelativeLayout. The view will be shown vertically. These 3 RelativeLayout() are set next to each other, and I want them to fill the whole screen, doesnt matter what will be the screen size. My, layout view:
<RelativeLayout 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:background="#drawable/backg"
>
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginTop="#dimen/top_mr_image"
android:src="#drawable/temp" />
<RelativeLayout
android:id="#+id/r1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_below="#+id/imageView1"
android:layout_marginLeft="10dp"
android:background="#drawable/r1bg"
android:layout_weight="1"
>
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_marginLeft="#dimen/txt_mr_right"
android:layout_marginRight="#dimen/txt_mr_right"
android:layout_marginTop="39dp"
android:text="S"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="#+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="#id/textView1"
android:layout_marginLeft="#dimen/txt_mr_right"
android:layout_marginRight="#dimen/txt_mr_right"
android:text="T"
android:textAppearance="?android:attr/textAppearanceLarge" />
</RelativeLayout>
<RelativeLayout
android:id="#+id/r2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignTop="#+id/r1"
android:layout_toRightOf="#+id/r1"
android:layout_weight="1" >
</RelativeLayout>
<RelativeLayout
android:id="#+id/r3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignTop="#+id/r2"
android:layout_toRightOf="#+id/r2"
android:layout_weight="1" >
</RelativeLayout>
I set weight=1 and layout_width=0dp for each relativeLayout and this technique works with buttons, I thought the same will be with relativeLayout, seems my thoughts were wrong. Any idea?
UPD1: I have added an image of what I would like to have
RelativeLayout does not pay attention to android:layout_weight. (That's a property of LinearLayout.LayoutParams, but not of RelativeLayout.LayoutParams.)
You should be able to get the layout you want with a much simpler view hierarchy. It's not clear what you are trying to do, since the last two RelativeLayouts are empty. If you need a purely vertical organization, I'd suggest using LinearLayout instead of RelativeLayout.
EDIT Based on your edit, it looks like you want a horizontal layout of three compound views, each one clickable. I think something like the following will work:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<!-- First column -->
<LinearLayout
android:id="#+id/firstColumn"
android:orientation="vertical"
android:gravity="center_horizontal"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="..." />
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="text 1"
. . . />
</LinearLayout>
<!-- Second column -->
<LinearLayout . . . >
. . .
</LinearLayout>
</LinearLayout>
If the contents of the buttons aren't correct, you can replace the second-level LinearLayout views with RelativeLayout if that helps organize the layout better.
RelativeLayouts do not support weight. You need to use a LinearLayout as a parent container if you want to use weights.
Solution is very simple. I have been looking for weight distribution in relative layout.
It's a small trick for all these kind situations.
Use LinearLayout with android:orientation="horizontal"
You can use Horizontally oriented LinearLayout Manager in the Recycler View, and place each RelativeLayout in each item, of its Adapter.
The Link: How to build a Horizontal ListView with RecyclerView?
If your RelativeLayouts are set to a fixed width and height, that is to the size of the Screen, that you can get from DisplayMatrics, that will be OK.
The Link: Get Screen width and height
If the contents of your RelativeLayouts are different, then you can use getItemViewType() method.
Please see: How to create RecyclerView with multiple view type?
Happy Coding :-)
I have a LinearLayout that has four views layed out horizontally. The first and last component are a set size. For the inner two views I want to just share the available space 50:50. I set each to a weight of "1" but when the views are layed out, the views are different sizes depending on the content they hold.
Here is my layout xml for reference.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/status"
android:src="#drawable/white"
android:paddingRight="10dip"
android:layout_height="35dip"
android:layout_width="35dip">
</ImageView>
<TextView android:id="#+id/name"
android:text="Name"
android:layout_height="fill_parent"
android:layout_toRightOf="#id/status"
android:layout_width="wrap_content"
android:layout_weight="1"
android:textSize="25dip">
</TextView>
<TextView android:id="#+id/description"
android:text="Description"
android:layout_toRightOf="#id/name"
android:layout_height="fill_parent"
android:layout_width="wrap_content"
android:layout_weight="1"
android:textSize="25dip">
</TextView>
<TextView android:id="#+id/time"
android:text="Time"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_toRightOf="#id/description"
android:textSize="25dip">
</TextView>
</LinearLayout>
Obviously these aren't the actual column names but I changed them for privacy purposes. This layout is used by a ListView which changes the text of each view to be whatever value its presented. The name and description fields should line up since they're both given 50% of the remaining screen but when the name is longer the description is shifted right. Why?
For the weight to be considered, the layout dimension needs to be 0 (zero)
<TextView android:id="#+id/name"
android:text="Name"
android:layout_height="fill_parent"
android:layout_width="0dip"
android:layout_weight="1"
android:textSize="25dip">
</TextView>
I also recommend making your weight add up to either 1 (and use fractions) or 100.
So instead of 1 you would use either 50 or .5 for each view. The LinearLayout code will work properly with any weight sum, but it gets difficult if you want to modify your view later with additional sections.
Also, if you are not using relative layout, get rid of the toRightOf attributes. Less is more.
Try to use android:layout_width="fill_parent" instead of "wrap_content" in all children of LinearLayout. Or better yet, make such a structure in your xml:
<RelativeLayout>
<ImageView /> # status, fixed width, alignParentLeft="true"
<TextView /> # time, fixed width, alignParentRight="true"
<LinearLayout> # layout_width="fill_parent", toLeftOf="time" toRightOf="status"
<TextView /> # name, use layout_weight="1"
<TextView /> # description, use layout_weight="1"
</LinearLayout>
</RelativeLayout>
This should do what you want. Using LinearLayout instead of RelativeLayout might work too, but you have to experiment a bit (I believe using nested Layout, as in my example, will do the work).
I have a TextView which I want to pin at the bottom of a landscape activity that is using LinearLayout with vertically arranged elements.
I have set android:gravity="bottom" on the text view, but it still likes to be just below the last element of the LinearLayout exactly what I do not want it to do.
Any suggestions?
You will have to expand one of your upper views to fill the remaining space by setting android:layout_weight="1" on it. This will push your last view down to the bottom.
Here is a brief sketch of what I mean:
<LinearLayout android:orientation="vertical">
<View/>
<View android:layout_weight="1"/>
<View/>
<View android:id="#+id/bottom"/>
</LinearLayout>
where each of the child view heights is "wrap_content" and everything else is "fill_parent".
Update: I still get upvotes on this question, which is still the accepted answer and which I think I answered poorly. In the spirit of making sure the best info is out there, I have decided to update this answer.
In modern Android I would use ConstraintLayout to do this. It is more performant and straightforward.
<ConstraintLayout>
<View
android:id="#+id/view1"
...other attributes elided... />
<View
android:id="#id/view2"
app:layout_constraintTop_toBottomOf="#id/view1" />
...other attributes elided... />
...etc for other views that should be aligned top to bottom...
<TextView
app:layout_constraintBottom_toBottomOf="parent" />
If you don't want to use a ConstraintLayout, using a LinearLayout with an expanding view is a straightforward and great way to handle taking up the extra space (see the answer by #Matthew Wills). If you don't want to expand the background of any of the Views above the bottom view, you can add an invisible View to take up the space.
The answer I originally gave works but is inefficient. Inefficiency may not be a big deal for a single top level layout, but it would be a terrible implementation in a ListView or RecyclerView, and there just isn't any reason to do it since there are better ways to do it that are roughly the same level of effort and complexity if not simpler.
Take the TextView out of the LinearLayout, then put the LinearLayout and the TextView inside a RelativeLayout. Add the attribute android:layout_alignParentBottom="true" to the TextView. With all the namespace and other attributes except for the above attribute elided:
<RelativeLayout>
<LinearLayout>
<!-- All your other elements in here -->
</LinearLayout>
<TextView
android:layout_alignParentBottom="true" />
</RelativeLayout>
I think it will be perfect solution:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!-- Other views -->
<Space
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
<!-- Target view below -->
<View
android:layout_width="match_parent"
android:layout_height="wrap_content">
</LinearLayout>
Step 1 : Create two view inside a linear layout
Step 2 : First view must set to android:layout_weight="1"
Step 3 : Second view will automatically putted downwards
<LinearLayout
android:id="#+id/botton_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<View
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<Button
android:id="#+id/btn_health_advice"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
You should put the parameter gravity to bottom not in the textview but in the Linear Layout. Like this:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="bottom|end">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Something"/>
</LinearLayout>
You can also use
android:layout_gravity="bottom"
for your textview
DO LIKE THIS
<LinearLayout
android:id="#+id/LinearLayouts02"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="bottom|end">
<TextView
android:id="#+id/texts1"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:layout_weight="2"
android:text="#string/forgotpass"
android:padding="7dp"
android:gravity="bottom|center_horizontal"
android:paddingLeft="10dp"
android:layout_marginBottom="30dp"
android:bottomLeftRadius="10dp"
android:bottomRightRadius="50dp"
android:fontFamily="sans-serif-condensed"
android:textColor="#color/colorAccent"
android:textStyle="bold"
android:textSize="16sp"
android:topLeftRadius="10dp"
android:topRightRadius="10dp"
/>
</LinearLayout>
try this
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:orientation="vertical" >
<TextView
android:id="#+id/textViewProfileName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView" />
</LinearLayout>