Home > Devices > Fire Phone

Dynamic Perspective UI Migration Guide

Introduction

This page provides basic information for converting an existing Android app to one that uses the Dynamic Perspective UI controls included in the Fire Phone SDK.

Comparing Android Controls to Dynamic Perspective UI Controls

The Dynamic Perspective UI controls are part of the Euclid package included in the Fire Phone SDK. For the most part, Euclid controls are very similar to their Android and Foundation Controls counterparts. Euclid controls retain the name of the original base control, but with a "Z" prepended to the name. For example, a Button control becomes a ZButton control. The next two sections discuss the key similarities and differences between 3D Euclid controls and their 2D counterparts.

Similarities between Euclid and 2D controls

Euclid simplifies the process of adding 3D effects to your Android apps. Because most Euclid layout and widget classes are derived from either standard Android or Amazon Foundation Control classes, you are probably already familiar with the most common methods and attributes of Euclid controls and should be able to convert your app to use the new Dynamic Perspective UI with few code updates.

The following aspects of a control remain unchanged when you swap a stock Android control for its Euclid equivalent, such as changing a Button to a ZButton:

  • Click handler methods: User interaction is handled via your existing onClick() method or View.OnClickListener object.
  • Screen position methods: Layout in the X and Y planes follow the same rules as 2D widgets.
  • Layout methods: Euclid controls follow Android rules for scaling, sizing, and padding, and auto-resize based on layout parameters.
  • Support methods: Euclid controls often inherit Android widget support for testing, accessibility, and localization.

Differences between Euclid and 2D controls

The biggest difference between Euclid and 2D widgets is how their visual assets are produced and rendered. These differences provide new behaviors but also set some limits on what you can change. Euclid widgets are artist-created textured mesh files, including collections of vertices, edges and faces that define the shape of 3D objects. Although you can set the color of a 3D widget, you cannot add a border, set a custom background, or make changes in View.OnDraw(). However, 3D controls do provide the same access to behaviors such as animations and head tracking without additional code.

The following summary highlights the changes between 2D and 3D controls:

  • Layout parameters: 3D object layout parameters include depth in addition to height and width. While 2D Android layouts are a nested hierarchy of flat rectangles, 3D layouts are a nested hierarchy of rectangular boxes.
  • Delegate classes: All 3D methods are passed to delegate classes to handle 3D operations, such as layout and animation. You do not need to extend the delegate classes unless you want to modify the stock control animations or layout.
  • Missing or overridden class methods: Some 2D Android base class methods have been removed from the 3D controls because these methods are either not relevant to a 3D environment or have been replaced with true 3D paradigms. For example, stock Android controls support rotation using a faux 3D mode, whereas Euclid replaces these methods with a simplified 3D orientation method.
  • Draw method: Because they are not rendered dynamically, 3D controls do not directly use the Draw method. Instead, you must build a tree of transformations and execute a drawing command using ZSceneNode and ZRenderable. This retained approach better matches the model of the underlying 3D graphics library. Note that this change is transparent if you are using the stock 3D controls in the toolkit.
  • Unsupported base class attributes: Some 2D base class attributes are not supported in 3D, such as the Android faux shadow parameter. See the API reference documentation for information about specific control attributes.
  • 3D-specific methods and attributes: 3D controls have 3D-specific methods and attributes, such as the ability to supply layout attributes using orientation_Z in a linear layout or depthGravity.

For more information about Euclid classes and layouts, see the Euclid reference documentation.

Adding Euclid Controls to Your App

Add Euclid 3D controls to your app by using a special container class (ZContainer) to wrap your controls and adding 3D elements. You should have to change a minimal amount of your existing code. This section discusses the details of migrating a standard Android app to a Euclid-based app.

Migration best practices

Use the following high-level guidelines to help plan your layout and controls for your Euclid content:

  • You can reuse most of your existing code when you migrate your app, mostly making minor layout modifications and writing code for new Euclid controls.
  • Use a standard Android activity, and embed your controls in the view hierarchy. Your controls may be all 2D, all 3D, or a mixture of the two types.
  • Use the ZContainer convenience class to add depth and place controls on the Z-axis. You must wrap 3D controls in a ZContainer to place those controls in a 2D Android layout.
  • Wrap your controls in a ZShadowReceiver to cast shadows from the controls. Place a ZShadowReceiver at the root of your layout to have all Euclid controls in that layout cast shadows.
  • The List, Grid, ScrollView, and picker classes have no Euclid equivalents. Use the original Android classes for these controls.

