Home » Android » Android Core » Creating a Google TV Sliding Navigation Menu

About David Carver

Creating a Google TV Sliding Navigation Menu

The standard design pattern for Google TV apps is generally to use the LeftNavBar library. Unfortunately there isn’t an apklib and it isn’t included as a google tv addon library, so one has to compile and work with the library itself. The LeftNavBar library is basically the action bar flipped vertically.

The problem I have with it it is that the bar is always visible on the screen, and it doesn’t implement the Drawer Layout pattern, which lets the menu slide all the way in. It allows shows the icons that are available and it is always visible on the screen. So, I’ve created an alternative that will be used with Serenity starting with 1.4.0. This uses the MenuDrawer library, and the following custom layout.
 

<?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="#50000000" >

    <LinearLayout
        android:id="@+id/title_bar_layout"
        android:layout_width="match_parent"
        android:layout_height="59dp"
        android:background="@android:color/background_dark"
        android:gravity="center_vertical"
        android:paddingLeft="8dip"
        android:paddingRight="8dip" >

        <ImageView
            android:id="@+id/left_icon"
            android:layout_width="36dip"
            android:layout_height="36dip"
            android:layout_marginRight="8dip"
            android:scaleType="fitCenter"
            android:src="@drawable/serenity_bonsai_logo_small"
            android:visibility="visible" />

        <LinearLayout
            android:layout_width="0dip"
            android:layout_height="59dp"
            android:layout_marginRight="8dip"
            android:layout_weight="1"
            android:gravity="center_vertical"
            android:orientation="vertical" >

            <TextView
                android:id="@+id/title"
                android:layout_width="match_parent"
                android:layout_height="0dip"
                android:layout_weight="1"
                android:ellipsize="end"
                android:gravity="center_vertical"
                android:singleLine="true"
                android:text="@string/app_label" />

            <TextView
                android:id="@+id/subtitle"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:ellipsize="end"
                android:singleLine="true"
                android:visibility="gone" />
        </LinearLayout>

        <ProgressBar
            android:id="@+id/progress_circular"
            style="?android:attr/progressBarStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginRight="8dip"
            android:max="10000"
            android:visibility="gone" />

        <ImageView
            android:id="@+id/right_icon"
            android:layout_width="36dip"
            android:layout_height="36dip"
            android:layout_marginRight="8dip"
            android:scaleType="fitCenter"
            android:visibility="gone" />
    </LinearLayout>

    <ListView
        android:id="@+id/menu_list_options"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/title_bar_layout"
        android:descendantFocusability="afterDescendants"
        android:focusable="false"
        android:nextFocusDown="@+id/menu_help_text"
        android:nextFocusUp="@+id/menu_settings"
        android:scrollingCache="true" >
    </ListView>

    <LinearLayout android:id="@+id/menu_help"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_vertical"
        android:orientation="horizontal"
        android:layout_above="@+id/menu_settings"
        android:layout_alignParentBottom="true"
        android:visibility="visible"
        android:addStatesFromChildren="true" >

        <TextView android:id="@+id/menu_help_text"
            android:layout_width="0dp"
            style="@android:style/TextAppearance.Holo.Medium"
            android:text="Help"
            android:textColor="@android:color/white"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center_vertical"
            android:background="@drawable/menu_item_selector"
            android:drawableLeft="@drawable/ic_action_action_help"
            android:focusable="true"
            android:focusableInTouchMode="true"
            android:nextFocusUp="@+id/menu_list_options"
            android:clickable="true"
             />
    </LinearLayout>

    <LinearLayout android:id="@+id/menu_settings"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@android:color/background_dark"
        android:gravity="center_vertical"
        android:orientation="horizontal"
        android:layout_alignParentBottom="true"
        android:focusable="true"
        android:focusableInTouchMode="true"
        android:visibility="gone" >

        <TextView android:id="@+id/menu_settings_text"
            android:layout_width="0dp"
            style="@android:style/TextAppearance.Holo.Medium"
            android:text="Help"
            android:textColor="@android:color/white"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center_vertical"
            android:background="@drawable/menu_item_selector"
            android:drawableLeft="@drawable/leftnav_bar_option_icon_normal_dark"
            android:focusable="true"
            android:focusableInTouchMode="true"
            android:nextFocusUp="@+id/menu_options"
            android:clickable="true"
             />
    </LinearLayout>
