Android: Container XML Layout wrap weight and fill height - android

I have been battling for a couple of days trying to create a custom layout in Android divided in 3 parts, a "vote" counter container that displays the amount of people that voted a message, a text message container that will contain the text and the author of a message and a button container that will be used to vote up or down a message.
So far I have this code
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/containerInner"
>
<!-- # VOTES CONTAINER -->
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/containerVotes"
android:layout_centerVertical="true"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:id="#+id/votesPost"
android:textStyle="bold"
android:textSize="16sp"
/>
</RelativeLayout>
<!-- MESSAGE CONTAINER -->
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/containerText"
android:layout_marginLeft="4dp"
android:layout_marginTop="4dp"
android:layout_toRightOf="#+id/containerVotes"
android:background="#color/gray"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#000000"
android:id="#+id/titleGlobus"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/AutorGlobus"
android:textColor="#000000"
android:textSize="12sp"
android:textStyle="italic"
android:maxWidth="180dp"
android:layout_weight="0.1"
android:layout_below="#+id/titleGlobus"
/>
</RelativeLayout>
<!-- VOTE UP/DOWN CONTAINER -->
<RelativeLayout
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:id="#+id/containerButtons"
android:layout_alignParentTop="true"
android:layout_toRightOf="#+id/containerText"
android:layout_toEndOf="#+id/containerText"
>
<RelativeLayout
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:id="#+id/containerButtonUp"
>
<at.markushi.ui.CircleButton
android:layout_width="32dip"
android:layout_height="32dip"
android:src="#mipmap/ic_arrow_drop_up_black_24dp"
app:cb_color="#color/white"
app:cb_pressedRingWidth="8dip"
android:id="#+id/upvote_button"
/>
</RelativeLayout>
<RelativeLayout
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:id="#+id/containerButtonDown"
android:layout_below="#+id/containerButtonUp"
>
<at.markushi.ui.CircleButton
android:layout_width="32dip"
android:layout_height="32dip"
app:cb_color="#color/white"
app:cb_pressedRingWidth="8dip"
android:src="#mipmap/ic_arrow_drop_down_black_24dp"
android:id="#+id/downvote_button"
/>
</RelativeLayout>
</RelativeLayout>
The Layout I am getting in the phone using the above code is this:
And I want to achieve this:
So there are two main things that I need to achieve here:
Make the RelativeLayout containerText fill the whole height of its superior container.
Alight the Author name to the right of the container, but aligned just at the end of the "message" TextView.
I have been trying to fix the fix issue changing the height of the containerText container to fill_parent without success, changing all the way up to the main container all the height properties to fill_parent.
If I try to align the author name to the right using alignParentRight=true , the RelativeLayout then takes the whole space of the screen, pushing out the buttons container. I have also tried changing the way I am positioning the different layouts respect others, changing the toLeftOf or toRightTo, with terrible results.
Any help would be highly appreciated as I am stuck with this issue.
Cheers!

Try this:
<!-- MESSAGE CONTAINER -->
<RelativeLayout
android:layout_width="wrap_content"
<!-- Set this height to match_parent -->
android:layout_height="match_parent"
android:id="#+id/containerText"
android:layout_marginLeft="4dp"
android:layout_marginTop="4dp"
android:layout_toRightOf="#+id/containerVotes"
android:background="#color/gray"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#000000"
android:id="#+id/titleGlobus"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/AutorGlobus"
android:textColor="#000000"
android:textSize="12sp"
android:textStyle="italic"
android:maxWidth="180dp"
android:layout_weight="0.1"
<!-- Removed below tag and added alignParentBottom and alignParentRight -->
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
/>
</RelativeLayout>

Related

Why doesn't gravity work when applied to Relative Layout?