High-level process for migrating your app from 2D to 3D

While any number of approaches for migrating your app from 2D to 3D can work, one possible approach would be to migrate your app in phases:

  1. Wrap your controls in a ZContainer to add depth and place those controls on the Z-axis.
  2. Add a ZShadowReceiver to the root of your layout to add shadows (optional).

Example: Migrating a simple 2D sample app to 3D

This section walks through the process of migrating a simple 2D app to 3D using Euclid classes:

  1. Create a new simple Android app with two buttons and a text box. (Set the Fire Phone SDK as your build target in your IDE.) Use the following sample code as a guide:
    import android.app.Activity;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.Button;
    import android.widget.TextView;
    
    import com.amazon.euclid.samples.R;
    
    /**
     * An example full-screen activity that is essentially a very simple
     * Android activity with a couple of Buttons and a TextBox.
     */
    public class AndroidSampleActivity extends Activity {
    
        /**
         * The text view to display status
         */
        private TextView contentView;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            setContentView(R.layout.transition_android_activity);
    
            contentView = (TextView) findViewById(R.id.fullscreen_content);
        }
    
        /**
         * Callback when a button is clicked
         *
         * @param v the view that was clicked
         */
        public void onButtonClicked(View v) {
            if (v instanceof Button) {
                contentView.setText(((Button) v).getText() + " was clicked");
            }
        }
    }
    This example uses the following layout:
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
        android:layout_height="match_parent" android:orientation="vertical"
        android:paddingTop="50dip" tools:context=".FullscreenActivity">
    
        <!-- The primary full-screen view. This can be replaced with whatever
            view is needed to present your content, e.g. VideoView, SurfaceView, TextureView,
            etc. -->
    
        <Button android:id="@+id/dummy_button1" android:layout_width="200dp"
            android:layout_height="wrap_content" android:paddingBottom="25dp"
            android:onClick="onButtonClicked" android:text="@string/dummy_button1" />
    
        <Button android:id="@+id/dummy_button2" android:layout_width="200dp"
            android:layout_height="wrap_content" android:paddingBottom="25dp"
            android:onClick="onButtonClicked" android:text="@string/dummy_button2" />
    
        <TextView android:id="@+id/fullscreen_content"
            android:layout_width="match_parent" android:layout_height="0dip"
            android:layout_weight="1" android:gravity="center"
            android:keepScreenOn="true" android:text="@string/dummy_content"
            android:textColor="#33b5e5" android:textSize="50sp"
            android:textStyle="bold" />
    
    </LinearLayout>
    
    The following diagram shows the hierarchy of the app layout:

  2. Set up your app to use Euclid:
    1. Add the Euclid namespace to your layout XML.
    2. In your AndroidManifest.xml file, in the attributes of the <application /> element, specify one of the Euclid themes:

      <application android:theme=”@euclid:style/Theme.Euclid.Light ...

      Or

      <application android:theme=”@euclid:style/Theme.Euclid.Dark
  3. Add your Euclid controls, then wrap the button controls in ZContainers, and place a ZShadowReceiver at the root of your layout. Set autoPadding attribute of the ZContainers to true to mitigate visual clipping of the container contents.

    The following example shows the described layout with Euclid controls:
    <?xml version="1.0" encoding="utf-8"?>
    <com.amazon.euclid.widget.ZShadowReceiver
         xmlns:android="http://schemas.android.com/apk/res/android"
         xmlns:amazon="http://schemas.android.com/apk/res/amazon"
         xmlns:euclid="http://schemas.android.com/apk/res/euclid"
         android:layout_width="match_parent"
         android:layout_height="match_parent">
    
         <LinearLayout android:layout_width="match_parent"
             android:layout_height="match_parent" android:paddingTop="50dp"
             android:orientation="vertical">
             <com.amazon.euclid.widget.ZContainer
                  android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  euclid:autoPadding="true">
    
                  <com.amazon.euclid.widget.ZButton
                          android:id="@+id/dummy_button1"
                          android:layout_width="200dp" android:layout_height="wrap_content"
                          android:paddingBottom="25dp" android:onClick="onButtonClicked"
                          android:text="@string/dummy_button1"
                          euclid:layout_depth="wrap_content" />
    
              </com.amazon.euclid.widget.ZContainer>
    
              <com.amazon.euclid.widget.ZContainer
                  android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                   euclid:autoPadding="true"
                      <com.amazon.euclid.widget.ZButton
                          android:id="@+id/dummy_button2"
                          android:layout_width="200dp" android:layout_height="wrap_content"
                          android:paddingBottom="25dp" android:onClick="onButtonClicked"
                          android:text="@string/dummy_button2"
                          euclid:layout_depth="match_parent" />
    
              </com.amazon.euclid.widget.ZContainer>
              <TextView android:id="@+id/fullscreen_content"
                  android:layout_width="match_parent" android:layout_height="wrap_content"
                  android:layout_weight="1" android:gravity="center"
                  android:keepScreenOn="true" android:text="@string/dummy_content"
                  android:textColor="#33b5e5" android:textSize="50sp"
                  android:textStyle="bold" />
    
          </LinearLayout>
    </com.amazon.euclid.widget.ZShadowReceiver>
    

    The following diagram shows the final layout hierarchy:

