APPENDIX A: Retrieving the Height of the Status Bar and the Action Bar Dynamically

Chapter opener image: © Fon_nongkran/Shutterstock

If we define a View programmatically, we often need to retrieve the height of the content view, which is the total height of the screen minus the heights of the status bar and the action bar.

FIGURE A.1 shows the various parts of a device’s screen. The device’s status bar is shown in yellow: 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 top left and a menu on the right, although it can be different depending on the app. The app content View is shown in blue. 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).

At the time of this writing, and according to Google’s design guidelines, the height of the status bar is 24 dp and the height of the action bar is 56 dp. These numbers are given in density independent pixels, so in order to compute the actual number of pixels, we need to multiply them by the logical pixel density of the device. There is no guarantee that the height of the status and action bars will not change in the future. Thus, it is better to retrieve them programmatically.

The following code sequence shows how to retrieve the logical pixel density of a device.

Resources res = getResources( );
DisplayMetrics metrics = res.getDisplayMetrics( );
float pixelDensity = metrics.density;

FIGURE A.1 View components of the screen

We first obtain a Resources reference by calling the getResources method inherited from the ContextWrapper class by the Activity class. We can use the Resources class to access the app’s resources. Using the Resources reference res, we call the getDisplayMetrics method to obtain a DisplayMetrics reference for the device. The DisplayMetrics class contains information about the display, including its size, its density, and font scaling. The density field of the DisplayMetrics class stores the logical pixel density of the device. TABLE A.1 shows the getResources method from the ContextWrapper class, the getDisplayMetrics from the Resources class, and the density field from the DisplayMetrics class.

TABLE A.1 The getResources, getDisplayMetrics methods, and the ensity field of DisplayMetrics

Class Method or field Description
ContextWrapper Resources getResources( ) Returns a Resources reference for this app’s package.
Resources Display getDisplayMetrics( ) Returns the display metrics for this Resources object.
DisplayMetrics density The scaling factor for the density independent pixel unit.

Once we have the density of the device, we can assign a default value to the action bar height and the status bar height as follows:

int actionBarHeight = ( int ) ( pixelDensity * 56 );
int statusBarHeight = ( int ) ( pixelDensity * 24 );

Now that we have a default value for the action bar height, we can attempt to retrieve its value dynamically using the following sequence. If we are not successful, we use the action bar default value.

//   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( ) );

The height of the action bar is part of the theme of the app. The getTheme method, shown in TABLE A.2, inherited from ContextThemeWrapper by Activity, returns the Theme associated with the current Context. Theme is an inner class of the Resources class: it stores the attribute values for a particular theme. The resolveAttribute method of the Theme class, shown in TABLE A.3, checks if an attribute is present in a theme. If it is, it returns true and assigns the attribute value to its TypedValue parameter, the second one. The resource id for the action bar height is android.R.attr.actionBarSize. We declare and instantiate a TypedValue reference, tv, for the purpose of passing it as the second argument to the resolveAttribute method. If the method returns true, we assign its value to actionBarHeight. We use the complexToDimensionPixelSize static method of the TypedValue class, shown in TABLE A.4, to convert the data inside tv, tv.data, to an integer representing its number of pixels. If we output the type of tv, tv.type, we can see that its value is 5, the value of the TYPE_DIMENSION constant of the TypedValue class.

TABLE A.2 The getTheme method of the ContextThemeWrapper class

Resources.Theme getTheme( ) Returns the Theme associated with the current Context.

TABLE A.3 The resolveAttribute method of the Resources.Theme class

boolean resolveAttribute( int resourceId, TypedValue outValue, boolean resolveRefs ) Returns true if the attribute resourceId is present in this Theme. If it is, it assigns its value to outValue; resolveRefs is used to determine the type of resource of the attribute.

TABLE A.4 Resources of the TypedValue class

public int data The data in this TypedValue.
public int type The type of data in this TypedValue.
static int complexToDimensionPixelSize( int data, DisplayMetrics metrics ) Returns the number of pixels corresponding to data using metrics as the display metrics. The type of data must be TYPE_DIMENSION (value 5)

To retrieve the value of the status bar height dynamically, we use the following sequence. If we are not successful, we use the status bar default value.

// 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 );

We can get the id of a resource given its name and the type of resource it is by calling the getIdentifier method of the Resources class shown in TABLE A.5. If the value returned is not 0, we have successfully retrieved it. We can then obtain its dimension by calling the getDimensionPixelSize method of Resources, passing the id value. Table A.5 also shows that method.

TABLE A.5 The getIdentifier and getDimensionPixelSize methods of the Resources class

int getIdentifier( String name, String type, String package ) Returns the resource id for the resource named name; type specifies the type of the resource (color, dimen, etc.), and package is the package that the resource is in. Both type and package are optional if name includes them (i.e., is a String like “package:type/resourceName”). Returns 0 if not found.
int getDimensionPixelSize( int id ) Returns the number of pixels of a resource whose id is id.

EXAMPLE A.1 shows the MainActivity class for a simple app that retrieves the status bar and action bar heights.

EXAMPLE A.1 The MainActivity class, showing how to retrieve the status bar and action bar heights of the current device

FIGURE A.2 shows the output of Example A.1 when running in the Nexus 5 emulator. The retrieved action bar height, 168, is equal to 3 (the pixel density) times 56 (the height given by Google for the action bar in dp units). The retrieved status bar height, 72, is equal to 3 (the pixel density) times 24 (the height given by Google for the status bar in dp units).

FIGURE A.2 The output of Example A.1 for the Nexus 5 emulator

FIGURE A.3 The output of Example A.1 for the Nexus 4 emulator

FIGURE A.3 shows the output of Example A.1 when running in the Nexus 4 emulator. The retrieved action bar height, 112, is equal to 2 (the pixel density) times 56 (the height given by Google for the action bar in dp units). The retrieved status bar height, 48, is equal to 2 (the pixel density) times 24 (the height given by Google for the status bar in dp units). We can verify that the resource id is the same as for the Nexus 5 emulator.

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

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