I already understand that if I use layout_gravity="center_horizontal" on the text view, then the text will be center. But I don't want to use that because I want to have as little code as possible and the best way to do that is by applying gravity="center_horizontal" to my relative layout. I am also asking this question because I am concerned about even using gravity or layout_gravity with relative layouts at all. As when doing my research I came upon this answer.
Notice the part that says:
Don't use gravity/layout_gravity with a RelativeLayout. Use them for Views in LinearLayouts and FrameLayouts.
Even though it seems pretty apparent to me from the relative layout Android Documentation, which clearly lists gravity as a valid attribute, that Google intended these attributes to be used with relative layouts.
If that quote is correct, how do I center views in relative layouts?
Also, here is my code:
Notice the title is not centered horizontally
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:gravity="center_horizontal"
tools:context="com.something">
<TextView
android:id="#+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="#style/TextAppearance.AppCompat.Title"
android:textAlignment="center"
android:text="#string/app_title"
android:layout_marginBottom="#dimen/main_spacing"
android:textSize="24sp" />
<AutoCompleteTextView
android:id="#+id/enterContact"
android:text="Enter Contact"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAlignment="center"
android:layout_below="#+id/title"
android:layout_marginBottom="#dimen/main_spacing" />
</RelativeLayout>
This is a supplemental answer to Gravity and layout_gravity on Android.
View gravity and layout_gravity inside a Relative Layout
My original statement that gravity and layout_gravity should not be used in the subviews of a RelativeLayout was partly wrong. The gravity actually works fine. However, layout_gravity has no effect. This can be seen in the example below. The light green and light blue are TextViews. The other two background colors are RelativeLayouts.
As you can see, gravity works, but layout_gravity doesn't work.
Relative Layout with gravity
My original answer about gravity and layout_gravity dealt with these attributes being applied to the Views within a ViewGroup (specifically a LinearLayout), not to the ViewGroup itself. However, it is possible to set gravity and layout_gravity on a RelativeLayout. The layout_gravity would affect how the RelativeLayout is positioned within its own parent, so I will not deal with that here. How gravity affects the subviews, though, is shown in the image below.
I resized the widths of all the subviews so that what is happening is more clear. Note that the way RelativeLayout handles gravity is to take all the subviews as a group and move them around the layout. This means that whichever view is widest will determine how everything else is positioned. So gravity in a Relative layout is probably only useful if all the subviews have the same width.
Linear Layout with gravity
When you add gravity to a LinearLayout, it does arrange the subviews as one would expect. For example, one could "save code" by setting the gravity of LinearLayout to center_horizontally. That way there is no need individually set the layout_gravity of each subview. See the various options in the image below.
Note that when a view uses layout_gravity, it overrides the LinearLayout's gravity. (This can be seen in the title for the two layouts in the left image. The LinearLayout gravity was set to left and right, but the title TextView's layout_gravity was set to center_horizontally.)
Final notes
When positioning views within a RelativeLayout, the general way to do it is adding things like the following to each view:
layout_alignParentTop
layout_centerVertical
layout_below
layout_toRightOf
If one wants to set all the views at once, a LinearLayout would likely be better (or perhaps using a Style).
So to sum up,
The layout_gravity does not work for subviews in a RelativeLayout.
The gravity of a RelativeLayout does work, but not as one might expect.
Supplemental XML
XML for image "View gravity and layout_gravity inside a Relative Layout":
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#e3e2ad" >
<TextView
android:id="#+id/tvTop1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:textSize="24sp"
android:text="Views' gravity=" />
<!-- examples of gravity -->
<TextView
android:id="#+id/tvTop2"
android:layout_below="#id/tvTop1"
android:layout_width="200dp"
android:layout_height="40dp"
android:background="#bcf5b1"
android:gravity="left"
android:text="left" />
<TextView
android:id="#+id/tvTop3"
android:layout_below="#id/tvTop2"
android:layout_width="200dp"
android:layout_height="40dp"
android:background="#aacaff"
android:gravity="center_horizontal"
android:text="center_horizontal" />
<TextView
android:id="#+id/tvTop4"
android:layout_below="#id/tvTop3"
android:layout_width="200dp"
android:layout_height="40dp"
android:background="#bcf5b1"
android:gravity="right"
android:text="right" />
<TextView
android:id="#+id/tvTop5"
android:layout_below="#id/tvTop4"
android:layout_width="200dp"
android:layout_height="40dp"
android:background="#aacaff"
android:gravity="center"
android:text="center" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#d6c6cd" >
<TextView
android:id="#+id/tvBottom1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:textSize="24sp"
android:text="Views' layout_gravity=" />
<!-- examples of layout_gravity -->
<TextView
android:id="#+id/tvBottom2"
android:layout_below="#id/tvBottom1"
android:layout_width="200dp"
android:layout_height="40dp"
android:layout_gravity="left"
android:background="#bcf5b1"
android:text="left" />
<TextView
android:id="#+id/tvBottom3"
android:layout_below="#id/tvBottom2"
android:layout_width="200dp"
android:layout_height="40dp"
android:layout_gravity="center_horizontal"
android:background="#aacaff"
android:text="center_horizontal" />
<TextView
android:id="#+id/tvBottom4"
android:layout_below="#id/tvBottom3"
android:layout_width="200dp"
android:layout_height="40dp"
android:layout_gravity="right"
android:background="#bcf5b1"
android:text="right" />
<TextView
android:id="#+id/tvBottom5"
android:layout_below="#id/tvBottom4"
android:layout_width="200dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:background="#aacaff"
android:text="center" />
</RelativeLayout>
</LinearLayout>
XML for image "Relative Layout with gravity":
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="center_horizontal"
android:background="#e3e2ad" >
<TextView
android:id="#+id/tvTop1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="24sp"
android:text="Views' gravity=" />
<!-- examples of gravity -->
<TextView
android:id="#+id/tvTop2"
android:layout_below="#id/tvTop1"
android:layout_width="200dp"
android:layout_height="40dp"
android:background="#bcf5b1"
android:gravity="left"
android:text="left" />
<TextView
android:id="#+id/tvTop3"
android:layout_below="#id/tvTop2"
android:layout_width="300dp"
android:layout_height="40dp"
android:background="#aacaff"
android:gravity="center_horizontal"
android:text="center_horizontal" />
<TextView
android:id="#+id/tvTop4"
android:layout_below="#id/tvTop3"
android:layout_width="100dp"
android:layout_height="40dp"
android:background="#bcf5b1"
android:gravity="right"
android:text="right" />
<TextView
android:id="#+id/tvTop5"
android:layout_below="#id/tvTop4"
android:layout_width="150dp"
android:layout_height="40dp"
android:background="#aacaff"
android:gravity="center"
android:text="center" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="center"
android:background="#d6c6cd" >
<TextView
android:id="#+id/tvBottom1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="24sp"
android:text="Views' gravity=" />
<!-- examples of layout_gravity -->
<TextView
android:id="#+id/tvBottom2"
android:layout_below="#id/tvBottom1"
android:layout_width="200dp"
android:layout_height="40dp"
android:gravity="left"
android:background="#bcf5b1"
android:text="left" />
<TextView
android:id="#+id/tvBottom3"
android:layout_below="#id/tvBottom2"
android:layout_width="300dp"
android:layout_height="40dp"
android:gravity="center_horizontal"
android:background="#aacaff"
android:text="center_horizontal" />
<TextView
android:id="#+id/tvBottom4"
android:layout_below="#id/tvBottom3"
android:layout_width="100dp"
android:layout_height="40dp"
android:gravity="right"
android:background="#bcf5b1"
android:text="right" />
<TextView
android:id="#+id/tvBottom5"
android:layout_below="#id/tvBottom4"
android:layout_width="150dp"
android:layout_height="40dp"
android:gravity="center"
android:background="#aacaff"
android:text="center" />
</RelativeLayout>
</LinearLayout>
XML for image "Linear Layout with gravity":
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="center_horizontal"
android:background="#e3e2ad"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textSize="24sp"
android:text="View's gravity=" />
<TextView
android:layout_width="200dp"
android:layout_height="40dp"
android:background="#bcf5b1"
android:gravity="left"
android:text="left" />
<TextView
android:layout_width="300dp"
android:layout_height="40dp"
android:background="#aacaff"
android:gravity="center_horizontal"
android:text="center_horizontal" />
<TextView
android:layout_width="100dp"
android:layout_height="40dp"
android:background="#bcf5b1"
android:gravity="right"
android:text="right" />
<TextView
android:layout_width="150dp"
android:layout_height="40dp"
android:background="#aacaff"
android:gravity="center"
android:text="center" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="center"
android:background="#d6c6cd"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textSize="24sp"
android:text="View's gravity=" />
<TextView
android:layout_width="200dp"
android:layout_height="40dp"
android:background="#bcf5b1"
android:gravity="left"
android:text="left" />
<TextView
android:layout_width="300dp"
android:layout_height="40dp"
android:background="#aacaff"
android:gravity="center_horizontal"
android:text="center_horizontal" />
<TextView
android:layout_width="100dp"
android:layout_height="40dp"
android:background="#bcf5b1"
android:gravity="right"
android:text="right" />
<TextView
android:layout_width="150dp"
android:layout_height="40dp"
android:background="#aacaff"
android:gravity="center"
android:text="center" />
</LinearLayout>
</LinearLayout>
Testing your layout, for me it's working (the TextView is centered correctly).
However, you could also remove android:gravity="center_horizontal" from the RelativeLayout and add android:layout_centerHorizontal="true" in the TextView.
I've always had problems with RelativeLayouts and TextViews too. I think that this is due to the fact that TextView calculates its size dynamically and this prevents it to work well with layout's gravity. That's just one my supposition.
The solution I generally adopt is to configure a textview horizontal size with match_parent. It might be a suboptimal solution, but should work. In case you need a Fixed size textView you can put a fixed size dimension and should work too, it gives problems only with wrap_content.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:gravity="center_horizontal"
tools:context="com.something">
<TextView
android:id="#+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="#style/TextAppearance.AppCompat.Title"
android:textAlignment="center"
android:text="#string/app_title"
android:layout_marginBottom="#dimen/main_spacing"
android:textSize="24sp" />
</RelativeLayout>
Edit:
as suggested by #Valentino S., adding
android:layout_centerHorizontal="true"
with wrap_content should work too. The reason is in my head still the same: size of textView is calculated later.
As the documentation says:
android:gravity
Specifies how an object should position its content, on both the X and
Y axes, within its own bounds.
...
center_horizontal
Place object in the horizontal center of its container, not changing
its size.
So the android:gravity="center_horizontal" will center horizontal-ing the RelativeLayout to its parent. Not making its content center horizontal.
Remember that android:layout_gravity is used for the view itself relative to the parent or layout.
Please be aware that the behaviour of Layout can differ slightly for each API Level. And be noted, that we can't 100% sure that the visual result in Layout Editor is correct. Always test your layout in real devices.
try this:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:background="#000000"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin">
<TextView
android:id="#+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginBottom="10dp"
android:background="#ffffffff"
android:text="TITLE"
android:textAlignment="center"
android:textAppearance="#style/TextAppearance.AppCompat.Title"
android:textSize="24sp" />
<AutoCompleteTextView
android:id="#+id/enterContact"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/title"
android:layout_marginBottom="10dp"
android:background="#ffffffff"
android:text="Enter Contact"
android:textAlignment="center" />
</RelativeLayout>
TlDr: android:gravity Works with RelativeLayout , you can skip to the bottom if you don't want to read the explanation
EDIT this is a giant wall of text, please bear with me
This is what I imagine you want to achieve:
<TextView
android:id="#+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="#style/TextAppearance.AppCompat.Title"
android:textAlignment="center"
android:text="#string/app_title"
android:layout_marginBottom="#dimen/main_spacing"
android:textSize="24sp"
android:layout_centerHorizontal="true"/> <!-- LAYOUT PARAMS WORK!!!-->
Why does this work, while android:gravity (apparently) doesn't?
if your goal is to put the TextView in the horizontal center of the Layout/Screen you have to let the RelativeLayout know!
this is achieved through something called LayoutParams - these are data structures defined by each View which are used by the View's parent (in this case the RelativeLayout)
so let's say your TextView has the following LayoutParams :
android:layout_centerHorizontal="true"
you will get something like this:
When the RelativeLayout is distributing its child views around the screen, along the way there is a callback method being run - onLayout(...) - which is part of a more complex method sequence that will determine the position of each child View inside the RelativeLayout, this is achieved in part by accessing the LayoutParams in each child View, in this case that line in your TextView
This is why we say LayoutParams are passed on to the parent like in the link you mentioned before
WARNING: Endless Confusion Source!
View positioning inside Layouts / ViewGroups is done through LayoutParams the onLayout calls
It so happens that some layouts like FrameLayout have a LayoutParam called android:layout_gravity which causes great confusion with the android:gravity property that each view can define, which is NOT the same and not even a LayoutParam
android:gravity is used by any View (like a TextView for example) to place its content inside.
Example: let's say that you change your TextView to be very high, and you want the text at the bottom of the TextView, instead of at the top
<TextView
android:id="#+id/title"
android:layout_width="wrap_content"
android:layout_height="95dp" <------------ very high!
android:textAppearance="#style/TextAppearance.AppCompat.Title"
android:textAlignment="center"
android:text="#string/app_title"
android:layout_marginBottom="#dimen/main_spacing"
android:textSize="24sp"
android:layout_centerHorizontal="true" <----- LayoutParams for RelativeLayout
/>
TextView is CENTERED in the RelativeLayout but text is at the TOP of the "box"
Let's use android:gravity to manage the text position INSIDE THE TextView
<TextView
android:id="#+id/title"
android:layout_width="wrap_content"
android:layout_height="95dp"
android:textAppearance="#style/TextAppearance.AppCompat.Title"
android:textAlignment="center"
android:text="#string/app_title"
android:layout_marginBottom="#dimen/main_spacing"
android:textSize="24sp"
android:layout_centerHorizontal="true"
android:gravity="bottom" <---**NOT LayoutParams**, NOT passed to RLayout
/>
Result: As expected only the inside of the View changed
TLDR
Now if you want to ignore everything above and still use android:gravity with RelativeLayout, RelativeLayout is also a Viewso it has the android:gravity property, but you have to remove other properties or LayoutParams which will override the behaviour defined by the android:gravity property look at android:gravity at work with RelativeLayout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:gravity="bottom"> <!-- NOT LAYOUT PARAMS -->
<TextView
android:id="#+id/title"
android:layout_width="wrap_content"
android:layout_height="95dp"
android:textAppearance="#style/TextAppearance.AppCompat.Title"
android:textAlignment="center"
android:text="#string/app_title"
android:layout_marginBottom="#dimen/main_spacing"
android:textSize="24sp"
android:layout_centerHorizontal="true"
/>
<AutoCompleteTextView
android:id="#+id/enterContact"
android:text="Enter Contact"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAlignment="center"
android:layout_below="#+id/title"
android:layout_marginBottom="#dimen/main_spacing" />
</RelativeLayout>

