I am doing the following course at udacity. It's about Android User Interface.
As a part of my course I used an XML visualizer.
http://labs.udacity.com/android-visualizer/#/android/linear-layout-weight
Now upon experimenting I entered the following code
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:src="#drawable/ocean"
android:layout_width="wrap_content"
android:layout_height="400dp"
android:scaleType="centerCrop"
android:layout_weight = "1"/>
<TextView
android:text="You're invited!"
android:layout_width="wrap_content"
android:layout_height="100dp"
android:textColor="#android:color/white"
android:textSize="54sp"
android:layout_weight = "1"
android:background="#009688" />
<TextView
android:text="Bonfire at the beach"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#android:color/white"
android:textSize="34sp"
android:background="#009688" />
</LinearLayout>
as per my understanding, by using android:layout_weight the whole parent layout is divided as per priority and distributed accordingly, if so, the space after distributing among image and "You're invited!" there should only be remaining space enough, to fill out "Bonfire at the beach".
Then why there is a empty space below "Bonfire at the beach" ?
(Also if possible can anyone please explain how the control flows among XML code).
UPDATE
when I added android:layout_weight = "0" in "Bonfire at the beach" then there is no empty space below. Can any one explain why this happens and why there is space in previous case. and this is the code is used.
before
after
even tried setting height to 0dp
Understand it using the below example
Weight defines how much space a view will consume compared to other views within a LinearLayout.
Weight is used when you want to give specific screen space to one component compared to other.
Key Properties:
weightSum is the overall sum of weights of all child views. If you don't specify the weightSum, the system will calculate the sum of all the weights on its own.
layout_weight specifies the amount of space out of the total weight sum
the widget will occupy.
Code:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:weightSum="4">
<EditText
android:layout_weight="2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Type Your Text Here" />
<Button
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Text1" />
<Button
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Text1" />
</LinearLayout>
The output is:
Now even if the size of the device is larger, the EditText will take 2/4 of the screen's space. Hence the look of your app is seen consistent across all screens.
[This if before you edit your question might be irrelevant now
Now in your Bonfire at the beach there is no weight and its wrap_content so there is no grantee that it will take the remaining space! and that space can remain after adding it will differ with the screen size of device ]
Note:
Here the layout_width is kept 0dp as the widget space is divided horizontally. If the widgets are to be aligned vertically layout_height will be set to 0dp.
This is done to increase the efficiency of the code because at runtime the system won't attempt to calculate the width or height respectively as this is managed by the weight. If you instead used wrap_content the system would attempt to calculate the width/height first before applying the weight attribute which causes another calculation cycle.
Lets Move to your XML
see how i used them
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:weightSum="3" //<-------------------
android:layout_height="match_parent">
<ImageView
android:src="#drawable/mc"
android:layout_width="match_parent"
android:layout_height="0dp"
android:scaleType="centerCrop"
android:layout_weight = "1"/> //<-------------------
<TextView
android:text="You're invited!"
android:layout_width="match_parent"
android:layout_height="0dp"
android:textColor="#android:color/white"
android:textSize="54sp"
android:layout_weight = "1" //<-------------------
android:background="#009688" />
<TextView
android:layout_weight = "1" //<------------------- if you remove this , this text view will be gone cuz its 0 by default
android:text="Bonfire at the beach"
android:layout_width="match_parent"
android:layout_height="0dp"
android:textColor="#android:color/white"
android:textSize="34sp"
android:background="#009688" />
</LinearLayout>
Now you ask what if you have not given android:layout_weight ,Default weight is zero. Zero means view will not be shown, that empty space will remain there
Since you don't believe you can read the documentation
EDIT: 2
Since you said that, i went through android-visualizer that you use
and Have you ever noticed this...
"Line 6: The attribute android:weight_sum is not supported here."
thing on its bottom.
Meaning they are not providing that functionality to adjust your layout boundaries. Its just a simple online tool.I am
not saying it is not recommended to use, but my personal idea is, you
can't touch the depth of android if you use that.
Now if you want a confirmation what actually happens have a look on android studio/ eclipse as well which are read IDE s
This is android studio
Can you see any view contain your text "Bonfire at the beach"? no
Instead a.studio display a red line in XML.
Suspicious size: this will make the view invisible
Because there is no layout_weight is given and we have added 0 height
Now you can accept the answer :)
Related
I have a TextView whose width should not exceed the ImageView above it. Both image and text are downloaded from server and I don't know their dimensions (can't make assumptions either). I went through the logic to wrap the text content using this SO post.
Here is my layout XML
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/parentLL"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout android:orientation="vertical"
android:id="#+id/LL1"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/image1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:width="0dp"
android:text="This is a string whose width may or may not be more than the image downloaded" />
</LinearLayout>
<TextView android:background="#android:color/holo_red_dark"
android:id="#+id/text2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Second Text"/>
</LinearLayout>
With this code, the TextView at the end (text2) does not even show up. There are 2 solutions to this issue :
Apply android:maxLines="5" to the text1. Problem with this approach is that Text1 view would always be 5 lines high (I understand 'lines' is not a unit of height, but that's what I see visually). So if the text content is just one word, there would be a big white space below. And then text2 shows up.
Change topmost linear layout (parentLL) to RelativeLayout. text2 can then be used with alignBelow=LL1. This works as expected. But I cannot migrate the topmost view to RelativeLayout, because this view is from a library not in my control. I can only modify LL1 and it's children. Due to my code, other views below (like text2) are suffering (by not showing up).
There is a third approach for setting the textview as a compound drawable on ImageView. I guess that might work (haven't tested), but my requirement is to show the TextView if image download has failed (which can be detected only after a while). So I need to have a TextView. Also, my LinearLayout LL1 can have other children too.
I would request for some help understanding :
Why is my code not showing up the content below the textview 'text1'? With width=0 on textview it seems to set the height of the parent to be match_parent.
How is RelativeLayout able to handle this smoothly ? Can I replicate any of that behavior in TextView's onMeasure ? Assume I have callbacks to detect image has been downloaded, and I can get image width also.
I think what you are running into is a conflict of setting the width and height but not setting the layout weight, which is a key factor in how Linear Layouts work. If you add one more vertical LinearLayout in there and then move #id/text2 into it, you should be set. You'll need something like the following (obviously modified to your specs, this was just a quick test). Note my use of android:layout_weight,
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
>
<LinearLayout
android:orientation="vertical"
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:textAppearance="?android:attr/textAppearanceLarge"
android:text="Large Text"
android:id="#+id/textView3" />
</LinearLayout>
<LinearLayout
android:orientation="vertical"
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:textAppearance="?android:attr/textAppearanceLarge"
android:text="Large Text"
android:id="#+id/textView2" />
</LinearLayout>
</LinearLayout>
Which splits the screen in half vertically as shown in this picture,
Photo of resulting layout
I had to wrap the TextView in a RelativeLayout, which was wrapped by a LinearLayout. Not happy with this solution, but this is the only way for now.
I'm playing with the option measureWithLargestChild="true". I don't understand why my layout breaks total, if one of my buttons has a too big text onto it. I think it should keep the basic size of 1/3 but they gets smaller about 1/6. Why is that?
Here can you see some screenshots:
Here is my xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:baselineAligned="false"
android:gravity="center"
android:orientation="vertical" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:baselineAligned="false"
android:measureWithLargestChild="true" >
<Button
style="#style/my_style"
android:layout_weight="1"
android:text="Button123456" />
<Button
style="#style/my_style"
android:layout_weight="1"
android:text="A" />
<Button
style="#style/my_style"
android:layout_weight="1"
android:text="WW" />
</LinearLayout>
</LinearLayout>
I believe this is a bug in measure algorithm. There is following comment in LinearLayout.measureHorizontal(int, int) method.
// Either expand children with weight to take up available space or
// shrink them if they extend beyond our current bounds
It says, the algorithm will shrink items with weight if there is not enough space for them. As measureWithLargestChild is set to true, all items have the same width as the most left item. Now they all together don't fit into the parent's width anymore. Thus they will be shrank. If there were no bug, all items would have same width afterwards. But due to the bug, algorithm shrinks original (wrap_content) widths instead of widths calculated according to measureWithLargestChild attribute. That's why two items on the right became smaller.
For example, if you have a horizontal LinearLayout with android:measureWithLargestChild="true" and android:layout_width="wrap_content"
Make sure the child view has set both android:layout_width="0dp" and android:layout_weight="1". Otherwise the width of child is not what you expect.
An answer at the end of this question has been filled out, combining remarks and solutions.
Question
I searched around but haven't found anything that really explains why Android Lint as well as some Eclipse hints suggest replacing some layout_height and layout_width values with 0dp.
For example, I have a ListView that was suggested to be changed
Before
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1">
</ListView>
After
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
</ListView>
Similarly, it suggested changes to a ListView item. These all look the same before and after the changes, but I'm interested in understanding why these are performance boosters.
Anyone have an explanation of why? If it helps, here is general layout with the ListView.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ImageView
android:id="#+id/logo_splash"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</ImageView>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:background="#color/background"
android:layout_below="#id/logo_splash">
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
</ListView>
<TextView
android:id="#android:id/empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/no_upcoming" />
</LinearLayout>
</RelativeLayout>
Answer
I'm putting in an answer here because it's really a combination of answers and referenced links below. If I'm wrong on something, do let me know.
From What is the trick with 0dip layout_height or layouth_width?
There are 3 general layout attributes that work with width and height
android:layout_height
android:layout_width
android:layout_weight
When a LinearLayout is vertical, then the layout_weight will effect the height of the child Views (ListView). Setting the layout_height to 0dp will cause this attribute to be ignored.
Example
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
</ListView>
</LinearLayout>
When a LinearLayout is horizontal, then the layout_weight will effect the width of the child Views (ListView). Setting the layout_width to 0dp will cause this attribute to be ignored.
Example
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal">
<ListView
android:id="#android:id/list"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1">
</ListView>
</LinearLayout>
The reason to want to ignore the attribute is that if you didn't ignore it, it would be used to calculate the layout which uses more CPU time.
Additionally this prevents any confusion over what the layout should look like when using a combination of the three attributes. This is highlighted by #android developer in an answer below.
Also, Android Lint and Eclipse both say to use 0dip. From that answer below, you can use 0dip, 0dp, 0px, etc since a zero size is the same in any of the units.
Avoid wrap_content on ListView
From Layout_width of a ListView
If you've ever wondered why getView(...) is called so many times like I have, it turns out to be related to wrap_content.
Using wrap_content like I was using above will cause all child Views to be measured which will cause further CPU time. This measurement will cause your getView(...) to be called. I've now tested this and the number of times getView(...) is called is reduced dramatically.
When I was using wrap_content on two ListViews, getView(...) was called 3 times for each row on one ListView and 4 times for each row on the other.
Changing this to the recommended 0dp, getView(...) was called only once for each row. This is quite an improvement, but has more to do with avoiding wrap_content on a ListView than it does the 0dp.
However the suggestion of 0dp does substantially improve performance because of this.
First of all you have this,
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1">
</ListView>
Never take the ListView's height as wrap_content, that will lead into troubles. Here is the reason for that and this answer.
Further more,
I searched around but haven't found anything that really explains why
Android Lint as well as some Eclipse hints suggests replacing some
layout_height and layout_width values with 0dp.
Its because you are using layout_weight = "1" that means your ListView with take the height as much as is available to it. So, in that case there is no need of using layout_height = "wrap_content" just change it to android:layout_height="0dp" and ListView's height will be managed by layout_weight = "1".
So when android:layout_weight is used on View X and LinearLayout is horizontal, then X's android:layout_width is simply ignored.
Similar, when android:layout_weight is used on View X and LinearLayout is vertical, then X's android:layout_height is ignored.
This actually means, that you can put anything in those ignored fields: 0dp or fill_parent or wrap_content. It doesn't matter. But it's recommended to use 0dp so View's do not do extra calculation of their height or width (which is then ignored). This small trick simply saves CPU cycles.
from :
What is the trick with 0dip layout_height or layouth_width?
as far as i know , there is a difference between using 0dp (or 0px btw, it's the same since 0 is 0 no matter what is the unit here ) and the wrap_content or fill_parent (or match_parent, it's the same).
it depends on the weight you use . if you only use weight of 1 , they all look the same , but the meaning is always different , and it is important for performance.
in order to show this , try the following:
<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">
<TextView android:id="#+id/textView1" android:layout_width="match_parent"
android:layout_height="0px" android:text="1" android:background="#ffff0000"
android:layout_weight="1" android:gravity="center"
android:textColor="#ffffffff" android:textSize="20sp" />
<TextView android:id="#+id/textView2" android:layout_width="match_parent"
android:layout_height="0px" android:text="2" android:background="#ff00ff00"
android:layout_weight="2" android:gravity="center"
android:textColor="#ffffffff" android:textSize="20sp" />
<TextView android:id="#+id/textView3" android:layout_width="match_parent"
android:layout_height="0px" android:text="3" android:background="#ff0000ff"
android:layout_weight="3" android:gravity="center"
android:textColor="#ffffffff" android:textSize="20sp" />
</LinearLayout>
and then try to replace the 0px with match_parent . you will see that the result is very different.
usually , for both better understanding and for better performance , you would want to use 0px.
LinearLayout measures all the children according to the layout_width/layout_height values, then divides up the leftover space (which may be negative) according to the layout_weight values.
0dp is more efficient than wrap_content in this case because it's more efficient to just use zero for the original height and then split the parent's full height based on the weight than to measure the child first and then split the remainder based on the weight.
So the efficiency comes from not measuring the child. 0dp should be exactly as efficient (and produce exactly the same result) as match_parent, or 42px, or any other fixed number.
Caution re using android:layout_height="0dp"
I have found that in a ListView
(with the recommended View recycling using convertView, see e.g. http://lucasr.org/2012/04/05/performance-tips-for-androids-listview/),
setting android:layout_height="0dp" for the row TextView can lead to text truncation for multi-line text content.
Whenever a TextView object that was previously used to display a text that fitted in a single line is recycled to display a longer text that needs more than one line, that text is truncated to a single line.
The problem is cured by using android:layout_height="wrap_content"
I'm confused and frustrated that I can't get my EditText field to take up a rational amount of space in the layout without explicitly telling it how many pixels to be.
I'm *sure I'm missing something obvious, but my experience is that EditText totally ignores layout_weight and either grows/shrinks dynamically with the text that is entered into it if I give it a layout_weight of "wrap_content" or takes up most of the space in its parent layout if I give it a weight of fill_parent.
So... what is the correct path to having an EditText field that occupies some portion of its parent layout (in my case Linear, but I'm flexible) so that it can have a label next to it and look like:
Name: [ EDIT TEXT HERE ]
Phone:[ EDIT TEXT HERE ]
etc.
TIA
You can do a couple different things. As mentioned, you should be using dp instead of pixels for layout. Using dp allows your views to scale by the screen's physical size rather than resolution.
Here's an example of specifying the edit boxes to appear to the right of each label and take up the remainder of a the screen:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="#+id/name_label"
android:layout_width="100dp"
android:layout_height="50dp"
android:text="Name:" />
<TextView
android:id="#+id/phone_label"
android:layout_width="100dp"
android:layout_height="50dp"
android:layout_below="#id/name_label"
android:text="Phone:" />
<EditText
android:id="#+id/name_text"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_toRightOf="#id/name_label" />
<EditText
android:id="#+id/phone_text"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_toRightOf="#id/phone_label"
android:layout_below="#id/name_text" />
</RelativeLayout>
Here's an example of a LinearLayout where weight is used:
<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="50dp"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="match_parent"
android:text="Name:"
android:layout_weight="1"/>
<EditText
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="5"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="match_parent"
android:text="Phone:"
android:layout_weight="1"/>
<EditText
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="5"/>
</LinearLayout>
</LinearLayout>
Note that the LinearLayout has 7 views while the RelativeLayout accomplishes something similar with 5 views. LinearLayouts hare handy, but they're more complex. As your layouts get more complicated, they will perform worse than RelativeLayouts, especially when you nest them.
For each line use a horizontal LinearLayout.
Inside that, add a horizontal LinearLayout to 'wrap' the TextView. Give that LinearLayout a layout_weight of 20 (for example).
Use another horizontal LinearLayout to 'wrap' the EditText and set the EditText to fill_parent but give its outer LinearLayout a layout_weight of 80 (or whatever value based on 20+80 = 100% if you see what I mean).
EDIT: Also if you need to have multiple lines then to simplify the overall layout file, you can define a 'single line' layout file and use it as a custom layout entry.
//for your edittext set min width and max length
android:minWidth="40"
android:maxLength="30"
android:layout_width="wrap_content"
so that it will be always shows minimum width and your characters wont exceed more than 30.
You need to work with the Layout. LinearLayout is not the right Layout for your purposes. Have a look at TableLayout, which I think might fulfill your requirements. Have a look at the TableLayout tutorial.
I've got a 4-item start screen in my app, which looks like the following:
What's important to me there:
- All items do have the same width (not regarding how much text is actually in it)
- Look the same on all devices (small-screen, mdpi, large-screen, etc.)
Im just wondering if there is a easy solution about this problem?
I've tried using 3 LinearLayouts but thats really awkward..
(1 presenting the layout root[vertical] and two which do each contain 2 buttons[horizonal]).
Making this layout ready for multiple screens would require a lot of fixed-width and fixed-margin hacking. Just like "button margin = 30dp on xlarge, 20 on large, 15 on normal,...".
My layout-xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/background"
android:id="#+id/main_root"
android:orientation="vertical"
android:gravity="center" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_gravity="center" >
<Button
android:id="#+id/btn_learn"
android:text="#string/mainBtn_learn"
style="#style/mainBtn"
android:onClick="handleBtnClick"
android:layout_margin="20dip" />
<Button
android:id="#+id/btn_quiz"
android:text="#string/mainBtn_quiz"
style="#style/mainBtn"
android:onClick="handleBtnClick"
android:layout_margin="20dip" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_gravity="center" >
<Button
android:id="#+id/btn_search"
android:text="#string/mainBtn_search"
style="#style/mainBtn"
android:onClick="handleBtnClick"
android:layout_margin="20dip" />
<Button
android:id="#+id/btn_more"
android:text="#string/mainBtn_more"
style="#style/mainBtn"
android:onClick="handleBtnClick"
android:layout_margin="20dip" />
</LinearLayout>
Is there a view which "auto-scales" these Buttons or still any other easier solution?
Edit:
So, in special, you need something like
button:
android:layout_width="15%" // 15% of screen width / height depending on the orientation
android:layout_marginBottom="10%" // see above
I'm pretty new to Android development but I can show you what worked for me in a similar case. I defined my layout as follows:
<LinearLayout
android:id="#+id/linearLayout2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<EditText
android:id="#+id/outputText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:editable="false" />
<Spinner
android:id="#+id/outputSpinner"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:prompt="#string/OutputBaseOptionsPrompt" />
</LinearLayout>
I have a horizontal layout with two items. The LinearLayout has a width of "match_parent" so that it is as wide as the screen. Both items in the layout have the following:
android:layout_width="0dp"
android:layout_weight="1"
Since both items have a layout_weight of 1, they will be drawn at the same width. In this case, each item takes up half of the available space. If you change the weight of one of these items to "2" then it will be twice as wide as the item with a weight of "1".
Do you already have xml that makes it work on one screen size? If so post what you have so far.
I would suggest using a RelativeLayout for your root though. You can use the alignCenter attributes to float your children towards the middle. Then you just have to hard code the inner margins (how far apart you want the buttons) rather than the margin from yourself to the wall.
You could also avoid having to hard code the inner margin by making your own button 9 patch images. You can just add a border of transparent pixels in your image to represent the margin. You'll probably still want to supply an image for each density you wish to support though.
The solution is you dont use hardcoded values any where
Put three images with same name in hdpi mdpi and ldpi folders in drawables
an run the code