Multiple screen sizes and XML Layout - android

I have read everything I can find, and I just can't figure this out. I have an XML with a heading, then a listview, and then 2 buttons on the bottom row. In order to make the layout look perfect, I have "hardcoded" the size (467dp) of the listview. This is fine on my Samsung Galaxy S4, but I'm not sure it will look appropriate on other phones of slightly different sizes. I tested it on a Galaxy 8" tab and it did not look right. I then tested it on a 10.1" tab and it (again) did not look right. Basically the bottom buttons were up in the middle of the screen. I got around this by creating layouts for sw600dp and sw720dp. For each of those I had to hardcode a different size for the listview. It would seem to me that there is a better way to have a heading-listview-button XML that would display (relatively) the same on any device. Can anyone please tell me how to to alter my XML so I don't have to hardcode the size of the listview?
LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/title_line"
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center"
android:text="#string/workout_locations">
</TextView>
<ListView
android:id="#+id/location_list"
android:layout_width="match_parent"
android:layout_height="467dp"
android:longClickable="true" >
</ListView>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal" >
<ImageButton
android:id="#+id/help_button"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:contentDescription="#string/help_description"
/>
<ImageButton
android:id="#+id/add_button"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:contentDescription="#string/add_description"
/>
</LinearLayout>
</LinearLayout>

android:layout_weight="1 add this in the buttons

I wonder if this might help:
ensure that the entire layout is a relativeLayout, and inside it, put the listview
<ListView
android:id="#+id/location_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="50dp" // the size of the buttons height
android:longClickable="true" >
</ListView>
and below it another relativelayout with the buttons inside it.
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_gravity="bottom"
android:layout_alignParentBottom="true">
<ImageButton
android:id="#+id/help_button"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:contentDescription="#string/help_description"
/>
<ImageButton
android:id="#+id/add_button"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:contentDescription="#string/add_description"
/>
If this still causes an issue, then you could write :
android:layout_above="#+id/relButtonLayout"
inside the listview.

Use layout_weight to take up as much room that can be afforded.
<ListView android:id="#+id/location_list"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:longClickable="true" >
</ListView>

If you've hardcoded some sizes, you can bet it won't look good in most of the devices. In order to do that, it's always better using layout_height and layout_weight set to wrap_content or match_parent depending on what you need.
There's another important tool for the case you describe: layout_weight, as you might have already used. Messing with a ListView to fit the design you want can be hard at the first time, but once you discover how to set up its layout it's easy for the rest of them.
In my case, this definition always work as should:
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<ListView
android:id="#+id/mylistview"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:scrollbars="vertical" >
</ListView>
</LinearLayout>
Take a look at it: I've set a singular LinearLayout (in this case because it has more views than just the ListView I'm showing), but I'm setting the weight of that ListView to 1, being the sumWeights of that LinearLayout 1. This way you assure yourself the ListView will expand as long as it can, without the needing of hardcoding values.
It's just a matter of playing around with it for a while, but the less values you hardcode, the more adaptable will be on other devices.

Related

Android: ListView pushes out everything else below it