Achieve Layout Elegantly Without Many Nested Layouts

I am attempting to create this layout in AXML:
However I am unsure of the easiest way to create this and avoid many nested Layout's. I am thinking to have an outer LinearLayout (horiz) with 2 RelativeLayouts for each column (then add the widgets in there).
So like this:
But with this current layout its not positioning correctly:
Can you suggest the easiest way to achieve this layout (ie, not involving many nested layouts) and why my code below isn't displaying correctly?
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:minWidth="25px"
android:minHeight="25px"
android:background="#161615">
<!-- Listing Details Section -->
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<RelativeLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="0.5">
<Mvx.MvxImageView
android:id="#+id/listingIcon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
local:MvxBind="ImageUrl LlistingIcon"
android:layout_alignParentLeft="true" />
<TextView
android:id="#+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dp"
android:textSize="15dp"
android:text="First name Last name"
android:layout_toRightOf="#+id/listingIcon" />
<TextView
android:id="#+id/datePosted"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dp"
android:textSize="15dp"
android:text="2 days ago"
android:layout_toRightOf="#+id/listingIcon" />
</RelativeLayout>
<RelativeLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="0.5">
<TextView
android:id="#+id/likes"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dp"
android:textSize="15dp"
android:text="13 likes"
android:layout_alignParentLeft="true" />
<TextView
android:id="#+id/comments"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dp"
android:textSize="15dp"
android:text="4 comments"
android:layout_alignParentLeft="true" />
<Mvx.MvxImageView
android:id="#+id/moreInfo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
local:MvxBind="ImageUrl MoreInfoIcon"
android:layout_alignParentRight="true" />
</RelativeLayout>
</LinearLayout>
</RelativeLayout>
You should be able to accomplish this with the below layout (using a single RelativeLayout). You may need to adjust padding/margin to your needs to get exactly what you want. I haven't tested it but this should get you close.
<RelativeLayout
...>
<Mvx.MvxImageView
android:id="#+id/listingIcon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="use appropriate margin for your needs/>
<TextView
android:id="#+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dp"
android:textSize="15dp"
android:text="First name Last name"
android:layout_toRightOf="#+id/listingIcon" />
<TextView
android:id="#+id/datePosted"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dp"
android:textSize="15dp"
android:text="2 days ago"
android:layout_below="#+id/name" /> <!-- see this change -->
<Mvx.MvxImageView
android:id="#+id/moreInfo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
local:MvxBind="ImageUrl MoreInfoIcon"
android:layout_alignParentRight="true" />
<TextView
android:id="#+id/likes"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="5dp"
android:textSize="15dp"
android:text="13 likes"
android:layout_alignPToLeftOf="#id/moreInfo" /> <!-- changed -->
<TextView
android:id="#+id/comments"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dp"
android:textSize="15dp"
android:text="4 comments"
android:layout_toLeftOf="#id/moreInfo"
android:layout_below="#id/likes" />
</RelativeLayout>
You can actually achieve this with a single horizontal LinearLayout and three children.
Your first child would be a TextView with a compound drawable.
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:drawableLeft="#drawable/some_icon"
/>
The text can be either hardcoded or something you set dynamically, but you can use the power of Android's spans if you need different sections of the text to be styled differently. This way you avoid creating unnecessary TextViews.
Your second child would be another TextView, again with spans if you need to style content differently, and your third child an ImageButton.
This approach will require at most two layout passes to succeed. (One if you don't use weights. It may even still be one pass if you specify weight for only one child and give it a width of 0dp, but I can't quite remember).
A single relative layout could also give you what you want, but requires the definition of confusing constraints and requires two measure/layout passes.

