Why does my relative layout occupy full screen width
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#f00"
>
<Button
android:id="#+id/Button01"
android:text="Press Here"
android:layout_alignParentRight="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"></Button>
<Button
android:id="#+id/Button02"
android:text="02"
android:layout_alignParentLeft="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"></Button>
</RelativeLayout>
I have specified the relative layout to "wrap_content", then why does it occupy full screen space. Out put is same even if i say android:layout_width="fill_parent".
Enlighten me please!
EDIT : I think i was not very clear with my question earlier. Apologies for that.
When I have 2 child views in a relative layout and one of them is left aligned to parent and other is right aligned and relative layouts width is WRAP_CONTENT then I expected the layouts width to be just the sum of width of 2 buttons (isn't that's what WRAP_CONTENT means??). I know there are other ways of achieving the UI im looking for but Im just trying to understand these relative layout tags properly.
EDIT 2: I have experimented a bit and it looks like if we using Layout_AlighParentRight with its parent's width as WRAP_CONTENT then the upper layout width is used for calculation (like few answers pointed out below). But we are using just the Layout_alignParentLeft then it works as expected and layout width is not extending to the complete screen. Thanks for the help folks!
The other answers have correctly pointed out that when your relative layout's width is set to wrap_content, and its children are aligned to both left and right, the relative layout takes the width of its parent - in this case, the entire screen. If, however, both children were aligned to one side, the relative layout would be as wide as the widest child.
Now if you want the two buttons to be placed next to each other, and the relative layout to be as wide as the sum of the widths of the buttons, a slightly different approach is needed. Instead of positioning both buttons relative to the parent, do that with one button only (e.g, the first one). Let's say its positioning is left unchanged (android:layout_alignParentRight="true"). Now the button is floated to the right, so the second button, in order to be position next to it, has to be aligned to the first button's left side. Thus, we just add android:layout_toLeftOf="#id/Button01" (and remove the android:layout_alignParentLeft="true" part).
For more, I suggest you check out a very friendly tutorial on relative layouts.
cause you have a
android:layout_alignParentLeft="true"
width an object , and a
android:layout_alignParentRight="true"
width another object , then the layout extends to both side , giving you the full width layout.
But when you use Layout_alignParentXXXXX , and you put in parent WRAP_CONTENT , that makes children to go to the upper layout with a width defined.
This line makes the "Press Here" button (Button01) align to the right:
android:layout_alignParentRight="true"
That makes your layout fill the parent in width.
Another issue you may face is that if you set your 2 children to "align parent right"+"wrap_content", and your relative layout to "wrap_content", and that relative layout is contained in a full screen LinearLayout your relative layout will occupy the whole LinearLayout width.
If you do that with both "align parent left", the relative layout sticks on the left, and its width is really a "wrap content". But the behaviour is different for "align parent right", that's a bit strange.
Workaround:
To solve that issue (I had to align one of the children to the right), I actually set the 2 children to "align parent left" and played with children padding in order to get one of the children positionned on the top right corner. This is a dirty workaround but the only one i've found for now.
Possible cleaner solutions:
Another trick would be to put 2 LinearLayout inside a FrameLayout, then put your real children in each LinearLayout, and play with the gravity of those LinearLayout to position children at the right position.
RelativeLayout
LinearLayout
Child 1 (wrap_content)
LinearLayout (gravity: top right)
Child 2 (wrap_content)
Related
I am trying to align two layouts horizontally but can't seem to get it working. The conditions I need are:
Layout 1 needs to fill up the whole width EXCEPT for the width that layout 2 requires
Layout 2 needs to have a width of 21dp and right / left margin of 17dp.
I can't take a picture because of my job, but here' some ascii art to illustrate what I want:
I attempted using a dummy View between the two layouts so that I could use a relative layout, but that wasn't quite working for me..so any suggestions?
Thanks!
<RelativeLayout layout_width="match_parent">
<Layout1 layout_width="match_parent" layout_toLeftOf="#+id/layout2"/>
<Layout2 id="#id/layout2" layout_width=21dp layout_alignParentRight="true" layout_marginLeft="17dp" layout_marginRight=17dp/>
</RelativeLayout>
Add in the rest of the parameters as needed
Try using a horizontal LinearLayout and set android:layout_weight="1" for layout 2. Like this layout 2 should keep it's size and layout 1 will fill the rest of the available space.
I have the following requirement in Android:
Given a horizontal LinearLayout, I have five buttons in it. All the buttons should have equal width and height. The height of each button is same as their parent LinearLayout and spacing between them should remain constant. The height of LinearLayout is not constant and depends on form factor and other layouts sizing. Therefore, I can not assign fixed with/height to each button.
While I can easily achieve that very easily in iOS with the help of constraints, I am not sure how to achieve this in Android at design time. Is there some way to achieve this or is it possible programatically only?
The height of each button is same as their parent LinearLayout
Set the height to match_parent
For your width, you'll have to calculate the screen size programmatically and set the widths accordingly. See this question.
Try this . As you have a horizontal LinearLayout with 5 buttons, for equal spacing of all buttons, you must first allocate the space to each button of of the total space available like this..
<LinearLayout
android:weightSum="5"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="allocate it programatically"
/>
This button shown above has to be for all 5 buttons u have. The idea allocating weight sum of 5 to LinearLayout and then dividing it as 1 to each button. Note the width here for the button should be 0dp.
Then dynamically change your button Height and Width per your requirement
Unfortunately no typical layout in Android seems to have the concept of this kind of layout constraint (square like elements).
It's the layout that ultimately determines the sizes of their children. Therefore if you want that you have to write your own layout implementing this constraint.
For this extend ViewGroup and in onLayout enforce that width of the children or a specific children equals height. You could even invent your own LayoutParams for this task. See the documentation of ViewGroupfor a general example. The exact implementation very much depends on which other requirements you have for your layout.
I have a linear layout in which I have 3 views.
View1-Weight=1
View2-Weight=10
View3-Weight=1
Total weight is 12.
Now all elements have android:layout_width="match_parent". Which means that the screen is divided in proportion of their heights.
What I want to do is that I want to nest 3 ImageViews in View2 so that each image view fully occupies the available screen area to View2. And on scrolling, I must see the second image view and third image views respectively. Each must be continuous and sizes(of ImageViews) must become equal. If all were to be on a single page, I would have done it by setting their weights.But now since they are on different pages, I dont have an idea how to do it. I dont want to take absolute sizes as it may look ugly on different devices.
How is it possible and what should be used in View2-a ListView or a Scrollview? Is it possible via the xml file(my preferred solution).
Ok So here is the basic idea :
You cannot use a ScrollView or a ListView or a GridView here perfectly as you have not specified the width and height in a fixed manner by applying dp and dip. So the only thing will work here is a ViewPager(A modified version) It will scroll vertically. So heres how to do this.
You have 3 Views in the layout.
<View
android:id="v1"
android:weight="1.0"
....
/>
<View
android:id="v1"
android:weight="10.0"
....
>
<ViewPager
//so you must specify the width and height here as fill parent
android:width="fill_parent"
android:height="Fill_parent"
/>
</View>
<View
android:id="v1"
android:weight="1.0"
....
/>
Just use this view pager and you must specify your fragment imageview by supplying it the property of fitXY, it will force fix your one ImageView to be visible in the entire view 2 at a time then you can scrol vertically to access other two.
I've noticed a strange behavior in RelativeLayout when you align a view to the layout's side
(any side) and having a large margin in the same direction.
I have 2 RelativeLayouts that each contains a simple view. In one layout that view is align to the top and left, in the other to the bottom and right:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<RelativeLayout
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_marginTop="110dp"
android:layout_gravity="center"
android:background="#ff555555" >
<View
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:background="#aa8711" />
</RelativeLayout>
<RelativeLayout
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_marginBottom="110dp"
android:layout_gravity="center"
android:background="#ff555555" >
<View
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:background="#998877" />
</RelativeLayout>
</FrameLayout>
It looks like this:
I added 130dp of margin in each direction of parent alignment. That means that the view should be only partially visible in the layout. This is what happens:
As you can see, the views are now smaller than the original size, as the get pushed on the "walls" of the layout. Next I tried to give a margin that is bigger than the layout, so I gave them 151dp of margin in the aligned directions. It looked like this:
The bottom-right aligned view now "breaks out" of the layout and is again the same size as it was originally. On the other hand, the top-left aligned view is too in its original size, but completely inside the layout instead of outside of it.
I've tried this individually and in every permutation of alignment and got the same results.
Question one: Can anyone explain this inconsistent behavior?
I tried the same thing, this time comparing the behavior to that of a FrameLayout.
Initial setup:
and after margins:
The FrameLayout keeps the view in its original size at all time and simply lets the view "exit" it. I tried to give a negative margin in the opposite direction of at least the size of the view that should be outside of the RelativeLayout and saw the same behavior as happens in the FrameLayout by default.
Question 2: Can anyone explain the difference in behavior and the opposite negative margin effect?
Why should it be only partially visible?
I added 130dp of margin in each direction of parent alignment. That
means that the view should be only partially visible in the layout
The box is getting smaller because preference is given to keeping it inside the parent layout at all costs, while still applying the margin. Since the smaller child view is 50dp, you have added a margin of 130dp, the total width it needs is 180dp but the parent view itself is only 150dp wide. That is 130dp + 50dp > 150dp - the child plus the margin cannot fit inside the parent.
This is "silly input" and the XML interpreter is doing its best to render something. The decision that it makes in the end is that it can alter the width of the child box and still respect the margin constraint. Or mathematically
130dp + 20dp == 150dp
Basically it shrinks the width of the inner box down from the assigned 50dp to 20dp so that it can fit inside the parent with its added margin. And if you look at the size of the square 20dp looks about right. It is 60% smaller.
This is clever behaviour by the interpreter because as screen sizes change and it runs into issues like this it should always preserve the margin constraint opposed to the width constraint.
In summary the interpreter is doing its best to fit the box, and its margin inside its parent, to do so it is making the box smaller. It is choosing to preserve the given margin, over the given width - probably because of the top-most parent layout.
When you say "this should be partially visible" I assume you think the child will render half inside the parent bounds, and half outside the parent bounds, similar to windows form development. This is not the case though because it will always try to keep children inside the bounds of parents in most layouts.
The choices that are made depend on the top-most parent layout too, some layouts may prefer to preserve the width of the child box rather than the margin, or even render the box outside of the parent's bounds.
In the second case:
so I gave them 151dp of margin in the aligned directions.
You are going beyond the point in which the interpreter can shrink the image. It cannot shrink the image to negative 1. That is
50dp + 151dp > 150dp
It can't meet this margin constraint you have given it so the behaviour is fairly unpredictable. At a guess I would say it knows it cannot keep both the images, along with their margins inside the parent. So it simply renders one inside and one outside.
Once again, this is silly input and the interpreter is doing its best to render what you want.
Can anyone explain the difference in behavior and the opposite negative margin effect?
A negative margin will do different things depending on the type of layout in its parent, and that it is aligned too. In a frame layout it will behave differently to a relative layout. Usually if you are looking at negative layouts you have chosen the wrong parent containers and you are trying to hack it to get it to look right.
I don't know what you are trying to do exactly but maybe you just need tweak your thought process a little and think of the poor interpreting trying to understand the XML you give it.
You wouldn't be the first person to be utterly confused by android's XML layouts. Nesting layouts inside layouts is always confusing and the behaviour changes depending on a number of things like margins, alignments, widths, etc. Most people I know simply muck around with it until it is right and try different container layout types to get the right design.
In short, avoid playing with margins (like flash or winforms) and play without layout types instead to get things where you want them.
hope that helps, sorry for tl;dr.
I have a vertical, set height (300px) LinearLayout (LL) with 3 nested LLs. 1 and 3rd are set with android:layout_height="wrap_content" and the middle one with android:layout_height="fill_parent". To my dismay, 3rd LL gets pushed out with 2nd one filling parent layout right to the bottom. How do I achieve desired effect since I want potentially resize the outside container with the middle portion expanding and contracting to accommodate the change
Turned out (Thanks Mark Murphy for the answer) that all I was looking for was to set middle row to
layout_height="0px" and layout_weight="1"
If, after all the wrap_content and fixed-sized items are allocated for
along an axis (horizontal or vertical), there is still room on that axis
left over, LinearLayout then allocates the remaining space to those
widgets with specified weights, in proportion to the weight.