</RelativeLayout>

This borrows a few design elements from the Google TV LeftNavBar (mainly the app header, progress items, and the Settings option in the menu). The rest contains a ListView named menu_list_options, which can be used to populate a list of options for the menu. In may case I use a TextView CompoundDrawable to create the options with their icons. You can populate the list however you want, and if you combine MenuDrawer with say SlidingMenu you could implement the multilevel sliding drawer that you see in apps like YouTube.

The results are similar to the following:

screenshot-from-2013-08-25-183736

By tying things further into the Google TV remote’s Menu key, and an on screen Drawer icon that is clickable, you can have the drawer slide out when needed and be hidden when it isn’t. It is important to make sure that users have some sort of visual indicator like standard 3 dots or dashes you see in the ActionBar on most apps.

To tie this into an activity is similar to the following:

protected void createSideMenu() {
   mainContext = this;
   menuDrawer = MenuDrawer.attach(this, MenuDrawer.Type.OVERLAY);
   menuDrawer.setMenuView(R.layout.menu_drawer);
   menuDrawer.setContentView(R.layout.activity_plex_app_main);
   menuDrawer.setDrawerIndicatorEnabled(true);

   View menuButton = findViewById(R.id.menu_button);
   menuButton.setOnClickListener(new MenuDrawerOnClickListener(menuDrawer));
   populateMenuOptions();
}

protected void populateMenuOptions() {
   List<MenuDrawerItem> drawerMenuItem = new ArrayList<MenuDrawerItem>();
   drawerMenuItem.add(new MenuDrawerItemImpl(getResources().getString(R.string.options_main_about), R.drawable.ic_action_action_about));
   drawerMenuItem.add(new MenuDrawerItemImpl(getResources().getString(R.string.options_main_clear_image_cache), R.drawable.ic_action_content_remove));
   drawerMenuItem.add(new MenuDrawerItemImpl(getResources().getString(R.string.tutorial), R.drawable.ic_action_tutorial));
   drawerMenuItem.add(new MenuDrawerItemImpl("Empty Video Queue", R.drawable.ic_action_content_remove));

   ListView listView = (ListView)menuDrawer.getMenuView().findViewById(R.id.menu_list_options);
   hideMenuItems(listView);
   listView.setAdapter(new MenuDrawerAdapter(this, drawerMenuItem));
   listView.setOnItemClickListener(new MainMenuDrawerOnItemClickedListener(menuDrawer, mainGallery));
}

If you want to tie this into the Google TV Menu key, here is a sample:

if (keyCode == KeyEvent.KEYCODE_MENU && !menuDrawer.isMenuVisible()) {
   menuDrawer.toggleMenu();
   return true;
}

if (keyCode == KeyEvent.KEYCODE_BACK && menuDrawer.isMenuVisible()) {
   menuDrawer.toggleMenu();
   return true;
}

In general using MenuDrawer vs SlidingMenu I found the former to be easier to use and worked well with the remote control. I experienced focus issues when trying to use SlidingMenu with a remote control, and not so with MenuDrawer. One thing to note, with MenuDrawer layouts is that items in the drawer even when they are not visible can gain focus with the D-Pad navigation. So make sure you are using the nextFocus* options in your layouts to help control things. Also you may want to hide options like the menu_list_options view when it isn’t actually showing.

So there you have it, a basic navigation drawer which hides when it isn’t needed, and can be made to slide out when it is. With a TV experience, screen space is at a premium, so freeing up much as possible can be a necessary thing at times.
 

Do you want to know how to develop your skillset to become a Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you our best selling eBooks for FREE!

1. JPA Mini Book

2. JVM Troubleshooting Guide

3. JUnit Tutorial for Unit Testing

4. Java Annotations Tutorial

5. Java Interview Questions

6. Spring Interview Questions

7. Android UI Design

and many more ....

 

Leave a Reply

Your email address will not be published. Required fields are marked *

*


8 − = six

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Want to take your Java Skills to the next level?
Grab our programming books for FREE!
  • Save time by leveraging our field-tested solutions to common problems.
  • The books cover a wide range of topics, from JPA and JUnit, to JMeter and Android.
  • Each book comes as a standalone guide (with source code provided), so that you use it as reference.
Last Step ...

Where should we send the free eBooks?

Good Work!
To download the books, please verify your email address by following the instructions found on the email we just sent you.