Scale layout items equally on large screens - android

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

Related

Android Layout Weight distribution

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 :)

adjust EditTexts and buttons with different screen sizes

How can I adjust EditTexts and Buttons to fit any screen size for android ? I'm trying to put some transparent EditTexts and Buttons in certain positions to fit my background image, but when I change screen size every thing changes. Here are my background image and my XML code :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/login_page"
android:orientation="vertical" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center_horizontal"
android:orientation="vertical"
android:padding="10sp" >
<EditText
android:id="#+id/etLogin"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10sp"
android:layout_marginTop="135sp"
android:background="#android:color/transparent"
android:hint="Login"
android:inputType="textCapWords"
android:padding="8sp" />
<EditText
android:id="#+id/etPassword"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="0sp"
android:layout_marginTop="-3sp"
android:background="#android:color/transparent"
android:hint="Password"
android:inputType="textPassword"
android:padding="8sp" />
<Button
android:id="#+id/btnLogin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12sp"
android:background="#android:color/transparent"
android:minHeight="40sp"
android:minWidth="500sp"
android:text="Login"
android:textColor="#08b0ef" />
</LinearLayout>
I tried other units like dp and dpi and dip but no one is giving the expected result.
Have you tried using "android:layout_weight" ?
I think what your talking about to set your Layout objects in a certain position relative to the background and once set, stay fixed proportionally so when the background stretches our contracts so do the buttons so they stay in the same position over the background?
If so (I could be way off),
setting the layout_weight attribute inside of each child object of the LinearLayout can let you position everything relative to the screen size so it automatically changes with each screen size. It will take a little trial and error to get the right percentages but should work.
Also consider creating multiple xml layout definitions for the major screen sizes so the OS automatically calls the one it needs for a particular screen with a resource qualifier, that way you know it will display in the right position. For example a xml called activity_main in R.layout is inflated by default but if you also create a activity_main in R.layout-land, this XML will only be inflated if the screen is in landscape mode. So you can set the sizes of your editText and Buttons for multiple screen size.
If you want to create only one file for all layout and trying to make your screen universal, you should try Linearlayout with weight property.
Instead of using sp or px, you should use pd for margin, padding or any other properties in your layout. dp will render differently as per screen resolution.

chess UI in android

