CHAPTER SIX: Managing the Device Orientation

Chapter opener image: © Fon_nongkran/Shutterstock

Introduction

When we run an app and we rotate the device that the app is running on, the Graphical User Interface (GUI) may or may not rotate. Some apps, in particular games, are best run in one orientation only, often horizontal. But sometimes, we want to build an app that works in both horizontal and vertical orientations in order to provide a better experience for the user and also to expand the reach of the app. Some users might prefer to run an app in horizontal position while others might prefer to run it in vertical position. The default behavior is that the app automatically rotates. If we want to prevent our app from rotating, we need to specify either portrait or landscape as the value for the android:screen Orientation attribute inside the activity element of the AndroidManifest.xml. For example, if we want the app to run in horizontal position only, we specify the following:

<activity
  android:screenOrientation=”landscape”

In this chapter, we want the app to run in both orientations. We use the Empty Activity template so that our View has nothing in it when we start.

6.1 The Configuration Class

The Configuration class, from the android.content.res package, encapsulates a device’s configuration information such as locale, input modes, screen size, or screen orientation. In this chapter, we focus on screen orientation. TABLE 6.1 shows some public fields and methods of that class. The orientation field can have two values as shown in TABLE 6.2: ORIENTATION_LANDSCAPE, a constant that has value 2, and ORIENTATION_PORTRAIT, another constant that has value 1.

TABLE 6.1 Selected public fields and methods of the Configuration class

Field or Method Description
public int keyboard Keyboard for the device.
public Locale locale User preference for the locale.
public int orientation An integer value representing the orientation of the screen.
public int screenHeightDp Height of the screen, not including the status bar, in dp units (density independent pixels).
public int screenWidthDp Width of the screen in dp units.
public boolean isLayoutSizeAtLeast( int size ) Checks if the device’s screen is at least a given size.

TABLE 6.2 Constant values for the orientation field of the Configuration class

Constant Value
ORIENTATION_LANDSCAPE 2
ORIENTATION_PORTRAIT 1

TABLE 6.3 Constant values of the Configuration class related to a device’s screen size

Constant Value
SCREENLAYOUT_SIZE_UNDEFINED 0
SCREENLAYOUT_SIZE_SMALL 1
SCREENLAYOUT_SIZE_NORMAL 2
SCREENLAYOUT_SIZE_LARGE 3
SCREENLAYOUT_SIZE_XLARGE 4

TABLE 6.4 The getResources and getConfiguration methods

Class Method
Context Resources getResources( )
Resources Configuration getConfiguration( )

The Configuration class provides constants to use as an argument of the isLayoutSizeAtLeast method (listed in TABLE 6.3). The SCREENLAYOUT_SIZE_SMALL and SCREENLAYOUT_SIZE_NORMAL constants apply to smartphones, whereas SCREENLAYOUT_SIZE_LARGE and SCREENLAYOUT_SIZE_XLARGE apply to tablets.

Using these resources, we can detect information about the device that our app is running on when the app starts. In order to use these resources, we need a Configuration reference. Inside the Activity class, we can call the getResources method from the Context class (that Activity inherits from) to get a Resources reference for the application’s package. Using that Resources reference, we can call the getConfiguration method of the Resources class to obtain a Configuration reference. TABLE 6.4 lists these two methods.

Thus, inside an Activity class, we can use these two methods in order to obtain a Configuration object as follows:

Resources resources = getResources();
Configuration config = resources.getConfiguration();

We can also chain these two method calls as follows:

Configuration config = getResources().getConfiguration();

Using a modified HelloAndroid app, we demonstrate how we can retrieve device information in EXAMPLE 6.1. We retrieve the Configuration config reference for the current app environment at line 18. At lines 19–20, we output the height and width of the screen in density independent pixels (dp). To obtain the actual size, we need to multiply those values by the pixel density. Note that screenHeightDp stores the height of the screen excluding the status bar.

At lines 22–27, we retrieve the size of the screen in actual pixels and output its width and height. At lines 29–32, we retrieve and output the pixel density of the screen. Appendix A gives us a detailed explanation.

At lines 34–47, we test for the relative size of the screen and output it. Note that we test for the relative sizes in descending order. If we tested for “at least” a small screen first, it would always evaluate to true. We output the two constants ORIENTATION_LANDSCAPE and ORIENTATION_PORTRAIT of the Configuration class (2 and 1, respectively) at lines 49–52. At line 53, we output the orientation value of the device as an integer. At lines 54–59, we compare that value to the two previous constants and output the device’s orientation.

