Google TV

Developing Google TV User Interface

  1. Google TV screen size and density
  2. Font guidelines
  3. Widget guidlines
  4. Layout guidelines
  5. Display resolution guidelines
  6. Handling Input events
  7. Controlling navigation and focus
  8. Using the left side navigation bar
  9. Using fragments
  10. Handling large/high resolution images

This topic contains guidelines for tuning your application's UI to a Google TV device. In general we recommend to base your Google TV application's look-and-feel on the Android "Holo" theme. Choosing this theme will ensure that your default Android widgets will have a consistent feel with the platform. More information about how to set (and customize) a theme for your applications can be found here.

Google TV screen size and density

A Google TV device is classified as a large rather than as an xlarge screen size. If your application provides multiple resource directories for different screen sizes, Google TV will automatically use the large set. Although TVs are bigger than mobile devices that use the large screen size, users view TVs from much farther away, so that the resulting UI is scaled accordingly.

A Google TV device with a 1080p TV display is classified with the xhdpi screen density. With a 720p TV display, it is classified with the tvdpi screen density. If your application provides multiple resource directories for different densities, Google TV will load resources based on the screen density.

Remember that multiple resource directories are optional. Android automatically scales resources to the TV display's current settings.

Font guidelines

If you specify a font size, use units of scale-independent pixels (sp). This allows user preferences for fonts to influence the resulting font size. For additional information, see the description of the android:textSize attribute and the reference documentation for android.util.DisplayMetrics.scaledDensity. Specifying your text sizes using the @android:style/TextAppearance.XXXX also works well on all devices

<TextView style="@android:style/TextAppearance.Small">
<TextView style="@android:style/TextAppearance.Medium">
<TextView style="@android:style/TextAppearance.Large">

Widget guidelines

Use the "10-foot UI" rule: Make sure widgets such as buttons or text are clearly visible to a viewer sitting approximately ten feet away from the TV (this distance is greater for very large screens).  The best way to ensure this is to use layout-relative sizing (for example, wrap_content), and use density-independent pixel values (dp units) instead of hard pixels (px units).

Layout guidelines

Use dynamic layouts like RelativeLayout or LinearLayout to arrange View objects, instead of AbsoluteLayout which uses fixed coordinates to position screen alignments. Using dynamic layouts allows Android to adjust the position of the View objects to the size, alignment, aspect ratio, and pixel density of the Google TV device screen.

Whenever possible, align child View objects to their parent Layout rather than to a sibling. For example, to left-align a View within the UI, set its android:alignParentLeft attribute. Using this technique, you can align View objects to the left or right of the parent Layout, and even center them within the Layout. Don't use the attribute android:toRightOf to position a View on the right side of your UI; instead, use the attribute android:alignParentRight to align the View's right edge with the right edge of its parent.

When you use RelativeLayout, set minimum margins for each View object, using dp units. This ensures that your screen layout is not too crowded. Remember to use margins, not padding; in general, padding controls spacing inside a View object, while margins control the spacing between View objects.

Display resolution guidelines

Avoid making assumptions about the display resolution of a Google TV device. Unlike mobile devices, the full display size of a TV may not be usable by your application, because of a factor called overscan.

Overscan is a technical aspect of TV transmission that reduces a TV's usable screen margins. The extra space is detected to features such as closed-captioning, and also adjusts for picture anomalies that occur at the screen edges. Because of various factors, there is no standard for the amount of reduction.

For Google TV devices, it results in a usable screen area that is smaller than the full display resolution. For example, a TV with a 16:9 aspect ratio and 1080 lines of horizontal resolution with progressive scan (1080p)  should have a theoretical display resolution of 1920 x 1080 pixels. Because of overscan, this may be reduced by 5% on all four edges, yielding an actual display resolution of 1728 x 972.

Google TV adjusts to overscan by having the user measure the viewable picture size during initial setup. Because of this, Google TV can report the actual display resolution. The DisplayMetrics object returned by Display.getMetrics() contains the actual display resolution.

Because of the overscan issue, you can not assume a display resolution for a Google TV device. Instead, allow Android to scale your UI. If you do calculations, base them on the data you get from the DisplayMetrics object.

To ensure that your UI displays correctly on all TVs, you can modify the size of this visible area and then test your application.

