I'm trying to layout some images using GridLayout, in uneven sizes (I'm trying to implement StaggeredGrid
), but when I'm placing the first image in the first cell it stretches all over the screen.
How do I prevent it from doing this ?
<?xml version="1.0" encoding="UTF-8"?>
<GridLayout 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:columnCount="4"
android:rowCount="4"
tools:context=".MainActivity" >
<ImageView
android:layout_columnSpan="1"
android:layout_rowSpan="2"
android:src="#drawable/pic1" />
<ImageView
android:layout_columnSpan="2"
android:layout_rowSpan="1"
android:src="#drawable/pic2" />
</GridLayout>
Thanks,
Shmulik
Please use layout_column and layout_row to specify in which row and in which column of that row you want to place your ImageView.
<?xml version="1.0" encoding="UTF-8"?>
<GridLayout 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:columnCount="4"
android:rowCount="4"
tools:context=".MainActivity" >
<ImageView
android:layout_column="1"
android:layout_row="0"
android:src="#drawable/pic1" />
<ImageView
android:layout_column="2"
android:layout_row="0"
android:src="#drawable/pic2" />
</GridLayout>
Also reading the doc I found that we can have control over the stretch using Gravity. It says,
Excess Space Distribution:
GridLayout's distribution of excess space is based on priority rather than weight. A child's ability to stretch is inferred from the alignment properties of its row and column groups (which are typically set by setting the gravity property of the child's layout parameters). If alignment was defined along a given axis then the component is taken as flexible in that direction. If no alignment was set, the component is instead assumed to be inflexible.
Multiple components in the same row or column group are considered to act in parallel. Such a group is flexible only if all of the components within it are flexible. Row and column groups that sit either side of a common boundary are instead considered to act in series. The composite group made of these two elements is flexible if one of its elements is flexible.
To make a column stretch, make sure all of the components inside it define a gravity. To prevent a column from stretching, ensure that one of the components in the column does not define a gravity.
AND
To place equal amounts of space around a component in a cell group; use CENTER alignment (or gravity). For complete control over excess space distribution in a row or column; use a LinearLayout subview to hold the components in the associated cell group. When using either of these techniques, bear in mind that cell groups may be defined to overlap.
Related
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>
I am trying to rework one of my layouts using GridLayout and a bit stuck with one of the problems. Here is what I have now:
And this is my layout:
<GridLayout
style="#style/Widget.Card"
android:layout_width="match_parent"
android:layout_height="#dimen/card_height"
android:background="#color/news_card_background"
android:clipChildren="false"
android:clipToPadding="false"
android:columnCount="3"
android:rowCount="2" >
<ImageView
android:id="#+id/thumbnail"
android:layout_width="#dimen/card_thumbnail_width"
android:layout_height="match_parent"
android:layout_rowSpan="2"
android:background="#drawable/news_card_thumbnail_background"
android:contentDescription="#string/thumbnail"
android:cropToPadding="true"
android:scaleType="centerCrop"
android:visibility="visible" />
<com.inrix.twc.view.RobotoTextView
android:id="#+id/title"
style="#style/TextAppearenceNewsTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="#dimen/news_title_horizontal_margin"
android:layout_marginRight="#dimen/news_title_horizontal_margin"
android:text="Title" />
<ImageView
android:id="#+id/icon"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="right"
android:layout_rowSpan="2"
android:src="#drawable/audio_mrss"
tools:ignore="ContentDescription" />
<com.inrix.twc.view.RobotoTextView
android:id="#+id/footer"
style="#style/TextAppearenceNewsFooter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_marginLeft="#dimen/news_description_horizontal_margin"
android:layout_marginRight="#dimen/news_description_horizontal_margin"
android:text="description" />
</GridLayout>
But when one of the text views goes very long, it pushes my last column out of the screen:
The question is - how do I restrict my text to go beyond row's bounds, so my icon always stays right-aligned. So basically I'm trying to mimic RelativeLayout's toLeftOf attribute.
I realize I can easily do that with RelativeLayout, but it doesn't quite work for me because of other reasons. I hope it is possible to do with GridLayout
Thats not the target of gridlayout. I don't think that is even (easily) possible. Blockqoute from GridLayout limitations.
GridLayout does not provide support for the principle of weight, as defined in weight. In general, it is not therefore possible to configure a GridLayout to distribute excess space between multiple components.
Some common use-cases may nevertheless be accommodated as follows. To place equal amounts of space around a component in a cell group; use CENTER alignment (or gravity). For complete control over excess space distribution in a row or column; use a LinearLayout subview to hold the components in the associated cell group. When using either of these techniques, bear in mind that cell groups may be defined to overlap.
TextView needs weight to define his own size on the screen (using wrap content).
You can try to use relative layout or build a tree of linearlayout like this:
LinearLayout horizontal
ImageView #thumbnail
LinearLayout vertical weight 1
TextView #title
TextView #footer
ImageView #icon
I have a ListView in which each row is a GridLayout with two rows. I want each list item to be at least 48dp high (recommended minimum size for press targets) because each can be pressed, and I want the GridLayout to be vertically centered in the row if it doesn't expand it.
To do this, I've put the GridLayout inside a FrameLayout, set the FrameLayout to a minimum height of 48dp, and set the layout_gravity of the GridLayout to center. If I don't use the FrameLayout and just set the minimum height of the GridLayout, then I can't get the whole thing nicely vertically centered because of GridLayout's bogus space distribution.
So, using the FrameLayout gives me the desired outcome, but generates a Lint warning in my XML file, "This GridLayout layout or its FrameLayout parent is useless." Obviously it's not useless since it lines stuff up right, but is there a better way to do it that I missed?
Here is my XML (I cut out a bunch of TextViews in the GridLayout because they're not relevant to this situation):
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:minHeight="48dp"
>
<GridLayout
android:layout_gravity="center"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:orientation="vertical"
android:rowCount="2"
android:useDefaultMargins="true"
>
<TextView android:id="#+id/number"
android:layout_gravity="center_vertical"
android:layout_marginLeft="2dp"
android:layout_rowSpan="2"
android:minEms="1"
/>
<TextView android:id="#+id/a"
android:layout_gravity="center_vertical"
android:layout_rowSpan="2"
android:minEms="2"
/>
<TextView android:id="#+id/b"
android:layout_marginBottom="0dp"
android:minEms="3"
/>
<TextView android:id="#+id/c"
android:layout_marginTop="0dp"
android:minEms="3"
/>
...
</GridLayout>
</FrameLayout>
Unless you're seeing a performance problem, I'd just keep it that way. If you're seeing a performance problem, and it's because of the additional FrameLayout (you can tell that if the problem goes away if you use GridLayout directly), then (and only then) I'd try fixing the GridLayout directly.
If that's the case, then what I know is that GridLayout distributes excess space according to the principle of flexibility. If that principle is not enough to disambiguate, then you'd see the behavior where it gives the excess space to the rightmost column and bottom row. I'd try to play with the row/col attributes to make sure that it understands how to distribute that evenly. You can control that by setting the gravity of the children of the GridLayout, in your case the TextViews. Try setting them to 'center', and see if that helps. If not, more info at:
http://developer.android.com/reference/android/widget/GridLayout.html
We are writing an app targeting ICS+ and believe a GridLayout is the best layout paradigm, but it seems very little has been written about it, and we are having some alignment issues.
<GridLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/row_background"
android:rowCount="1"
android:columnCount="3"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:useDefaultMargins="true"
android:background="#drawable/list_item_bg">
<ImageView
android:id="#+id/visibilityIcon"
android:layout_row="0"
android:layout_column="0"
android:src="#drawable/visibility_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"/>
<ImageView
android:id="#+id/windIcon"
android:layout_row="0"
android:layout_column="1"
android:src="#drawable/wind_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"/>
<ImageView
android:id="#+id/crosswindIcon"
android:layout_row="0"
android:layout_column="2"
android:src="#drawable/cloud_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"/>
</GridLayout>
However, the left 2 icons remain left-aligned, and the right-most icon centers with the remaining space.
Essentially what we need to do is specify the size of each column to be 1/3 (since 3 columns) of the total screen size. I thought this is what GridLayout did, but it appears 'wrap_content' causes this behavior (makes sense), but 'match_parent' causes the first column to fill the entire screen, rather than fill its cell which is the behavior I would have expected.
We seem to have tried every combination of gravity, layout_gravity, etc., but either we fundamentally are doing something wrong, or have found a limitation of the GridLayout.
Thanks for your help!
Only one row and one column is allowed to grow in a GridLayout, and that is the one with gravity along that axis. If more than one row or column specify gravity only one will get it (if I remember it is the "last" one). Choose another layout or write your own. If you only want a row with equally split icons you can use a LinearLayout where the widths of the components are 0px and the weight are all the same, e.g. 1.
My Login screen layout seems like this:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/login_layout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#ffffff">
<include
android:id="#+id/headerlayout"
layout="#layout/headerview"
android:layout_height="50dip"
android:layout_width="fill_parent" />
<ImageView
android:id="#+id/imgIcon"
android:src="#drawable/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/txtUserName"
android:layout_width="fill_parent"
android:layout_height="80dip"
android:lines="1"
android:textColor="#000000"
android:textStyle="bold"
android:textSize="16dip"
android:text="User Name"/>
</LinearLayout>
However I am not able to see ImageView and TextView. Only headerview is visible and white layout below it. Why is it so?
Thanks,
Stone
just add
android:orientation="vertical"
in your <LinearLayout> tag.
Edit:
By default the orientation is set to Horizontal means every component will be added horizontally, since you are using "fill_parent" to the header, so it covers all the place(width) and leave no room for other components to appear. So when you add vertical all components are placed vertically. So enough room is available for components to layout themselves.More detail here
Bydefault LinearLayout aligns all children in a single direction horizontally (if you dont specify android:orientation ) .
So here in your case it was adding views horizontally. Your header portion took full width of the screen (as you have specified android:layout_width="fill_parent" in include tag)and no space is left for that TextView and ImageView.
You just have to add orientation tag in LinearLayout and set its value to vertical.
ie android:orientation="vertical".
LinearLayout from Android Docs says
LinearLayout aligns all children in a single direction — vertically or horizontally, depending on how you define the orientation attribute. All children are stacked one after the other, so a vertical list will only have one child per row, no matter how wide they are, and a horizontal list will only be one row high (the height of the tallest child, plus padding). A LinearLayout respects margins between children and the gravity (right, center, or left alignment) of each child.