EXAMPLE 6.1 Obtaining information on the device running the app

FIGURE 6.1 shows the various parts of a device’s screen. In yellow is the device’s status bar. It typically includes some icons for system and application notifications, including the clock. In red is the app’s action bar, which typically includes the app name on the left and optional menu items on the right, although it can be different depending on the app. In blue is the app content View. This is where the contents of our app go. The visible display frame is made up of the app’s action bar (in red) and the app content View (in blue).

FIGURE 6.2 shows the output of Example 6.1 in Logcat when running using the emulator for the Nexus 5 started in vertical position. The output confirms that the device is in vertical position, that the screen of the device is 568 dp × 360 dp in that position and is considered a normal size screen. The orientation value is 1, equal to the portrait constant. The height dimension (568 dp) includes the action bar height but does not include the status bar height. The logical pixel density is 3; 568 dp is equivalent to 1,704 pixels (568 × 3), 72 pixels less than the 1,776 pixels screen height. The 72 pixels are equivalent to 24 dp, the height of the status bar.

If we rotate the emulator (Ctrl+F11), we notice more output, which means that the onCreate method executes again. Furthermore, the screen dimensions are different in horizontal orientation: the height is 336 dp and the width is 598 dp. The action bar height, 56 dp in vertical position, is only 48 dp in horizontal orientation. Furthermore, the Back and Home buttons are at the bottom of the screen in vertical orientation, but are to the right of the screen in horizontal orientation.

If we leave the emulator in horizontal position and restart the app, the output shows that we detect that the device is in the horizontal position.

If we run the app in the Nexus 4 emulator, we can see that the logical pixel density for the Nexus 4 is only 2, and the height and width are 568 dp and 384 dp, respectively.

FIGURE 6.1 View components of the screen

FIGURE 6.2 Logcat output of Example 6.1

6.2 Capturing a Device Rotation Event

The user could start an app in a given orientation but might rotate the device later. If we are building an app that works in both orientations, we need to code our app so that it will react properly to a change in device orientation. By default, the onCreate method of the Activity class is called when the user rotates the device. However, the onCreate method typically does more than just handling orientation changes. Thus, it could be a waste of CPU resources to let onCreate execute every time the user rotates the device.

The onConfigurationChanged method of the Activity class, shown in TABLE 6.5, is called automatically whenever the device’s configuration changes (e.g., when the user rotates the device), provided that we specify it in the AndroidManifest.xml file. In turn, the onCreate method is only called when the user starts the app and no longer called when the user rotates the device. The newConfig parameter of the onConfigurationChanged method represents the latest configuration of the device.

Inside the activity element for which we want to be notified if the device configuration changes, we need to add the android:configChanges attribute and assign to it the appropriate value or values. We can assign several values, separated by the | character. TABLE 6.6 shows selected values. If we want to be notified whenever the user rotates the device, we need to assign the value orientation to android:configChanges. However, starting with API level 13, we also need to add the value screenSize. Indeed, the system considers that the screen size changes when the user rotates the device. Thus, we need to specify the value orientation | screenSize for the android:configChanges attribute as follows (note that there is no space between orientation and |, and between | and screenSize):

<activity
  android:name=”.MainActivity”
  android:configChanges=”orientation|screenSize” >

Using another modified HelloAndroid app, we demonstrate how we execute inside the onConfigurationChanged method when the user rotates the device in EXAMPLE 6.2. We can use the newConfig parameter of that method (lines 16–28) to detect what orientation the device is in and code the appropriate changes for the app. In this simple app, we output screen size information at lines 18–19 and orientation information at lines 21–27.

TABLE 6.5 The onConfigurationChanged method of the Activity class

Method Description
void onConfigurationChanged(Configuration newConfig) Called when one of the configurations specified in the AndroidManifest.xml file has changed.

TABLE 6.6 Selected values for the android:configChanges attribute of the activity element

Attribute Value Meaning
orientation The user has rotated the device.
screenSize The size of the screen has changed.
locale The locale has changed (the user has selected a new language).
keyboard The keyboard type has changed.
fontScale The user has selected a new global font size.

EXAMPLE 6.2 Detecting configuration changes inside the onConfigurationChanged method