Android - RelativeLayout with image and text, design problems

I have a relative layout with an image and two textviews (one for the news title and the other one for the date). I put a hardcoded value for the width of the textview with the title. If I use wrap content it overlaps the date.
Here's my xml code:
<?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="wrap_content"
android:orientation="horizontal"
android:padding="5dp" >
<LinearLayout
android:id="#+id/thumbnail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_marginRight="5dp"
android:padding="3dp" >
<ImageView
android:id="#+id/imgIcon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/internet"
android:contentDescription="News" />
</LinearLayout>
<TextView
android:id="#+id/txtTitle"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_alignTop="#+id/thumbnail"
android:layout_toRightOf="#+id/thumbnail"
android:text="Timberlake's fourth studio album The 20/20 Experience – 2 of 2 was released on September 30, 2013."
android:textSize="14sp" />
<TextView
android:id="#+id/txtDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignTop="#+id/txtTitle"
android:layout_marginRight="5dp"
android:gravity="right"
android:text="23.09.2013"
android:textColor="#C0C0C0"
android:textSize="10sp" />
</RelativeLayout>
For the screen size 4,7 it looks like this:
screen size 4,7
But for the screen size 5,1 it looks bad:
screen size 5,1
My goal is that I have the same look for each screen size.
The space between the title and the date should always be the same.
How can I achieve this?
You're already using a RelativeLayout, so surprisingly there is a quick fix for you here. Leave your TextView's width as match_parent, but what you want to do is sandwich it between the ImageView and the TextView you use for your date. Try doing the following (note that I have to switch the order of the TextViews in your layout to make this work).
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="5dp" >
<LinearLayout
android:id="#+id/thumbnail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_marginRight="5dp"
android:padding="3dp" >
<ImageView
android:id="#+id/imgIcon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="News" />
</LinearLayout>
<!-- Note: I switched txtDate and txtTitle in your layout file ONLY -->
<!-- This will NOT change their order in your actual view -->
<TextView
android:id="#+id/txtDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignTop="#+id/txtTitle"
android:layout_marginRight="5dp"
android:gravity="right"
android:text="23.09.2013"
android:textColor="#C0C0C0"
android:textSize="10sp" />
<!-- This is the important part, note the android:layout_toLeftOf -->
<!-- Also remember to change the width back to "wrap_content -->
<TextView
android:id="#+id/txtTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="#+id/thumbnail"
android:layout_toRightOf="#+id/thumbnail"
android:layout_toLeftOf="#id/txtDate"
android:text="Timberlake's fourth studio album The 20/20 Experience – 2 of 2 was released on September 30, 2013."
android:textSize="14sp" />
</RelativeLayout>
This should give you your desired view.
Hope this helps. Good luck and happy coding!

