Android UI design for multiple size factors

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.

Answers


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.


Need Your Help

Can a variable like 'int' be considered a primitive/fundamental data structure?

language-agnostic data-structures variables computer-science

A rough definition of a data structure is that it allows you to store data and apply a set of operations on that data while preserving consistency of data before and after the operation.

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.