If we run the app starting in vertical position, there is no output until we rotate the device (Ctrl+F11) to the horizontal position. When we do, the first four lines of FIGURE 6.3 are output. When we rotate the device back (Ctrl+F12) to the vertical position, the next four lines of Figure 6.2 are output. We can see that the dimensions of the screen differ depending on the device’s orientation.

We now have the tools to detect orientation and screen dimensions whenever the user rotates the device. There are many possible ways to display the correct layout to the user, including:

  • ▸ Have one layout XML file per orientation and inflate it whenever the user rotates the device.

  • ▸ Have the same layout XML file for both orientations and modify the characteristics of some of the GUI components whenever the user rotates the device.

  • ▸ Manage layouts 100% by code and make the appropriate modifications whenever the user rotates the device.

FIGURE 6.3 Logcat output of Example 6.1

6.3 Strategy 1: One Layout XML File per Orientation

We already have one layout XML file, activity_main.xml, shown in EXAMPLE 6.3. We use it for the vertical orientation: we add a background color (green) to the TextView element at line 17 and modify the text displayed, using the String named portrait at line 18. We add another layout XML file, activity_main_landscape.xml, shown in EXAMPLE 6.4, which we use for the horizontal orientation. This time, we set the background color of the TextView element to red at line 17 and the text is displayed using the String landscape at line 18. The portrait and landscape Strings are defined at lines 3 and 4 of the strings.xml file in EXAMPLE 6.5. We also edit the styles.xml file, shown in EXAMPLE 6.6, so that the size of the text is large enough (line 3).

Now that the resource files are set, we code the MainActivity class. If the device is in the vertical position, we use the activity_main.xml file for the layout. If the device is in the horizontal position, we use the activity_main_landscape.xml file for the layout. Not only do we need to do this inside the onConfigurationChanged method, but we must also do this inside the onCreate method so that the proper layout file is used when the app starts. Indeed, the device could either be in horizontal or vertical position when the app starts. Since the same code will be run two times, we code a new method, modifyLayout (lines 20–25 of EXAMPLE 6.7), which we call from onCreate (line 12) and onConfigurationChanged (line 17). The modifyLayout method tests what the orientation of the device is, and sets the layout for it, inflating the appropriate XML file.

EXAMPLE 6.3 The activity_main.xml file, for portrait orientation

EXAMPLE 6.4 The activity_main_landscape.xml file, for landscape orientation

EXAMPLE 6.5 The strings.xml file

EXAMPLE 6.6 The styles.xml file

EXAMPLE 6.7 Managing orientation changes using two XML layout files

FIGURE 6.4 shows the app running inside the emulator when the device is in vertical position, and FIGURE 6.5 shows the app after we rotate the device to the horizontal position. If we place output statements to Logcat inside onCreate and onConfigurationChanged, we see that onCreate is only called when the app starts and is no longer called afterward when we rotate the device. Instead, onConfigurationChanged is called. As discussed earlier, this is because we added

android:configChanges=”orientation|screenSize”

inside the activity element in the AndroidManifest.xml file.

FIGURE 6.4 App running inside the emulator, starting in vertical position

FIGURE 6.5 App running inside the emulator, after rotating to horizontal position

6.4 Strategy 2: One Layout XML File for Both Orientations, Modify the Layout by Code

We now look at another strategy to control the layout depending on screen orientation. We use only one XML layout file but we modify the layout parameters of some of its components programmatically depending on the screen orientation. To better illustrate this, we modify the activity_main.xml, as shown in EXAMPLE 6.8. It displays three buttons (lines 10, 15, and 21) inside a LinearLayout (line 2). A LinearLayout organizes elements linearly, either horizontally or vertically depending on the value of its android:orientation attribute. In this app, we specify a vertical organization of its elements (line 6). If we keep the spacing constant between the buttons no matter the orientation of the screen, for example 50 pixels, it is possible that the app looks good in one orientation (vertical for example) but looks bad in the other orientation (horizontal). Instead, we can set the spacing between the buttons by code, depending on orientation. For this, we need to access the second and third buttons at run time, so we give them an id at lines 16 and 22. Lines 13, 19, and 25 specify the text of the three buttons using the view1, view2, and view3 Strings defined in the strings.xml file, shown in EXAMPLE 6.9. We use the same styles.xml file as the one in Example 6.6.

EXAMPLE 6.8 The activity_main.xml file

EXAMPLE 6.9 The strings.xml file

