Android View to fill center area of Layout - android

I have this layout:
All views fill the entire space horizontally, and they're inside a LinearLayout oriented vertically. The blue parts have a fixed height (they have the wrap_content property).
The red part is a ListView. How can I make it fill that center space if there are not enough elements in the list and at the same time preventing it to push the last two elements down if it has more elements?
So far it doesn't push down the two views under it (with the layout_weight="1" property), but if it doesn't have enough elements, it shrinks and makes those two elements go up, leaving an ugly white space under them.
This is what happens:
This is what I expect:
Notice that even though the ListView is smaller, the two last views don't go up.
So far I've tried:
Giving all views a weight (ugly display but sort of works).
Giving each view a size (different results on different devices).
Giving the last view the android:gravity="bottom" property, but the view still goes up.
What may work
I've been messing around and I think a RelativeLayout may work, with a property like layout_alignBottom that instead of aligning to the end of the given view, it aligned to the start of it.
SOLUTION
The solution was to use a RelativeLayout and set the list's layout_above and layout_below properties to that of the elements I want to align it to.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.stackoverflow.app.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hello_world" />
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minHeight="48dp"
android:text="#string/hello_world" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minHeight="48dp"
android:text="#string/hello_world" />
</LinearLayout>

Here's a couple of options that may work for you. Let me know how it goes.
Option 1:
Set the containing vertical orientated linear layout to fill_parent / match_parent (they are the same). Then set the gravity or layout gravity of the bottom 2 views to bottom.
Option 2:
Contain the list view in a linear layout with a fixed height. Set the list view to wrap_content.
EDIT
You could use relative layouts for this, this link here seems to do what you need
http://www.javacodegeeks.com/2013/10/android-fixed-header-and-footer-with-scrollable-content-layout-example.html

How about wrapping your list view inside the a layout and give the layout the fixed height.
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="300dp" >
<ListView
android:id="#+id/listView1"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</RelativeLayout>

Related

Why does the orientation of a linearlayout determine the centering of a child element?

Why doesn't this center a button both horizontally and vertically on the screen?
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:background="#FFFFFFFF">
<Button android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#color/red"
android:textColor="#color/white"
android:text="click"
android:layout_gravity="center"/>
</LinearLayout>
layout_gravity specifies alignment for the button within it's parent. But this only centers the button vertically, not horizontally. If I change the orientation of the linearlayout to vertical, the button is centered horizontally, not vertically. I don't see why the orientation matters here because I only have 1 child element.
I know I can achieve this by specifying the gravity in the LinearLayout with android:gravity="true" or using a RelativeLayout and have the Button android:centerInParent="true", but I'd like to know how android came up with the layout in the code above.
P.S. Why does the background color still show as gray if that's the hex code for white?
LinearLayout will only allocate the minimum amount of space needed for a view in the direction of its orientation. That's why you can't seem to center a view in the same direction as the orientation. LinearLayout generally assumes that you want to put multiple things adjacent to each other, not occupy an entire space unconditionally for a single item.
P.S. I see the entire background of the LinearLayout as white in my preview view in Android Studio, so I don't know what you mean in your P.S.
Don't use a linear layout to display items in the middle of the screen, as these are meant to list items in a row. Use a relative layout instead. So your code should look like this:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:background="#FFFFFF">
<Button android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#color/red"
android:textColor="#color/white"
android:text="click"
android:layout_centerInParent="true"/>
</RelativeLayout>

ListView not getting space to show content on smaller screens

