Designing User Interfaces For Android Wear Part 1: Lists

Rising in popularity after the latest Google I/O, Android Wear is a game changer for mobile development. Wearable technology has brought benefits from a quicker access to information to a more accurate monitoring of our physical health. Developing for this platform allows you to tap into those features that are not as readily available on mobile handhelds as well as offer a more immersive experience of your product by making it available on wearable devices.

As always, the documentation will offer the most thorough insight into what is available, but I’d like to discuss how the UI development differs and how you can get started.

WatchViewStub

The first class you should learn about from the Wear library is WatchViewStub. This class is responsible for determining the screen shape of a Wear device. Currently there are two (or three) shapes of Wearable devices: square and round, with some round devices having an inset at the bottom. Assuming you’d like your Activity to appear differently for each device, your activity_main.xml file should have this component as its root view:

    <android.support.wearable.view.WatchViewStub 
    	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/watch_view_stub"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:rectLayout="@layout/rect_activity_main"
        app:roundLayout="@layout/round_activity_main"
        tools:context="com.androidessence.watchsample.MainActivity"
        tools:deviceIds="wear"/>

The main attributes to notice here are app:rectLayout and app:roundLayout. The layouts specified in each are the layouts that will appear on the device when the Activity loads, after the device shape has been determined.

Unlike an Activity on a mobile handset, referencing views is not as simple as calling findViewById() inside of onCreate(). You need to wait until the WatchViewStub has inflated the necessary layout. You do so by attached an OnLayoutInflatedListener:

    final WatchViewStub stub = (WatchViewStub) findViewById(R.id.watch_view_stub);
    stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() {
        @Override
        public void onLayoutInflated(WatchViewStub stub) {
            // Handle views
        }
    });

If the same resource identifiers are used in both round and square layouts, your code can be the same here. If you need to do something special programatically based on screen shape, see this article from the documentation.

BoxInsetLayout

This layout is similar to a FrameLayout but is aware of the type of screen and is used to display something the same way on both round and square devices.

WearableListView

Extending from the new RecyclerView, a WearableListView is simply a list component optimized for Wear devices. It is optimized by only showing three list items at a time, so the item height is programatically determined by the component. This is to allow for easier click handling of list items. It is also recommended that you create a special layout for each list item, so you can use an OnCenterProximityListener to provide a special implementation for views when they appear in the middle of the watch screen, as explained here. In this first segment on Wear UI, we’ll go through that in a little more detail, skipping over what we’ve already touched on.

List Item

In this sample, we’ll use a WearableListItemLayout that extends from TextView, so we can just simply display some words on the screen for testing purposes:

    public class WearableListItemLayout extends TextView implements WearableListView.OnCenterProximityListener{
     
        WearableListItemLayout(Context context) {
            this(context, null);
        }
     
        WearableListItemLayout(Context context, AttributeSet attributeSet) {
            this(context, attributeSet, 0);
        }
     
        WearableListItemLayout(Context context, AttributeSet attributeSet, int defStyle) {
            super(context, attributeSet, defStyle);
        }
     
        @Override
        public void onCenterPosition(boolean b) {
            // When centered, let's enlarge the text.
            // As of API 23, we don't need to pass context.
            if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                setTextAppearance(android.R.style.TextAppearance_Large);
            } else {
                setTextAppearance(getContext(), android.R.style.TextAppearance_Large);
            }
        }
     
        @Override
        public void onNonCenterPosition(boolean b) {
            // When leaving centered, set text backk to small.
            if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                setTextAppearance(android.R.style.TextAppearance_Small);
            } else {
                setTextAppearance(getContext(), android.R.style.TextAppearance_Small);
            }
        }
    }

As mentioned, we can implement the OnCenterProximityListener so that items in the center of our list at the time can be enlarged, as seen by this photo:

WearList

We also implement the onNonCenterPosition method so that when an item moves out of the center location, it returns back to the appropriate text appearance.

Earlier I stated that the WearableListView class extends from RecyclerView, as a result the Adapter class is setup in a very similar fashion, so it has been omitted from this post. If you would like to see it, please check the code on GitHub, which you can also run on your own Wear device or emulator to see the list in action.

More information on running your Wear app can be found here.

Adam McNeilly

Adam McNeilly
Adam is a Google Developer Expert for Android. He's been developing apps since 2015, and travels the world to present and learn from other Android engineers.

Interface Naming Conventions

Many engineers will tell you that one of the most complicated responsibilities of our job is naming things. Variables, classes, functions...… Continue reading