In order to make the app look good in both positions, we need to set the spacing between the buttons by code in the MainActivity class. If the device is in the vertical position, we set the spacing to 50 pixels, and if the device is in the horizontal position, we set the spacing to 25 pixels.

EXAMPLE 6.10 shows the new MainActivity class. This time, we inflate the XML inside the onCreate method. Like before, both onCreate and onConfigurationChanged call modifyLayout, which sets the spacing parameters between the buttons.

The modifyLayout method (lines 25–41) retrieves the second and third buttons at lines 26 and 29, and then retrieves their associated margin layout parameters at lines 27–28 and 30–31.

EXAMPLE 6.10 Managing orientation changes using two XML layout files

The Android framework includes layout parameter classes that we can use to set the layout parameters of the GUI components contained in a layout. The root class for those is ViewGroup.LayoutParams. It has many specialized subclasses relating to specialized ViewGroups, including TableLayout.LayoutParams, RelativeLayout.LayoutParams, LinearLayout.LayoutParams, or ViewGroup.MarginLayoutParams. The ViewGroup.MarginLayoutParams class (MarginLayoutParams is a public static inner class of ViewGroup) is used to set margins for GUI components.

TABLE 6.7 shows some XML attributes of ViewGroup.MarginLayoutParams, along with the corresponding method. Although there are four attributes, we can set them by using a single method, setMargins.

TABLE 6.7 Selected XML attributes of ViewGroup.MarginLayoutParams and the setMargins method

Attribute Name Related Method
android:layout_marginBottom setMargins( int left, int top, int right, int bottom )
android: layout_marginTop setMargins( int left, int top, int right, int bottom )
android: layout_marginLeft setMargins( int left, int top, int right, int bottom )
android: layout_marginRight setMargins( int left, int top, int right, int bottom )

FIGURE 6.6 App running in vertical position using 50 pixels between buttons

FIGURE 6.7 App running in horizontal position using 25 pixels between buttons

We test for orientation at lines 33 and 36–37 and set the top margin of the layout parameters of the two buttons at lines 34–35 or 38–39 depending on orientation. We use the two constants SPACING_VERTICAL and SPACING_HORIZONTAL defined at lines 10–11. The MarginLayoutParams, params2 and params3 are object references, so when we modify them, we automatically modify the layout parameters of the two buttons associated with them.

As we did earlier, we add

android:configChanges=”orientation|screenSize”

inside the activity element in the AndroidManifest.xml file.

FIGURES 6.6 and 6.7 show the app running inside the emulator when the device is in vertical position and horizontal position, respectively.

In this example, we hard coded the spacing between the buttons. As a result, the app may not look as good in some devices. In the next example, we set the spacing dynamically, relative to the dimensions of the device that the app is running on.

6.5 Strategy 3: Manage Layout and Orientation 100% by Code

In the previous example, we could have set up some dimen elements in the dimens.xml file to define several spacing values to go with different screen sizes. This strategy would work for most current devices, but may or may not work well for future devices. In order to have maximum flexibility and tailor the GUI to any screen size, we can control everything by code, without using any layout XML file. Instead of inflating a layout XML file, we call a method that sets up the layout programmatically. Additionally, we call another method that sets the layout parameters for the GUI components of the View. The basic principles of the previous example apply as far as managing orientations: each time the user rotates the device, onConfigurationChanged is called, and in turn it calls modifyLayout. This app is more complex, however, because we need to capture information related to the screen dimensions when the app starts in order to display the GUI components properly based on the starting orientation. Overall, we replace the layout XML file and the call to setContentView with a method setting up the GUI programmatically and a call to that method. Again, we use the same styles.xml file as the one in Example 6.6.

We need to display our buttons inside the app content View, the blue area of the screen in Figure 6.1. And we want our buttons to be equally distributed, whatever the orientation of the device, as shown in FIGURE 6.8.

FIGURE 6.8 Three buttons with equal spacing

If h is the height of the screen, a is the space between buttons, and b is the height of a button, we have (assuming we are using three buttons):

h = 4 * a + 3 * b

Therefore,

a = (h – 3 * b)/4

We can measure the dimensions of a View that has not been displayed yet by calling its measure method, and then its getMeasuredHeight method, shown in TABLE 6.8. If button is a Button reference, we can obtain its height as follows:

button.measure( LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT );
int buttonHeight = button.getMeasuredHeight();