So I am developing a screen where there are some images and buttons on top and Below that is a list view which shows a list of some activity.
The design is something like this :-
Now on smaller screen the ListView height becomes very small as the screen space is taken up by the above icons and images.
So how can i increase the height of the Linearlayout or ListView so that user can scroll to the see the rest of the ListView.
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
.... Other Layouts .....
<ListView
android:id="#+id/listArea"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:paddingLeft="#dimen/list_padding"
android:paddingRight="#dimen/list_padding" />
</LinearLayout>
Edit: Tried using the top view as a header to the List but since I want an EmptyView too, this is creating a problem as it replaces the whole header + listview
From what I read about that issue, you should specify the Views on top as header of the list, and the'll scroll properly.
Afaik this only works if the list is non-empty, as the empty view replaces the whole list including headers.
You can use the weightSum and layout_weight attributes to control how much of the parent's available space a child view will take up. To use these, a parent layout, for example, your LinearLayout, gets the android:weightSum attribute. Each child layout gets the android:layout_weight attribute, where the sum of all child weights is the weightSum of the parent. In addition, each child should have their layout_height or layout_width set to 0dp, whichever is going to be decided by the weight.
Here's an example based on your diagram. Let's say you want the two top views to take up 1/4 of the screen each, and the ListView to take up the bottom half. Add android:weightSum="4" to your LinearLayout, android:layout_weight="1" to the two child layouts that you represent with ...Other Layouts..., and android:layout_weight="2" to the ListView. Code might look something like this:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:weightSum="4">
<ImageView
android:layout_weight="1"
android:layout_height="0dp"
...some other attributes.../>
<LinearLayout
android:layout_weight="1"
android:layout_height="0dp"
android:orientation="horizontal"
...some other attributes...>
...some children of the LinearLayout...
</LinearLayout>
<ListView
android:id="#+id/listArea"
android:layout_width="match_parent"
android:layout_height="0dp"
android:paddingLeft="#dimen/list_padding"
android:paddingRight="#dimen/list_padding"
android:layout_weight="2"/>
</LinearLayout>

Left aligning images in LinearLayout using gravity or linear_gravity in XML

First off, this is not a duplicate question, to best of my ability I've tried all (there are many) similar questions. Solutions to such problems appear to be very subjective, specific to a given scenario.
My layout currently appears as follows. Black boxes are images (logo and body, respectively), colours represent each layout:
My XML:
<?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:background="#000"
android:padding="0px"
android:layout_margin="0px"
android:orientation="vertical">
<LinearLayout
android:layout_weight="16"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FFF"
android:gravity="top|center"
android:orientation="horizontal">
<ImageView
android:id="#+id/logo"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/logo"
android:layout_gravity="top|center" />
</LinearLayout>
<LinearLayout
android:layout_weight="4"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#00F"
android:gravity="bottom|left"
android:orientation="vertical">
<ImageView
android:id="#+id/body"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/body"
android:layout_gravity="bottom|left" />
</LinearLayout>
</LinearLayout>
Here you can see I have a parent linear layout, split into two children linear layouts. This is because I need the images to be positioned differently within that part of the page.
In a nutshell, I need logo to be vertically aligned to the top, and body horizontally aligned to bottom-left.
Now, a few things that I've tried:
Using RelativeLayout rather than Linear
Switching gravity with layout_gravity for both LinearLayout and ImageView, along with combinations of excluding each
Fairly confident match_parent for width and height is what I want, but I have tried different combinations with wrap_content
What I've come to understand:
gravity:top requires the parent view use orientation:horizontal
gravity:left requires the parent view use orientation:vertical
gravity applies to the children of the view
linear_gravity applies how the child aligns with it's parent
Using the same value for gravity on the parent and linear_gravity on the child might have the same effect (when using one instead of the other)?
Hopefully this is enough information. I'm having a very difficult time wrapping my head around how these layouts work.
Thank you SO much for the help!
I think your problem is you are setting dimensions of the image views to match_parent. I would use a RelativeLayout as it seems to be the most efficient in your case (pseudo-XML-code):
RelativeLayout (width=match_parent, height=match_parent)
ImageView (width=wrap_content, height=wrap_content,
alignParentTop=true, centerHorizontal=true)
ImageView (width=wrap_content, height=wrap_content,
alignParentBottom=true, alignParentLeft=true)
You don't need any gravity setting here. You might want to play with the scaleType attribute depending on your image sizes.