Start by setting an actual display size that is smaller than the display size the TV can use:

  1. Go to Settings > Picture and Sound > Picture Size. This displays the Overscan dialog.
  2. Select No, start with default. On the screen, a black box entitled Maximize your screen area appears. The box is surrounded by a light blue edge.
  3. Click Next. At each succeeding screen, click Next but do not adjust the edges of the box. At the last screen, click Save and restart to reboot the Google TV device.
  4. After your device reboots, examine the screen closely. You should see that the edges of the Home screen have a large black border around them.
  5. Now test your application. The entire application with all of its UI controls should be visible and should appear undistorted.

Next, set the actual display size to be slightly larger than the TV's viewable area:

  1. Go to Settings > Picture and Sound > Picture Size to display the Overscan dialog.
  2. Click Yes, start with current. On the screen, a black box entitled Maximize your screen area appears. The box is surrounded by a light blue edge.
  3. Click Next. On the next screen, press Up to move the black box edge one line up towards the top edge of the entire screen. When the box edge reaches the screen edge, and the blue border is no longer visible, press Up 10 times more to adjust the screen area beyond the actual viewable area.
  4. Repeat step 3 to adjust the right, bottom, and left edges of the screen.
  5. At the last screen, click Save and restart to reboot the Google TV device.
  6. Now test your application. The entire application with all of its UI controls should be visible and should appear undistorted.

Handling Input events

The standard input hardware for a Google TV device includes a mouse or equivalent, an alphanumeric keyboard, a directional pad (D-Pad), and media transport controls keys such as play, pause, and rewind (see the following section "Media Keys"). In addition, you should expect that the device does not have a full touch screen interface. Some devices may emulate a subset of touchscreen features using the mouse or D-Pad.

To respond to input devices, your Android application UI contains several View objects that trigger actions or provide input to the application. These are your UI controls.

Your users interact with your UI controls by using the D-Pad keys either to navigate to a control or to trigger an input. To navigate between controls, the user presses the up, down, left, and right arrow keys on the D-Pad. These may be labeled with text or icons or both, or may simply have the appropriate shape. In response, Google TV moves the input focus to the nearest control in the appropriate direction, as determined by an internal algorithm.

To trigger the action of a control, the user presses the center key of the D-Pad, which sends KeyEvent.KEYCODE_DPAD_CENTER. The keyboard ENTER key sends KeyEvent.KEYCODE_ENTER.

In some cases, the navigation task is not over, because the control has its own internal navigation; for example, the user may also need to navigate among the cells in a GridView control. In this case, you may need to provide the user with one or more sub-controls for saving and canceling the work down within the control.

Most Android devices are touchscreen devies, while Google Tv is non-touchscreen device. So make sure all your controls are d-pad navigable and they show appropriate highlight when they are selected or focused using d-pad. Test your application with the D-Pad to ensure that your users can easily navigate to all the controls in each Activity.

Ensure that movement between controls is straightforward and predictable. For example, if you have vertically scrolling content on your screen, make sure that the actionable controls are on the left. In this case you can use LeftNavLibrary to set actionable controls on the left. If you have horizontally scrolling content, make sure that actionable controls are on top of bottom using the standard Android ActionBar. Also, make sure that the d-pad navigation does not jump randomly or skip controls in between. All controls should be d-pad navigable in a intuitive manner.

If the screen layout makes navigation difficult, or if you want users to move through the layout in a specific way, you can set up explicit navigation for your controls. To set up explicit navigation, use the android:nextFocusUp, android:nextFocusDown, android:nextFocusLeft, and android:nextFocusRight attributes for the control View objects in your layout. These specify the next View that should get focus when the next focus is "up", "down", "left", and "right". The next focus is triggered by a D-Pad key; for example, android:nextFocusUp is triggered by KeyEvent.KEYCODE_DPAD_UP.

You can also use android:nextFocusForward, which specifies the next View that should receive focus when the next focus is FOCUS_FORWARD. This is usually generated by KeyEvent.KEYCODE_TAB.

If necessary, you can allow a View object to receive focus, even if it normally doesn't. To do this, you use the android:focusable attribute.

To learn more about designing UIs for non-touchscreen devices, you should also read the topic Controlling Focus Order in the Android Developers Guide.