In order to compute a, the space between the buttons, we need to calculate h, the height of the app’s content view, first. We can retrieve the height of the action bar as shown next. Once we have it, we can easily compute the height of the app content View. Appendix A provides detailed explanations.

// set default value for action bar height
int actionBarHeight = ( int ) ( pixelDensity * 56 );
TypedValue tv = new TypedValue( );
if(getTheme().resolveAttribute( android.R.attr.actionBarSize, tv, true ))
    actionBarHeight = TypedValue.complexToDimensionPixelSize( tv.data,
                                 getResources( ).getDisplayMetrics( ) );

TABLE 6.8 The measure and getMeasuredHeight methods of the View class

public void measure( int widthMeasureSpec, int heightMeasureSpec ) The two parameters are dimensional constraint information supplied by the parent of this View.
public int getMeasuredHeight( ) Returns the measured height of this View.

In Example 6.1, we learned how to retrieve the height of the screen minus the status bar. Thus, to compute the height of the content view, we do the following:

Retrieve the height of the screen minus the status bar: appScreenHeight
Retrieve the height of the action bar: actionBarHeight
Height of content view = appScreenHeight - actionBarHeight

EXAMPLE 6.11 shows a simple app whose View is defined by code and whose orientation changes are managed by code. As shown in Figure 6.8, the screen contains three buttons that are equally spaced vertically in both horizontal and vertical orientations. In addition to the three buttons, we also declare instance variables to store various dimensions: the height of the action bar, the height of the screen in both orientations, and the spacing between the buttons. We also declare two boolean state variables, verticalDimensionsSet and horizontalDimensionsSet (lines 20 and 24), so that we only set all these variables once and not every time the device changes orientation. Some of these variables are declared as public and static so they can be easily accessed from other activities if necessary—most likely, if we have other activities in the app, we will need to access these values in other activities for the same reason that we need to access them in this activity, and we do not want to rewrite the same code to retrieve them.

EXAMPLE 6.11 Managing orientation by code only

The onCreate method (lines 31–40) calls setUpGui at line 33. The setUpGui method is coded at lines 70–94: it sets up the layout manager for the View, creates the buttons, and adds them to the View. In order to retrieve the action bar height, the screen dimensions, and to calculate the space between the buttons, we call a separate method, checkDimensions, at line 38. At line 39, we call modifyLayout, which displays the buttons properly depending on the orientation of the device. Since we do not know what orientation the device is in when the app starts, we assign the current configuration to the variable config at line 37 and pass config to checkDimensions and modifyLayout.

Inside setUpGui, we declare and instantiate linearLayout, a LinearLayout, at line 71 and set its orientation to vertical at line 72. This means that the buttons inside it are arranged vertically. We set its gravity to vertical at line 73. That means that the buttons inside it are centered vertically. We instantiate the three buttons at lines 75–77 and set their respective texts at lines 79–81. We instantiate a LayoutParams object at lines 83–84 and use it to set the layout parameters to WRAP_CONTENT for all three buttons at lines 85–87. We add the buttons to linearLayout at lines 89–91 and set the content view of this activity to linearLayout at line 93. The setUpGui method does not set the space between the buttons because that value depends on the device orientation. Thus, we want to set it when the onConfigurationChanged method is called and also when the app starts. We code a separate method, setLayoutMargins, to do that at lines 103–114. That method accepts one parameter, the space between two buttons. Depending on the position of the device, we pass a different value for that parameter when calling that method.

The checkDimensions method (lines 42–68) retrieves the action bar height and assigns values to the various dimension-related instance variables. We only want to do that twice: when the app starts, and after the user has rotated the device the first time. Thus, inside onConfigurationChanged, we only call checkDimensions if either verticalDimensionsSet or horizontalDimensionsSet is false (line 98). The checkDimensions method retrieves the height of the action bar, and the height of the screen in both orientations. We assign them to the instance variables actionBarHeight, screenHeightInHP, and screenHeightInVP. We also retrieve the height of the buttons (lines 52–54) and calculate the values of spacingInHP and spacingInVP at lines 59–60 and 64–65. We output the value of the action bar height at line 50 for feedback purposes. FIGURE 6.9 shows the output after we start the app in vertical orientation and rotate the device. The height of the action bar is 168 pixels (56 dp) and 144 pixels (48 dp) in vertical and horizontal orientations, respectively.