Collapsing margins in Android layouts

Is it possible to make margins collapse in Android? Let's say I have a LinearLayout and add three TextViews, each with an android:layout_margin of 10dp. I get the following result:
However, I'd like to get this result:
I know that I could workaround this by setting different top/bottom margins for the different items:
set the top margin of the first item and the bottom margin of the last item to 10dp,
set the remainding top/bottom margins to 5dp,
but that makes the design more complicated (especially if the TextViews are dynamically created). Is there some way to make the margins behave like in CSS? (For an explanation of why this makes sense, see: What is the point of CSS collapsing margins?)
What I typically do to fix this myself, is to simply cut the View's (i.e. your TextView) margin in half, and add that same number as padding to the containing ViewGroup (i.e. your LinearLayout). This way you will end up with even spacing around all items. For example:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="5dip"
>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dip"
android:text="I'm a TextView!"
/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dip"
android:text="I'm a TextView!"
/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dip"
android:text="I'm a TextView!"
/>
</LinearLayout>
Posting a solution for someone who might need this in future. Works for static as well as AdapterViews where list items are dynamic.
Example parent container:
<RecyclerView
----
android:padding_top="10dp"
android:padding_start="10dp"
android:padding_end="10dp"
----
>
</RecyclerView>
The padding ensures the spacing from top, left & right of the window.
Only thing remaining now is the vertical gap between two consecutive children & bottom gap after last child.
Example child / item view:
<RelativeLayout
----
android:margin_bottom="10dp"
----
>
<DynamicChild1 />
<DynamicChild2 />
</RelativeLayout>
For this question specifically, the child view will just be a TextView with bottom margin.
This will give you the exact output as expected in the question.

Positioning ListViews inside FrameLayout

So I'm trying to create a screen which has a ListView and over that I need to be able to float another custom horizontal ListView, right at the bottom edge of the screen. When the user scrolls on the vertical listview, the horizontal one would go invisible and reappear when the scrolling stops. I figured FrameLayout would be my best bet for overlapping views. But I can't seem to make this work. The Horizontal listview seems to occupy the whole screen space. Any ideas? Is this even the right approach? I wish to have something similar to a fixed div in HTML.
Here's my XML:
UPDATE-1: Used RelativeLayout as suggested, but still a no-go. The HorizontalListView still seems to be occupying the whole screen. I'm using the HorizintalListView from here
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<ListView
android:id="#+id/messages"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginTop="5dip" />
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true" >
<test.ui.app.HorizontalListView
android:id="#+id/folders"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#FFFFFF" />
</RelativeLayout>
</RelativeLayout>
I got it to work by setting the height of the inner Relative Layout myself instead of using 'wrap_content'.
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<ListView
android:id="#+id/messages"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="80dip"
android:layout_alignParentBottom="true" >
<test.ui.app.HorizontalListView
android:id="#+id/folders"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#FFFFFF" />
</RelativeLayout>
</RelativeLayout>
You cannot adjust the views inaide FrameLayout.So it will be better for you to go for RelativeLayout.
Or you can put your listviews inside RelativeLayout or linearlayout and then you can adjust.
Hope this will help you. :)
Like the other answerer said, you could use a RelativeLayout:
set android:layout_alignParentLeft|Right|Top|Bottom="true" for the vertical list view
set android:layout_alignParentLeft|Right|Bottom="true" for the horizontal list view (and height to "wrap_content" or fixed size)
Or if you reeeeaaaally want to stick with FrameLayout (maybe for performance reasons...), you could somply add a huge android:layout_marginTop to the horizontal list view. But this solution is uglier, since you need to set exact values. For example if the whole screen is 320dp height, and you want the horizontal list view to be 80dp height, you need to set the top margin to 240dp. However if you run this on a screen with different aspect ratio, the horizontal list view will be ugly.

Categories

Resources