I want to create simple UI for chess game in Android.
I want to adjust the screen to all kinds of mobiles.
I make a TableLayout with Table Row , each Row contain 8 Linear Layout that contain the View
for the players , my problem is that i make the width and the height of each linear layout in specific size (40 dp width and height), what is the best teqhniques to make the width and height right , here is the layout in xml file i described one row here ,
<?xml version="1.0"?>
-<TableLayout android:id="#+id/tableLayout" android:layout_height="fill_parent" android:layout_width="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android">
-<RelativeLayout android:layout_height="120dp" android:layout_width="120dp" android:background="#android:color/white">
<TextView android:id="#+id/textView1" android:layout_height="wrap_content" android:layout_width="wrap_content" android:text="TextView" android:layout_marginTop="24dp" android:layout_marginLeft="33dp" android:layout_alignParentTop="true" android:layout_alignParentLeft="true"/>
</RelativeLayout>
-<TableRow android:id="#+id/tableRow0" android:layout_height="wrap_content" android:layout_width="wrap_content">
<LinearLayout android:id="#+id/n00" android:layout_height="40dp" android:layout_width="40dp" android:background="#android:color/white" android:orientation="horizontal"/>
<LinearLayout android:id="#+id/n01" android:layout_height="40dp" android:layout_width="40dp" android:background="#android:color/black" android:orientation="horizontal"> </LinearLayout>
<LinearLayout android:id="#+id/n02" android:layout_height="40dp" android:layout_width="40dp" android:background="#android:color/white" android:orientation="horizontal"/>
<LinearLayout android:id="#+id/n03" android:layout_height="40dp" android:layout_width="40dp" android:background="#android:color/black" android:orientation="horizontal"> </LinearLayout>
<LinearLayout android:id="#+id/n04" android:layout_height="40dp" android:layout_width="40dp" android:background="#android:color/white" android:orientation="horizontal"/>
<LinearLayout android:id="#+id/n05" android:layout_height="40dp" android:layout_width="40dp" android:background="#android:color/black" android:orientation="horizontal"> </LinearLayout>
<LinearLayout android:id="#+id/n06" android:layout_height="40dp" android:layout_width="40dp" android:background="#android:color/white" android:orientation="horizontal"/>
<LinearLayout android:id="#+id/n07" android:layout_height="40dp" android:layout_width="40dp" android:background="#android:color/black" android:orientation="horizontal"> </LinearLayout>
</TableRow>
If I were developing a chess UI, I would not use frame layouts, but look into using a SurfaceView, and drawing onto a canvas.
Every View has a canvas, which is the what is actually drawn to the screen. If you create your own, you will be able to get much better control and render speeds, and you can just create the checkerboard with a simple look in your Java Code.
Might I suggest a different way to create your chess layout?
Consider a vertical LinearLayout (this will make your rows) containing horizontal linear (your columns). And then in each horizontal LinearLayout, have eight Buttons/ImageButtons. Here's an open source implementation of such a layout.
Now the question is how to correctly space these out (this should be applicable to your orignal layout if you want to keep it). There are two main ways we could do this:
Make the chess board fit on the screen, no scrolling needed.
Make the chess board a minimum width/height, scrolling may be necessary.
To accomplish the former, your outer layout should have match_parent for both width and height. Your inner layouts should match_parent for the width and wrap_content for height. Then your individual cells should have a weight attribute of 1. There are limitations to this approach, like how you won't be able to have any views to the side of the chess board (above and below should have space though).
To accomplish the latter (this is what you were asking for), the width and height attributes of your outer and inner layouts should be wrap_content. I also suggest you embed your structure in a ScrollView in case it expands past the screen.

Understanding measureWithLargestChild: Why breaks the layout?

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.

Extra Padding On Top Of My Images

I have a LinearLayout (Horizontal) that I am using to display 3 ImageViews. When I first add the ImageViews the last one is shrunk because the images are too big to fit 3 across. Here is what my designer screen looks like:
Notice the third image is shrunk.
To fix this issue I set the following attributes on each ImageView.
width: 0dp
weight: 1
Here is how my images look after setting those attributes:
The problem I am running into is even though the images have been shrunk there is still space at the top and bottom as shown by the blue rectangle in the following image:
My question is, why is this extra padding there and how can I get rid of it?
Thank you
UPDATE - adding my layout file
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/RelativeLayout1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center"
android:background="#color/app_background_color"
android:contentDescription="#string/game_image_button"
android:gravity="center"
tools:context=".EasyActivity" >
<LinearLayout
android:id="#+id/linearLayout1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<ImageView
android:id="#+id/ImageView02"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:contentDescription="#string/game_image_button"
android:src="#drawable/ruler200x200" />
<ImageView
android:id="#+id/ImageView01"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:contentDescription="#string/game_image_button"
android:src="#drawable/ruler200x200" />
<ImageView
android:id="#+id/imageView1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:contentDescription="#string/game_image_button"
android:src="#drawable/ruler200x200" />
</LinearLayout>
</RelativeLayout>
ImageViews support different ScaleTypes, the default is FIT_CENTER. here are the other options. FIT_CENTER means its going to start out with height and width equal to your image (what your images looked like in the first screen shot before you added weight). What I believe happened is that it then resized the width of the image based on your layout_weight, and maintained the image's aspect ratio by shrinking it to fit the new width. It left the height to be the original height and centered the result.
I think one of the other scale types would do what you want. Maybe CENTER or CENTER_INSIDE
You can use the following code
<Imageview.....
android:adjustViewBounds="true"
..../>

Categories

Resources