Android UI design for multiple size factors - android-layout

I'm building an app, which starts with a PIN screen similar to the stock PIN entry screen, the problem is that I cannot get the design to work on all kinds of phones, for simplicity's sake let's talk only about portrait mode ( I will link the layout xml below ):
on small-screen devices I needed to decrease the size in dp of the buttons, so that they don't hang out on the edge of the screen
on large devices the buttons are bigger, so they don't clump together in the middle of the screen
there are some old (2.3) devices I need to support, one of them is a 5"-ish tablet, on which the buttons hang out ( because the size factor falls in the large category ), but it should be in the normal size category. I know about smallest-width size group, but that is only for >3.2 devices.
I would like to have a somewhat consistent look on all the devices, (largely) independent of its form or size. I thought about dynamic sizing of elements, but there is no support for it, and I don't want to go near the AbsoluteLayout class.
Does anyone share my frustrations, or has developed a good solution?
The layout file I'm using:
<?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="fill_parent" >
<TextView android:id="#+id/enter_pin"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/DIALOG_ENTERPIN" />
<EditText android:id="#+id/pin_box"
android:layout_below="#id/enter_pin"
android:layout_centerHorizontal="true"
android:layout_width="fill_parent" />
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_below="#id/pin_box"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<TableRow android:gravity="center" >
<Button android:id="#+id/pin_1"
style="#style/pinbutton"
android:text="1" />
<Button android:id="#+id/pin_2"
style="#style/pinbutton"
android:text="2" />
<Button android:id="#+id/pin_3"
style="#style/pinbutton"
android:text="3" />
</TableRow>
<TableRow android:gravity="center" >
<Button android:id="#+id/pin_4"
style="#style/pinbutton"
android:text="4" />
<Button android:id="#+id/pin_5"
style="#style/pinbutton"
android:text="5" />
<Button android:id="#+id/pin_6"
style="#style/pinbutton"
android:text="6" />
</TableRow>
<TableRow android:gravity="center" >
<Button android:id="#+id/pin_7"
style="#style/pinbutton"
android:text="7" />
<Button android:id="#+id/pin_8"
style="#style/pinbutton"
android:text="8" />
<Button android:id="#+id/pin_9"
style="#style/pinbutton"
android:text="9" />
</TableRow>
<TableRow android:gravity="center" >
<Button android:id="#+id/pin_back"
style="#style/pinbutton"
android:text="‹" />
<Button android:id="#+id/pin_0"
style="#style/pinbutton"
android:text="0" />
<Button android:id="#+id/pin_ok"
style="#style/pinbutton"
android:text="OK" />
</TableRow>
</TableLayout>
</RelativeLayout>
Update:
I am already using different layouts for different size-groups, and exclusively use dp & sp, FYI, so please refrain from writing generalities. Still the problem lies in the finer details, the size-bins are not well chosen IMO.

I thought about dynamic sizing of elements, but there is no support for it
What does this mean? Dynamic sizing is more or less the basis of Android layouts. You can use DP as you've mentioned for relative sizing based on the density, you can use layout_weight with LinearLayouts to work with fractional portions of the display, you can use wrap_content and match_parent to make the graphics size based on the size of the display, or the content inside. My suggestion to start with would be to give the buttons both a min_width/min_height attribute, that way on a larger device the buttons don't get so large as to be ridiculous, but also don't get too small to press on smaller devices.
An alternate method, if you don't mind having a few different versions of your layout file, is to have more resource-qualified layout folders (e.g. layout-large, layout-small, etc.) with slightly different layouts depending on the general size of the display.
EDIT: Okay, quick idea, just for the PIN pad, I didn't even look at this in a layout editor, but this is the basic idea of how I'd probably do this. There's no maxWidth or maxHeight attribute for LinearLayout, so I'd probably make a resource folder for layout_sw600dp and layout_sw720dp and hardcode a smaller size for the PIN pad for screens of that size.
<LinearLayout
android:id="#+id/pin_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:max_width="480dp"
android:max_height
android:layout_margin="20dp"
android:orientation="vertical"
>
<LinearLayout
android:id="#+id/pin_row1"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal"
>
<Button
android:id="#+id/num1"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:padding="5dp"
android:text="1"
/>
<Button
android:id="#+id/num2"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:padding="5dp"
android:text="2"
/>
<Button
android:id="#+id/num3"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:padding="5dp"
android:text="3"
/>
</LinearLayout>
<LinearLayout
android:id="#+id/pin_row2"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal"
>
<Button
android:id="#+id/num4"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:padding="5dp"
android:text="4"
/>
<Button
android:id="#+id/num5"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:padding="5dp"
android:text="5"
/>
<Button
android:id="#+id/num6"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:padding="5dp"
android:text="6"
/>
</LinearLayout>
<LinearLayout
android:id="#+id/pin_row3"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal"
>
<Button
android:id="#+id/num7"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:padding="5dp"
android:text="7"
/>
<Button
android:id="#+id/num8"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:padding="5dp"
android:text="8"
/>
<Button
android:id="#+id/num9"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:padding="5dp"
android:text="9"
/>
</LinearLayout>
</LinearLayout>