Android - having trouble properly sizing an xml layout used for a listview row

I'm trying to set up an xml layout to be used for a row in a ListView. The layout consists of a root LinearLayout with a child RelativeLayout containing two ImageViews (one anchored to the other's bottom/right corner) and a child vertical LinearLayout containing two TextViews. I want each row in the listview to have the same width and height, despite the size of the content in the subviews. I realize I cannot use wrap_content which will size the views based on their content, but I'm unclear on what I should use to accomplish a uniform width/height. I tried using fixed dp values, but that just made it even worse. I've attached two screenshots. The first one, from the iOS version, shows how it should look, while the second one shows how it looks on the Android version with the following layout. As a said, I know what's wrong (the wrap_content attributes), but how do I change it to size correctly? Thanks in advance!
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/campaign_thumbnail_container" >
<ImageView
android:id="#+id/campaign_thumbnail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<ImageView
android:id="#+id/campaign_mark_new"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="#id/campaign_thumbnail"
android:layout_alignRight="#id/campaign_thumbnail"
android:src="#drawable/new1" />
</RelativeLayout>
<LinearLayout
android:id="#+id/campaign_bg"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/word_bar"
android:orientation="vertical" >
<TextView
android:id="#+id/campaign_category"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Medium Text"
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="#+id/campaign_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="#+id/campaign_desc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Small Text"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:id="#+id/campaign_footer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Small Text"
android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>
EDIT - According to comments below:
One general thing: To size elements in a LinearLayout uniformly, you need to do two things:
Use a equal android:layout_weight for each element
Make the width or height (whatever has to be uniquely sized) ="0dip"
This is, because the weight factor is only used to fill the rest of the available space. First all elements are placed using their weight/height, then the still available space is calculated and distributed by weight to each element.
EDIT-end
Now, let me create the layouts step by step.
First, this would be your layout of one entry without the "new campaign" indication.
<!-- Type 1: Picture left, text right. half-half size. Picture resized to fit -->
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:orientation="horizontal" >
<ImageView
android:id="#+id/imageView1"
android:layout_width="0dip"
android:layout_height="fill_parent"
android:layout_weight="1"
android:scaleType="fitCenter"
android:src="#android:drawable/ic_menu_camera" />
<TextView
android:id="#+id/textView1"
android:layout_width="0dip"
android:layout_height="fill_parent"
android:layout_weight="1"
android:gravity="center"
android:text="Your Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
</LinearLayout>
You get a warning, because the LinearLayout itself has a weight. That is necessary, to give all list entries the same height.
Here's type 2:
<!-- Type 2: Picture right, text left. half-half size. Picture resized to fit -->
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:orientation="horizontal" >
<TextView
android:id="#+id/textView2"
android:layout_width="0dip"
android:layout_height="fill_parent"
android:layout_weight="1"
android:gravity="center"
android:text="Your Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<ImageView
android:id="#+id/imageView2"
android:layout_width="0dip"
android:layout_height="fill_parent"
android:layout_weight="1"
android:scaleType="fitCenter"
android:src="#android:drawable/ic_menu_camera" />
</LinearLayout>
(Where's my "That was easy!" button?)
And Type 3. Even easier:
<!-- Type 3: Picture full width. Picture resized to fit -->
<ImageView
android:id="#+id/imageView2"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:scaleType="fitCenter"
android:src="#android:drawable/ic_menu_camera" />
Now the final thing. Put these three layouts in separate XML-files and include them into a wrapping RelativeLayout.
<!-- Finally overlay the entry with a new indication -->
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1" >
<ImageView
android:id="#+id/newIndication"
android:layout_width="24dip"
android:layout_height="24dip"
android:layout_alignRight="#+id/entry1"
android:layout_alignBottom="#+id/entry1"
android:scaleType="fitCenter"
android:src="#android:drawable/ic_input_add" />
<include
layout="#layout/type1entry"
android:id="#+id/entry1"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</RelativeLayout>
Note the include. I've put the Type1 LinearLayout in its own XML file named "type1entry". By giving this a new id with #+id/entry1 I can access this entry explicitely in the Activity. Also, I've given the indicator a size of 24dip in square. Change that to your image accordingly.
I've checked the layouts in Eclipse and they did look as I expected them.
Do you need to use a relative layout?
If not, use linearLayout with weights like this.
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:id="#+id/campaign_thumbnail_container"
android:weightSum="100" >
<ImageView
android:id="#+id/campaign_thumbnail"
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="50"
android:scaleType="fitCenter"
/>
<ImageView
android:id="#+id/campaign_mark_new"
android:layout_width="0dip"
android:layout_height="match_parent"
android:src="#drawable/new1"
android:layout_weight=50
android:scaleType="fitCenter" />
</LinearLayout>
This is untested, but similar solutions like this have worked for me in the past.

Adding ScrollView to RelativeLayout changes position of wigdets

The following is the XML of my layout. It explicitly states that the title, time and description TextViews should be under the image of the alarm. However, as the screen shot shows, the TextViews have moved into the ImageView. Why does this happen and how can I fix this? The problem only started happening when I added the scrollview.
XML
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ImageView
android:id="#+id/img_alarm"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/alarm"
android:layout_centerInParent="true"
android:contentDescription="#string/content_description_layout_alarm"/>
<TextView
android:id="#+id/lbl_alarm_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20dip"
android:textStyle="bold"
android:layout_centerHorizontal="true"
android:layout_below="#+id/img_alarm"
android:layout_alignLeft="#+id/img_alarm"
android:text="#string/empty"
/>
<TextView
android:id="#+id/lbl_alarm_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20dip"
android:textStyle="bold"
android:layout_centerHorizontal="true"
android:layout_below="#+id/img_alarm"
android:layout_alignRight="#+id/img_alarm"
android:text="#string/empty"
/>
<TextView
android:id="#+id/lbl_alarm_description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_below="#+id/lbl_alarm_title"
android:layout_alignLeft="#+id/lbl_alarm_title"
android:layout_alignRight="#+id/lbl_alarm_time"
android:maxLines="1"
android:ellipsize="marquee"
android:text="#string/empty"
/>
<Button
android:id="#+id/btn_stop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/lbl_alarm_description"
android:layout_centerHorizontal="true"
android:layout_marginTop="5dip"
android:paddingLeft="20dip"
android:paddingRight="20dip"
android:text="#string/stop_layout_alarm"
android:gravity="center" />
</RelativeLayout>
</ScrollView>
Image
Cute app :)
hmm... not sure why it's doing it, looks like you have the right code, without busting out eclipse. but i've also had some weird bugs with relativelayout that i didn't understand and didn't have time to debug.
i do know of an alternative way you can accomplish what you're looking for -
have a scrollview that encases a linearlayout instead of a relative layout. Do these things:
For the linearlayout, you can set orientation = vertical so that it's still a top down order.
For the part where you need two textviews where one is aligned to the right and the other is aligned to the right, you need another inner linearlayout with its orientation=horizontal. then have one element align parent left, and the other align parent right. add a weightSum=1 attribute to this linearlayout and have each of the two textviews layout_width=0.5 so that each is half the width of the screen
Apply a weightSum=1 attribute to your outer most linearlayout, and see each element inside so that it's layout_weight sum adds up to 1. layout_weight will allow an element to take up that much % of real estate on the screen. like if you set your imageView to have android:layout_weight=0.8 then it'll take up 80% of the screen... since mathematically, (layout_weight/weightSum) = (.08/1) = 80%
try to use that mechanism instead, and if should work :) if it's confusing i can give code
example
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:weightSum="1">
<ImageView
android:id="#+id/img_alarm"
android:layout_width="match_parent"
android:layout_height="0dip"
android:src="#drawable/alarm"
android:layout_weight="0.7"
android:contentDescription="#string/content_description_layout_alarm"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.1">
<TextView
android:id="#+id/lbl_alarm_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textSize="20dip"
android:textStyle="bold"
android:text="#string/empty"
/>
<TextView
android:id="#+id/lbl_alarm_time"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textSize="20dip"
android:textStyle="bold"
android:text="#string/empty"
/>
</LinearLayout>
<TextView
android:id="#+id/lbl_alarm_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="0.1"
android:maxLines="1"
android:ellipsize="marquee"
android:text="#string/empty"
/>
<Button
android:id="#+id/btn_stop"
android:layout_weight="0.1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="5dip"
android:paddingLeft="20dip"
android:paddingRight="20dip"
android:text="#string/stop_layout_alarm"
android:gravity="center" />
</LinearLayout>
</ScrollView>
i hope this deserves at least an upvote for the effort :D

Categories

Resources