In my app, there is a tabbed activity with three fragments. The first fragment has a form to create a new task, the second fragment has the list of all the saved tasks, and the third fragment will show the comments on a task when selected from the list in the second fragment. The third fragment is also supposed to act like a chat activity which posts comments when you type them in and tap the send button. The XML layout of this third fragment is as follows:
<?xml version="1.0" encoding="utf-8"?>
<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:background="#android:color/darker_gray"
android:orientation="vertical"
tools:context="com.example.ishita.assigntasks.CommentsFragment">
<TextView
android:id="#+id/frag_task_details"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#dd55ff"
android:padding="10dp" />
<ListView
android:id="#+id/frag_comment_list"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:transcriptMode="normal" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="#android:color/white">
<EditText
android:id="#+id/frag_msg_edit"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:inputType="textMultiLine"
android:layout_weight="1" />
<ImageButton
android:id="#+id/frag_send_btn"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0"
android:background="#android:color/background_light"
android:contentDescription="#string/send_btn"
android:src="#android:drawable/ic_menu_send" />
</LinearLayout>
</LinearLayout>
As you can see, there is a TextView and a ListView and below that is another LinearLayout. Here is how it should look (the purple bar is the TextView):
And here is how it actually looks:
The TextView shows up above the ListView, but the LinearLayout does not. It is there, though. If I do android:layout_marginBottom="20dp" on the outermost LinearLayout, it does show up, but the ActionBar scrolls up and overlaps with the notification bar so that the title on the ActionBar and the notifications on the notification bar are both visible simultaneously and neither is legible.
I searched a lot and this seemed a common issue, but none of the solutions helped me. Believe me, I tried everything I could find. I tried wrapping the whole thing in a FrameLayout, using a RelativeLayout in place of the outermost LinearLayout, using two LinearLayouts--one to wrap the TextView and the ListView and the other to wrap the EditText and the ImageButton, etc., but nothing was able to show the bottom LinearLayout below the ListView. I even tried to set focus on the EditText when the fragment launches so that the keyboard would show and I can type, but even that doesn't help.
Note: On the other hand, if I use the exact same layout on an activity, the bottom LinearLayout displays exactly as it should.
I am unable to find the bug. Please help!
It looks like your toolbar pushes fragment layout down without decreasing its height. I have no idea why this happens (there are no root layout code here).
As a workaround you can set fragments layout bottom margin to ?attr/actionBarSize
As you have given layout_weight 1 in listview layout, so it occupies the whole space available. In order to get rid of you have to give some static height or use layout_weight in right manner
<ListView
android:id="#+id/frag_comment_list"
android:layout_width="match_parent"
android:layout_height="500dp"
android:transcriptMode="normal" />
or try like this
<?xml version="1.0" encoding="utf-8"?>
<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:background="#android:color/darker_gray"
android:orientation="vertical"
tools:context="com.example.ishita.assigntasks.CommentsFragment">
<TextView
android:id="#+id/frag_task_details"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#dd55ff"
android:padding="10dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="vertical"
android:background="#android:color/white">
<ListView
android:id="#+id/frag_comment_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:transcriptMode="normal" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal"
android:background="#android:color/white">
<EditText
android:id="#+id/frag_msg_edit"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:inputType="textMultiLine"
android:layout_weight="1" />
<ImageButton
android:id="#+id/frag_send_btn"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0"
android:background="#android:color/background_light"
android:contentDescription="#string/send_btn"
android:src="#android:drawable/ic_menu_send" />
</LinearLayout>
</LinearLayout>
All,
Thank you for all your responses. I found a workaround by trial and error now and thought I should post the answer for others who face the same issue. I set android:layout_marginBottom="50dp" on the inner LinearLayout (the one wrapping the comments bar--EditText and ImageButton). Somehow, this sets the layout correctly and the fragment functions properly in both Lollipop and Jellybean OS's. I haven't tested on other OS versions.
First of all you should read this, what is layout_weight and how it works.
You assigned layout_weight to ListView as 1, it means it covers whole height. just change it to 0.7 or any proportion you want (less than 1) will solve the problem.
<ListView
android:id="#+id/frag_comment_list"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.7"
android:transcriptMode="normal" />

Resize ImageView to make entire layout fill screen

