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;
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.
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.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.
3.12.154.172