Wednesday, May 06, 2015

Android UI: Supporting multiple screen dimensions

My PART store app has evolved from a crappy jam-every-bits-of-code-into-one-java-file-and-ignore-OOP-project to a full-fledged Material-themed app taking into consideration some Android Design Patterns and all the Object Oriented goodness. However, working with fragments and separating all the bits into paginated layouts such as the Drawer Navigation as I've done, I quickly come to realize that while it works great for small phones, the UI looks like a waste of space on larger tablets. This is what iOS users have been complaining about about two years ago when they said that Android tablet apps are just phone apps blown up. Well, Android Studio makes the adjustment for this SUPER easy.

Now you can do this manually or you can just let AndroidStudio dialog interface work out the kins for you.

If you were to right click res > New > Android Resource Directory.. you'd get the following dialog:

So I can either just name the layout resource directory as layout-w600dp or.. if I just select "Screen Width" and enter 600 as a value, it will automatically create the new layout directory as layout-w600dp. But I'm not done yet. What I'll have to do is create anther layout that gets used when a width of 600 dp has been exceeded. That's easy, just copy and paste the original activity's layout. However, instead of using a DrawerLayout, I want to fix the Navigation ListView to the left of the screen. So I'd change the DrawerLayout view to a LinearLayout view, set the orientation to horizontal and put the drawerlist before the mainContent view. For example, here is mine for a layout with a slide-out DrawerLayout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <!-- Toolbar -->
    <android.support.v7.widget.Toolbar
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/tool_bar"
        android:background="@color/ColorPrimary"
        app:theme="@style/ThemeOverlay.AppCompat.Dark"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">

        <!-- DropShadow-->
        <View
            android:layout_width="fill_parent"
            android:layout_height="3dip"
            android:background="@drawable/drop_shadow" >
        </View>


        <android.support.v4.widget.DrawerLayout
            android:id="@+id/drawer_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <!-- Main Content -->
            <RelativeLayout
                android:id="@+id/mainContent"
                android:layout_width="match_parent"
                android:layout_height="match_parent">

            </RelativeLayout>


            <!-- Side navigation drawer UI -->
            <LinearLayout
                android:id="@+id/drawer_pane"
                android:layout_width="@dimen/drawer_width"
                android:layout_height="match_parent"
                android:layout_gravity="left|start">

                <ListView
                    android:id="@+id/navList"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:background="#ffeeeeee" />
            </LinearLayout>

        </android.support.v4.widget.DrawerLayout>

    </RelativeLayout>
</LinearLayout>

And here it is after I've changed the DrawerLayout to a LinearLayout (keeping the same id "@+id/drawer_layout") and readjusted the position

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <!-- Toolbar -->
    <android.support.v7.widget.Toolbar
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/tool_bar"
        android:background="@color/ColorPrimary"
        app:theme="@style/ThemeOverlay.AppCompat.Dark"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
        
        <LinearLayout
            android:orientation="horizontal"
            android:id="@+id/drawer_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <!-- Side navigation drawer UI -->
            <RelativeLayout
                android:id="@+id/drawer_pane"
                android:layout_width="@dimen/drawer_width"
                android:layout_height="match_parent"
                android:layout_gravity="left|start">

                <ListView
                    android:id="@+id/navList"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:background="#ffeeeeee" />

                <View
                    android:layout_width="fill_parent"
                    android:layout_height="3dip"
                    android:background="@drawable/drop_shadow" >
                </View>
            </RelativeLayout>

            <!-- Main Content -->
            <RelativeLayout
                android:id="@+id/mainContent"
                android:layout_width="match_parent"
                android:layout_height="match_parent">

            </RelativeLayout>
        </LinearLayout>
    </RelativeLayout>
</LinearLayout>

Lastly, how does the main activity handle this? Well, it can't. So the way to do this is to just simply check to see what kind of View the resource with id R.id.drawer_layout is. And if it's a drawerlayout, then you would proceed to create a hamburger menu icon, handle sliding in and out, etc. Otherwise if it's not a drawer_layout, then set it as a linear layout, in which case is probably not required.

private boolean slideOutDrawerMode = false;

//...

@Override
protected void onCreate(Bundle savedInstanceState) {

   //...
   View layout = findViewById(R.id.drawer_layout);

   slideOutDrawerMode = layout instanceof DrawerLayout;


   //..
   if (slideOutDrawerMode) {
      // Show hamburger menu icon
      getSupportActionBar().setDisplayHomeAsUpEnabled(true);

      // Do other things
   }
}

No comments :

Post a Comment