I have a screen that contains some TextViews and an ImageView inside a LinearLayout with vertical orientation. I would like the whole thing to fit exactly in the screen (no matter what its size is) where the ImageView is the one that adjusts itself to accommodate this.
I've seen here a few variations of this question (including this) but didn't find anything that really answers my requirement.
So far i've used a solution which is not very "pretty", which is putting the entire LinearLayout inside a ScrollView, and use a custom ImageView that on its onMeasure method calculates the delta between the height of the ScrollView to the height of the screen. If the former is larger than the latter then the delta is subtracted from the ImageView's measured height.
This solution is not perfect and i would really like to know if there is a better one. Im sure there is.
Appreciate your help.
EDIT: here is the layout xml
<com.xxx.widgets.LockableScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:custom="http://schemas.android.com/apk/res/com.venews"
android:layout_width="match_parent"
android:layout_height="match_parent"
custom:scrollable="false"
android:fillViewport="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="#dimen/login_horizontal_margin"
android:paddingRight="#dimen/login_horizontal_margin"
android:orientation="vertical">
<com.xxx.widgets.ResizableToFitScreenImageView android:id="#+id/login_logo_image"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="#dimen/login_logo_margin"
android:layout_marginBottom="#dimen/login_logo_margin"
android:src="#drawable/ic_logo_and_name"/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView android:id="#+id/login_username"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"/>
<TextView android:id="#+id/login_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/login_username"/>
(...Other stuff...)
</RelativeLayout>
</LinearLayout>
</com.xxx.widgets.LockableScrollView>
EDIT2: and here's a sketch that i hope will make things clearer.
The sketch is showing 2 different screen sizes cause this solution would need to support also different devices with different screen sizes.
On the ImageView, set android:layout_height="0dp" and android:layout_weight="1". This will cause it to fill the remaining space (more about layout_weight here).
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>

Equal button height for RelativeLayout (while still filling up all space)

I have an Android application that goes about like this:
<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">
<RelativeLayout
android:id="#+id/toplayout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.90" >
<Button
android:id="#+id/button_1_of_10"
android:layout_width="70dip"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:text="#string/text_0x1701" />
<Button
android:id="#+id/button_2_of_10"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignRight="#+id/button_1_of_10"
android:layout_below="#+id/button_1_of_10"/>
<!--Another 8 buttons-->
<RelativeLayout
android:id="#+id/contentpane"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_toRightOf="#+id/button_1_of_10" >
</RelativeLayout>
</RelativeLayout>
<RelativeLayout
android:id="#+id/actionbuttonslayout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.10">
</RelativeLayout>
</LinearLayout>
I need the 10 buttons to fill up the entire height from the top to the footer (the 0.1 weighted RelativeLayout), while all the buttons keep an equal height. However, I want to know whether there is a kind of equivalent to the layout_weight from LinearLayout, but for RelativeLayouts, as it's not performant to have nested weights in LinearLayouts. I'm not really looking for other solutions, because I still have some thing to try, but I want to know whether or not this is possible?
My question, just to be clear, is: Is it possible to have an amount of Buttons with an equal height in a RelativeLayout and at the same time fill up all the available space?
To use weight you need to use a LinearLayout, just make a linear layout with the buttons take the space you want and then on each button inside have android:layout_height="0dp" and also a android:layout_weight="1"
You don't need to sum all the weights to 1, just think of items with the same weight have the same size

Problems with RelativeLayout