Note that you did not need to make any changes to the Java code. You only needed to add a few elements to your layout XML file to migrate this app.

Control/Widget Migration Matrix

The following chart maps standard Android and Amazon Foundation Controls to their Euclid equivalents and gives recommendations on when to use which controls in an app that uses Euclid:

For examples of the Euclid controls, see the Dynamic Perspective Controls page within the design guidelines.

Android widget Foundation Controls widget Euclid widget Recommendation Comments
Button N/A ZButton ZButton
CheckBox N/A ZCheckBox ZCheckBox
DatePicker N/A N/A DatePicker Use 2D control within a 2D layout.
FrameLayout N/A ZFrameLayout ZFrameLayout or FrameLayout Use ZFrameLayout within a ZViewHost; use FrameLayout outside of a ZViewHost
N/A HeaderNavigationBar ZHeaderNavigationBar ZHeaderNavigationBar
N/A N/A ZImageButton ZImageButton

Use ZImageButton when you have a glyph that you want to function as a button.

ImageView N/A ZImageView ZImageView Use ZImageView to place a 2D image within a 3D layout. ZImageView does not support glyphs.
LinearLayout N/A ZLinearLayout ZLinearLayout or LinearLayout Use ZLinearLayout within a ZViewHost; use LinearLayout outside of a ZViewHost
MediaController MediaController ZMediaController ZMediaController
N/A NavigationPane N/A NavigationPane Use 2D control within a 2D layout.
NumberPicker N/A N/A NumberPicker Use 2D control within a 2D layout.
PopupMenu N/A N/A PopupMenu Use 2D control within a 2D layout.
PopupWindow N/A N/A PopupWindow Use 2D control within a 2D layout.
ProgressBar N/A ZProgressBar ZProgressBar
RadioButton N/A ZRadioButton ZRadioButton
RadioGroup N/A ZRadioGroup ZRadioGroup
RelativeLayout N/A ZRelativeLayout ZRelativeLayout Use ZRelativeLayout within a ZViewHost; use RelativeLayout outside of a ZViewHost
ScrollView N/A N/A ScrollView Use 2D control within a 2D layout.
SeekBar N/A ZSeekBar ZSeekBar
Slider N/A ZSeekBar ZSeekBar
N/A TabBar ZTabBar ZTabBar
N/A TabBarItem ZTabBarItem ZTabBarItem
TextView N/A ZTextView
ZExtrudedText
ZTextView or ZExtrudedText Use ZTextView when putting 2D text inside of a 3D layout or when putting 2D text in a normal android (non-3D) layout. Use ZExtrudedText for 3D text in 3D layout
TimePicker N/A N/A TimePicker Use 2D control within a 2D layout.
ToggleButton N/A ZToggleButton ZToggleButton
N/A ToolBar ZToolBar ZToolBar
N/A ToolBarItem ZToolBarItem ZToolBarItem