Earlier in the chapter, we showed that the height of the screen, not including the status bar, is 1,704 pixels (568 dp × 3) and 1,008 pixels (336 dp × 3) in vertical and horizontal orientations, respectively. Thus, the height of the app content view for our emulator is 1,536 pixels (1,704 – 168) in vertical orientation, and 864 pixels (1,008 – 144) in horizontal orientation as shown in FIGURES 6.10 and 6.11.

FIGURE 6.9 Logcat output of Example 6.11

FIGURE 6.10 Heights in vertical orientations for the Nexus 5 emulator

FIGURE 6.11 Heights in horizontal orientations for the Nexus 5 emulator

The modifyLayout method, coded at lines 116–121, tests the orientation of the device (lines 117 and 119) and calls the setLayoutMargins method with the appropriate argument (lines 118 and 120), either spacingInHP or spacingInVP.

The onConfigurationChanged method is coded at lines 96–101. If the values of the various instance variables have not been set yet (line 98), we call checkDimensions (line 99). This will happen only once, the first time the user rotates the device. Currently, the action bar height is the same in both orientations. If this changes in the future, the code in this Example will need to be modified. At line 100, we call modifyLayout so that the buttons are displayed according to the device orientation.

The setLayoutMargins method is coded at lines 103–114. We first retrieve MarginLayoutParams references params1, params2, and params3 to the three buttons at lines 104–109. We then call setMargins at lines 111–113, passing spacing as its second argument, in order to set the y-coordinate of the top of each button. Remember that the params1, params2, and params3 are object references, so when we modify them, we modify the layout parameters of the three buttons.

Finally, remember that since we want the onConfigurationChanged method to be called when the user rotates the device, we need to add the android:configChanges attribute of the activity element in the androidManifest.xml file:

<activity
    android:name=”.MainActivity”
  android:configChanges=”orientation|screenSize” >

If we run the app and rotate the device, the vertical and horizontal Views look like the ones in Figures 6.6 and 6.7, with the buttons evenly spaced in both orientations.

At the time of this writing, the height of the status bar is 24 dp in both orientations. If necessary, it can be retrieved by code as follows (Appendix A provides detailed explanations):

// set default value for status bar height
int statusBarHeight = ( int ) ( pixelDensity * 24 );
// res is a Resources reference
int resourceId =
    res.getIdentifier( ”status_bar_height”, ”dimen”, ”android” );
    // res.getIdentifier( ”android:dimen/status_bar_height”, ””, ”” );
if( resourceId != 0 ) // found resource for status bar height
  statusBarHeight = res.getDimensionPixelSize( resourceId );

Chapter Summary

  • It is possible to build an app that runs in both orientations: we can have two separate layout XML files, combine one layout XML file with some code to handle both orientations, or manage both the layout and orientation programmatically.

  • The Configuration class includes resources to access device information such as its keyboard, locale, orientation, screen dimensions, and many others. It also includes a method and constants to test if the current device is at least a certain size.

  • The getResources and getConfiguration methods can be used to obtain a Configuration reference representing the current device configuration.

  • The onConfigurationChanged is called automatically when the user rotates the device, provided that the android:onChanges attribute is defined inside the activity element of the AndroidManifest.xml file.

  • In order to detect a change in orientation, the value of android:onChanges should be orientation|screenSize.

  • The LayoutParams class and its subclasses can be used to set the various layout parameters of a GUI component.

  • When an app is running, the screen is typically divided into three parts: the status bar at the top, the action bar (which may include other GUI components in addition to the app name), and the app’s content view. Their respective heights can be retrieved programmatically.

  • At the time of this writing, the height of the status bar is 24 dp and is the same in vertical and horizontal orientation.

  • At the time of this writing, the height of the action bar is 56 dp and 48 dp in vertical and horizontal orientations, respectively.

  • Appendix A provides detailed explanations on how to retrieve the heights of the status bar and action bar.

Exercises, Problems, and Projects