I separated the interface of my app in three areas: header, content and footer.
The header has a fixed size (it has only one image), while the footer and content have sizes that can vary.
In devices with higher resolutions I thought to insert the header and footer on the screen, and reserve any free space for the content area.
In devices with low resolutions thought of putting the content length as little as possible (something like wrap_content) and insert the footer below (requiring the user to perform scroll to view the footer).
The best I got was using RelativeView:
<RelativeLayout
android:id="#+id/relativeLayout1"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<LinearLayout
android:id="#+id/header"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_alignParentTop="true" >
(...)
</LinearLayout>
<LinearLayout
android:id="#+id/footer"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_alignParentBottom="true" >
(...)
</LinearLayout>
<FrameLayout
android:id="#+id/content"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_above="#+id/footer"
android:layout_below="#+id/header"
android:lay >
(...)
</FrameLayout>
</RelativeLayout>
For resolutions larger works as expected, the problem is that for small resolutions: the content is less than it should, because it takes the space between the header and footer.
How can I solve the problem?
I could not find another way to get content assuming all the free space of the screen (in large resolutions), because I can not simply use fill_parent, since the content is between the header and footer.
I also tried using min-height, but without success.
Top level RelativeLayout layout_height make that fill_parent.
Then FrameLayout remove the layout_above property, just saying it's below the header should be enough.
Finally, FrameLayout may be causing the problem as it's normally used when only 1 element is on the screen and it fills the screen. Try replacing this with a LinearLayout. I've done something exactly like what you want in one of my apps, the layout is (keep in mind in my case I swap out the FrameLayouts for Fragments which are LinearLayout or RelativeLayout based.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mainBack"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#color/transparent" >
<FrameLayout
android:id="#+id/headerFrag"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<FrameLayout
android:id="#+id/homeAdMsgFrag"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true" />
<ListView
android:id="#+id/contactList"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="#id/homeAdMsgFrag"
android:layout_alignParentLeft="true"
android:layout_below="#id/headerFrag"
android:background="#color/transparent"
android:cacheColorHint="#color/transparent" >
</ListView>
</RelativeLayout>
Some days before I also faced this issue, to solved what I did that I created Header.xml and footer.xml and included this two xml in my all others activities xmls because this two are common in all others activities.
To meet global resolution issue, I used weightsum and weight, applying weight will fixed your header and footer area and content area too.
This way I done in my one of project to resolve this issue, just try it, hope it will works for you.
EXAMPLE
<LinearLayout
android:weightSum="10"
android:orientation="vertical"
android:id="#+id/relativeLayout1"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<LinearLayout
android:id="#+id/header"
android:layout_width="fill_parent"
android:layout_weight="2"
android:layout_height="0dp"
android:orientation="vertical" >
(...)
</LinearLayout>
<FrameLayout
android:id="#+id/content"
android:layout_width="fill_parent"
android:layout_weight="6"
android:layout_height="0dp">
(...)
</FrameLayout>
<LinearLayout
android:id="#+id/footer"
android:layout_width="fill_parent"
android:layout_weight="2"
android:layout_height="0dp"
android:orientation="vertical" >
(...)
</LinearLayout>
</LinearLayout>
Thanks.

LinearLayout space distribution

I have a complex layout situation in which an horizontal LinearLayout holds two other LinearLayouts. The content for those layouts is dynamic, can be any kind of views, and is generated at runtime from different independent sources.
I want to display both of them as long as there is enough space, and limit them to 50% of the available space each otherwise. So I want those child LinearLayouts to have layout_width="wrap_content" when there is enough space, and layout_weight="0.5" when there isn't. This means that the space distribution could be 10-90, 25-75, 60-40; it would only be 50-50 when there isn't enough space to show the entire content of both views. So far I haven't find a way to do this from XML, so I'm doing it from code. My question is can I achieve what I want using only XML attributes? Will a different kind of layout be able to do it?
Here is my current layout XML:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="2dp" >
<LinearLayout
android:id="#+id/title_frame"
android:layout_width="wrap_content"
android:layout_height="48dp"/>
<LinearLayout
android:id="#+id/options_frame"
android:layout_width="wrap_content"
android:layout_height="48dp"/>
</LinearLayout>
Try this.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="2dp" >
<LinearLayout
android:id="#+id/title_frame"
android:layout_width="wrap_content"
android:layout_height="48dp" android:layout_weight="1">
</LinearLayout>
<LinearLayout
android:id="#+id/options_frame"
android:layout_width="wrap_content"
android:layout_height="48dp" android:layout_weight="1">
</LinearLayout>
</LinearLayout>
I tried it with textviews and this should work according to ure requirements.
It appears this cannot be achieved using only XML attributes.
Change layout_width="wrap_content" to layout_width="fill_parent" as you are using weight concept .

Categories

Resources