You should use appropriate highlights for focusable and selected states of the controls. This makes it easy for the user to know that the control is focused or selected. Also make sure that these are uniform in color across your application. You can implement these highlights using Color State List Resources.

Using the left side navigation bar

When your screen layout has a vertically scrolling component, its recommended that you use the left side navigation bar. To do this, include the Left side Navigation library in your application. The library contains classes that facilitate putting action controls on the left side of the screen. For vertically-scrolling layouts, the left-side navigation controls are better than the regular ActionBar controls on the top, the reason being, Google TV layouts should be navigable with the D-pad alone. If the current focus is inside a vertically-scrolling area, and you use ActionBar, you are forcing users to navigate through the entire vertical list to get to action controls. Conversely, using left-side navigation means that the user simply has to navigate once to the left to exit the vertical scrolling and reach action controls.

The Left navigation bar demo sample app demonstrates how simple it is to include the left navigation bar in your app.

Using Fragments

Google TV applications usually work with more screen area than mobile apps, and the Android Fragments feature is a good tool for making good use of this larger UI space. Check out the sample code to learn how to use Fragments to control multiple panes within your application's UI.

Handling large/high resolution images

Google TV devices have higher display resolution. If you provide low resolution or small images in your layouts, they will appear pixelated, fuzzy, or grainy. This is not a good experience for the user. Instead, use high resolution images. Remember, though, that downloading and storing high-resolution images may cause "out of memory" errors. To avoid these errors, follow these tips:

  • Load images only when they're displayed on the screen. For example, are displaying multiple images in a GridView, ListView or Gallery, only load an image when its getView() is called.
  • Call recycle() on Bitmaps that are no longer needed.
  • Use WeakReferences for storing references to Bitmap objects in a in memory collection.
  • If you fetch the images from the network, use AsyncTask to fetch them all at once or as needed. Never do network transactions on the main ("UI") thread. Instead, if possible, fetch all the images at once on a background thread, and store them on the sdcard.
  • Scale down very large images to a more appropriate size as you download them; otherwise, downloading the image may cause an "out of memory" error. Here is sample code that does this scaling while downloading:
       // Get the source image's dimensions
       BitmapFactory.Options options = new BitmapFactory.Options();
       options.inJustDecodeBounds = true; // this does not download the actual image, just downloads headers.
       BitmapFactory.decodeFile(IMAGE_FILE_URL, options);
    
       int srcWidth = options.outWidth;  // actual width of the image.
       int srcHeight = options.outHeight;  // actual height of the image.
    
       // Only scale if the source is big enough. This code is just trying to fit a image into a certain width.
       if(desiredWidth > srcWidth)
         desiredWidth = srcWidth;
    
       // Calculate the correct inSampleSize/scale value. This helps reduce memory use. It should be a power of 2.
       int inSampleSize = 1;
       while(srcWidth / 2 > desiredWidth){
         srcWidth /= 2;
         srcHeight /= 2;
         inSampleSize *= 2;
       }
    
       float desiredScale = (float) desiredWidth / srcWidth;
    
       // Decode with inSampleSize
       options.inJustDecodeBounds = false;  // now download the actual image.
       options.inDither = false;
       options.inSampleSize = inSampleSize;
       options.inScaled = false;
       options.inPreferredConfig = Bitmap.Config.ARGB_8888;  // ensures the image stays as a 32-bit ARGB_8888 image. 
                                                             // This preserves image quality.
       Bitmap sampledSrcBitmap = BitmapFactory.decodeFile(IMAGE_FILE_URL, options);
    
       // Resize
       Matrix matrix = new Matrix();
       matrix.postScale(desiredScale, desiredScale);
       Bitmap scaledBitmap = Bitmap.createBitmap(sampledSrcBitmap, 0, 0,
           sampledSrcBitmap.getWidth(), sampledSrcBitmap.getHeight(), matrix, true);
       sampledSrcBitmap = null;
    
       // Save
       FileOutputStream out = new FileOutputStream(LOCAL_PATH_TO_STORE_IMAGE);
       scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
       scaledBitmap = null;
    
       

Authentication required

You need to be signed in with Google+ to do that.

Signing you in...

Google Developers needs your permission to do that.