Multiple-Choice Exercises

  1. In what package is the Configuration class?

    • android.config

    • android.configuration

    • android.content

    • android.content.res

  2. In what class is the getConfiguration method?

    • Configuration

    • Resources

    • Activity

    • Context

  3. The getResources method

    • Can be called from the Activity class because Activity inherits it from Context

    • Cannot be called from the Activity class

    • Is automatically called by the system

    • Is called by a Configuration reference

  4. ORIENTATION_PORTRAIT and ORIENTATION_LANDSCAPE

    • Are constants of the Resources class

    • Are constants of the Activity class

    • Are constants of the Configuration class

    • Are constants of the View class

  5. The name of the instance variable of the Configuration class that stores the value of the device orientation is

    • config

    • name

    • position

    • orientation

  6. The screenHeightDp instance variable of the Configuration class stores (in dp units)

    • the height of the status bar

    • the height of the whole screen, including the status bar

    • the height of the whole screen, excluding the status bar

    • the height of the whole screen, excluding the status bar and the action bar

  7. What method is automatically called when the user rotates the device, provided the AndroidManifest.xml file is correctly coded?

    • onConfigurationChanged

    • onRotate

    • onChange

    • onRotation

  8. For the method in question 7 to be called automatically when the user rotates the device, what attribute needs to be set in the AndroidManifest.xml file?

    • android:changes

    • android:configChanges

    • android:rotate

    • android:onRotate

  9. The height of the status bar

    • cannot be retrieved programmatically

    • can be retrieved programmatically

    • is currently equal to 20 pixels

    • is always different in vertical and horizontal orientations

  10. Margins around a GUI component

    • Must be set in the layout xml file—they cannot be set by code

    • can be set using the setMargins method of the View class

    • can be set using the setMargins method of the MarginLayoutParams class

    • can be set using the setMargins method of the Activity class

Fill in the Code

  1. Write the code to get a Configuration reference.

  2. Write the code to retrieve the width of the screen in pixels.

  3. Write the code to retrieve the width of the screen in dp.

  4. Write the code to output to Logcat the current orientation of the device.

  5. Write the code to test if a device has an extra large screen and output the result to Logcat.

  6. Write the code to test if a device has a screen that is considered at least large but not extra large and output the result to Logcat.

  7. Write the code to set the view to be inflated from portrait.xml if the device is in vertical position and from landscape.xml if the device is in horizontal position. Assume that you already have a Configuration reference.

  8. Write the code to retrieve the height of the action bar in pixels.

  9. Write the code to output to Logcat the width and height of a TextView named label.

    /* Assume that the TextView label has been instantiated and has
    been added to the View */
    // Your code goes here
    
  10. Write the code to set the margins of a button to 30 pixels on the left and 50 pixels on the right.

    /* Assume that the Button myButton has been instantiated and has
    been added to the View */
    MarginLayoutParams params =
      ( MarginLayoutParams ) myButton.getLayoutParams( );
    // Your code goes here
    

Write an App

  1. Write an app that works in both vertical and horizontal orientations using two layout XML files: the app asks the user to enter the result of an addition and checks the answer. Use randomly generated integers between 0 and 20 for the operands of the addition. Include a Model. The GUI should look nice in both orientations.

  2. Write an app that works in both vertical and horizontal orientations. The app is a variety of the game of nim. Two players take turns removing identical objects from a set of objects. A player can remove one, two, or three objects at a time. The player who takes the last object loses. You can store the current number of objects in a TextView and get user input via an EditText. Include a Model. Generate randomly the starting number of objects, an integer between 10 and 20. The GUI should look nice in both orientations.

  3. Write an app that works in both vertical and horizontal orientations using two layout XML files. The app is a simple calculator: the user can click on buttons showing digits from 1 to 9, click on buttons displaying +, -, and *, and the app shows the result. Include a Model. The GUI should look nice in both orientations. Use one color theme for an orientation, and another color theme for the other orientation.

  4. Write an app that works in both vertical and horizontal orientations using two layout XML files. The app is a tip calculator: the user can enter a restaurant bill, a number of guests, and a tip percentage, and the app shows the total tip, the total amount, the tip per guest, and the total per guest. Include a Model. The GUI should look nice in both orientations.

  5. Write an app that works in both vertical and horizontal orientations. The app is a tic-tac-toe game. Include a Model. The GUI should look nice in both orientations. Use Xs and Os in one orientation, and As and Zs in the other orientation.

  6. Write an app that works in both vertical and horizontal orientations. The app displays a chessboard in its starting position. Include a Model. The GUI should look nice in both orientations. Use black and white colors in one orientation, and two other colors in the other orientation. In vertical position, position the chessboard at the top of the screen, using the full width of the screen. In horizontal position, position the chessboard in the middle of the screen, using the full height of the screen. Use chars to represent the various pieces (K for King, Q for Queen, etc.).

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
44.200.94.150