Yes, UI design for Android is one of the most tedious and frustrating aspects of app development.
There are several ways to deal with the issue (none of which are quick and easy per se). Either lay things out in code, and deal with different densities/resolutions then.
Otherwise, duplicate your layouts, but adjust the values, and store them in separate layout folders which the OS will automatically select from depending on the manufacturer specified screen size.
Take advantage of the layout, layout-small, layout-large, layout-xlarge, layout-xlarge, layout-land, etc. This way, you can basically c&p your layouts in to each directory and modify the specific dimensions that way. Further, if you find you're reusing a lot of the different dimensions, specify dimensions.xml or styles.xml so that you can avoid having to type them repeatedly.
http://developer.android.com/guide/practices/screens_support.html
is a pretty good resource, but the answer in general is that ui design for multiple sizes simply takes a lot of work.

in a general way,define the size of Button or other View using dip or dp, define the size of text using sp, if you do so,then your app could fit most of the screens.

Related

Design Android dev screen sizes

Hi I need some advice/help
I am designing a app for educational purposes, but battling with different screen sizes.
I am using Android studio to create the screen layouts.
What I did so far works well up and until a point.
I have tried to use constraint layout / Linear layout and relative layout but all have the same issues.
I create my main layout as normal, and then I create new layout resource files with the same activity name but with different densities.
But for some odd reason some of my test phones picks up the certain density layout but is completely out of proportion, even though it looks correct on the layout on the IDE but the minute it is ported to the phone its out.
What would be the best way to create layouts that can cater for all layouts?
here is an example of the layout I have
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".login.LoginActivity"
android:background="#drawable/background"
android:padding="10dp">
<TextView
android:id="#+id/tv_appName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="250dp"
android:layout_marginEnd="8dp"
android:text="#string/app_name"
android:textColor="#color/colorAccent"
style="#style/Base.TextAppearance.AppCompat.Headline"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:textAlignment="center"
android:textStyle="bold"
android:textSize="28dp"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="50dp"
android:layout_marginTop="32dp"
android:layout_marginEnd="50dp"
android:ems="10"
android:inputType="textPersonName"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/tv_appName"
android:background="#drawable/input_shape"
android:padding="15dp"
android:textColorHint="#color/colorAccent"
android:textColor="#color/colorAccent"
android:id="#+id/edittext1"
android:singleLine="true"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="50dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="50dp"
android:ems="10"
android:inputType="textPersonName"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/edittext1"
android:background="#drawable/input_shape"
android:padding="15dp"
android:textColorHint="#color/colorAccent"
android:textColor="#color/colorAccent"
android:id="#+id/edittext2"
android:singleLine="true"/>
<Button
android:id="#+id/btn_button1"
android:layout_width="134dp"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
app:layout_constraintStart_toStartOf="#+id/edittext2"
app:layout_constraintTop_toBottomOf="#+id/edittext2"
android:background="#drawable/btn_shape"
android:text="Button 1"/>
<Button
android:id="#+id/btn_button2"
android:layout_width="134dp"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
app:layout_constraintEnd_toEndOf="#+id/edittext2"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toEndOf="#+id/btn_button1"
app:layout_constraintTop_toBottomOf="#+id/btn_button1"
android:background="#drawable/btn_shape"
android:text="Button 2"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
I am pretty sure that you are using a fixed size for your views.
Never use a fixed size for a view. If you are using a ConstraintLayout then set the layout_width and layout_height of any view to either 0dp (which will make the view as big as it can be as long as it doesn't go past the constraints) or wrap_content (which will automatically make the view only the size it needs). On other layouts instead of using 0dp for making the view as big as it can be, use match_parent. wrap_content does the same thing in every layout.

Android layout weight not working as I thought

following What does android:layout_weight mean?
I have this:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<Button
android:id="#+id/buttonToastSimple"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="English Toast" />
<Button
android:id="#+id/buttonToastFancy"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="3"
android:text="French Toast" />
</LinearLayout>
The link tells me buttonToastFancy will take up three quarters of the size (3/(3+1), but it's the other way round. The buttonToastSimple takes up three quarters of the screen size according to Eclipse/my AVD.
What am I doing wrong?
<LinearLayout
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:weightSum="4"
android:orientation="horizontal" >
<Button
android:id="#+id/buttonToastSimple"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="English Toast" />
<Button
android:id="#+id/buttonToastFancy"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="3"
android:text="French Toast" />
</LinearLayout>
try setting the wanted attribute to 0dp ..
ex. if you are setting the weight for the widths support, use android:layout_width="0dp" along with the android:layout_weight="3". Also, don't forget the android:weightSum="4" in the parent.
the amount of space your view is going to occupy is computed as
dimension/layout_weight hence the view with the lower layout_weight occupies more space in your layout. in the future, you may also need to user layout_weightSum.
They are further explained here.

Display a changeable ListView next to a Webview

I need to display a ListView next to a Webview (like the Master/Detail sample), but I need to be able to sort the ListView in a different order (to display some items by category or by name for example), but I did not succeed to make it possible with tabs, dropdown menu or SectionPagerAdapter because the Master/Detail sample uses Fragment, and the TabHost is not a Fragment. I am a bit lost with what I should use.
To make it clear, I want to display it like that :
1
Is there some open source project that use this kind of view, or do your have some advice to perform that ?
You can do it also manually. Just make two list views on top of each other and change their visibilities so only one at a time will be shown.
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<Button
android:id="#+id/btn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:id="#+id/btn2"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal" >
<FrameLayout
android:layout_width="64dp"
android:layout_height="match_parent" >
<ListView
android:id="#+id/list_view1"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ListView
android:id="#+id/list_view2"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
<WebView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
</LinearLayout>
This is just skeleton of you're UI that you can use.

Possible overdraw: Root element paints background

In my application, it appears this warning on the lints of Android:
Possible overdraw: Root element paints background #drawable/main with
a theme that also paints a background (inferred theme is #android:style/Theme)
I wanna know how to correct this mistake, cause after checking and checking on internet, I just found that it is decreasing application speed cause it reload two times the background to put this source.
This is the source of my layout.xml:
<?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/main"
android:orientation="vertical" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="120dp"
android:layout_centerHorizontal="true"
android:layout_marginLeft="20dp"
android:text="#string/alta1"
android:textColor="#000"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="#+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/textView1"
android:layout_marginTop="20dp"
android:layout_centerHorizontal="true"
android:text="#string/alta2"
android:layout_marginLeft="20dp"
android:textColor="#000"
android:textAppearance="?android:attr/textAppearanceSmall" />
<Button
android:id="#+id/continuaralta"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_below="#+id/textView2"
android:layout_marginRight="50dp"
android:layout_marginTop="36dp"
android:textStyle="bold"
android:background="#drawable/boton"
android:text="#string/continuar" />
<Button
android:id="#+id/saliralta"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="#+id/continuaralta"
android:layout_alignBottom="#+id/continuaralta"
android:layout_marginRight="15dp"
android:layout_toLeftOf="#+id/continuaralta"
android:background="#drawable/boton"
android:textStyle="bold"
android:text="#string/salir" />
Neil Sainsbury, at http://www.earthtoneil.com/, says that Romain Guy has addressed the underlying issue at http://android-developers.blogspot.com/2009/03/window-backgrounds-ui-speed.html. See Neil's blog and search for your error message. Then, go to http://developer.android.com/guide/topics/ui/themes.html to learn how to apply background themes to the app as a whole and to individual activities.
This approach will at least cause the error message to no longer appear. Hitting the two-arrows icon to refresh the warnings in the lint window after making the fix was necessary in my case.

Android UI: how to align a TextView and two radiobuttons to occupy 1/3rd parent each?

I'm sure it's very simple and I'm just being stupid, but I've tried numerous variants and still can't get it working. What's worse - these 3 components are aligned exactly the way I want in the graphical editor in Eclipse, but not on the real device. I only get to align it to 50% for TextView and RadioGroup.
The XML goes like this currently (here I presumed RadioGroup is kind of LinearLayout):
<RadioGroup
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
style="#style/ButtonStyle"
android:layout_width="wrap_content"
android:text="#string/CC_Direction_caption" />
<RadioButton
android:id="#+id/rb_toCamera"
style="#style/ButtonStyle"
android:text="#string/CC_Backwards_Caption" />
<RadioButton
android:id="#+id/rb_toInfinity"
style="#style/ButtonStyle"
android:text="#string/CC_Forwards_Caption" />
</RadioGroup>
And the ButtonStyle is:
<item name="android:layout_width">0dip</item>
<item name="android:layout_height">70dp</item>
<item name="android:layout_weight">1</item>
And all this is inside a TableRow.
Use android:layout_centerVertical="true" in your TextView.
Below is a sample:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical" >
<TextView
android:id="#+id/typeLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:text="GroupBox Label"
android:textColor="#color/black"
android:textSize="14dp" />
<RadioGroup
android:id="#+id/radioGroup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#color/white"
android:layout_alignParentRight="true"
android:gravity="center"
android:orientation="horizontal" >
<RadioButton
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="Radio 1 Text"
android:textColor="#color/blue" />
<RadioButton
android:id="#+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Radio 2 t"
android:textColor="#color/blue" />
</RadioGroup>
</RelativeLayout>
Try adding android:layout_weight="1" to all three elements. This specifies the relative weight every element has to the others. The higher this value is the less weight the element gets.
oh, and wrap everything in a linear layout (didn't see you didn't add a layout first).
You should use a Linear Layout with weights on your elements which will make it pretty easy to achieve what you want.
Check the docs for info on Linear Layout and weights.
http://developer.android.com/guide/topics/ui/layout-objects.html
Try changing layout_width to "wrap_content" for radio buttons as well. You have already done it for the text field.

Resources