Android Tips, Techniques and Theory
PART 1: Creating Content with XML with Android Studio (No programming required)
With Simple Recipes
Go Back To TOC
GUI Techniques
Qualify Resources
You can use qualify resources to declare specific resources for various things with Android:
- Screen sizes
- Screen densities
- Screen orientations
- Device languages
- Platform versions
- Country codes
- UI modes
By using qualify resources for specific purposes, you can tell Android OS to use the string constants as needed based on these qualifiers at runtime. It also allows for multi-languages supports.
Qualify Resource Examples:
- Different graphics (drawable folder) resources based on screen resolution density
- Drawable - default graphics
- Drawable-hdpi – graphics for high dpi devices
- Different string constant (strings folder) resources based on the user’s locale.
- values/strings.xml – default locale string resources
- value-es/strings.xml – string resources for Spanish
- value-fr/strings.xml – string resources for French
- String resources are defined as integers in the values folder which has several xml files:
Customizing Component States
You can create custom states for a button or other components by creating a series of XML selector files to represent the various states. This is also called State List Drawable which, as the name implies, is a list of states. A StateListDrawable is a drawable object defined in XML that uses several different images, colors, or gradients to represent the various “states” of a component (e.g., button). Depending upon the component, states include:
- Normal
- Pressed
- Focus
- Enabled / Disabled
- Checked / Unchecked
Each state is represented by an <item> element inside of their parent <selector> element.
SYNTAX:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
android:constantSize=["true" | "false"]
android:dither=["true" | "false"]
android:variablePadding=["true" | "false"] >
<item
android:drawable="@[package:]drawable/drawable_resource"
android:state_pressed=["true" | "false"]
android:state_focused=["true" | "false"]
android:state_hovered=["true" | "false"]
android:state_selected=["true" | "false"]
android:state_checkable=["true" | "false"]
android:state_checked=["true" | "false"]
android:state_enabled=["true" | "false"]
android:state_activated=["true" | "false"]
android:state_window_focused=["true" | "false"] />
</selector>
NOTE: You set either the true or the false option for each state. For example, if the state is enabled then choose “true” and if the state is disabled then choose “false” as the option.
SELECTOR ELEMENT:
- <selector>—Required. Must be the root element that contains one or more <item> elements.
SELECTOR ATTRIBUTES:
Except for the namespace (e.g., xmlns:android) attribute, the other attributes accept a Boolean value (true or false).
- xmlns:android—String. Required. Defines the XML namespace which must be "http://schemas.android.com/apk/res/android".
- android:constantSize—"true" if the drawable's reported internal size remains constant as the state changes (will take the size of the largest drawable and use it for all states); "false" if the size varies based on the current state (default)
- android:dither—"true" to enable dithering of the bitmap if the bitmap does not have the same pixel configuration as the screen (for instance, an ARGB 8888 bitmap with an RGB 565 screen) (default); "false" to disable dithering. android:variablePadding—"true" if the drawable's padding should change based on the current state that is selected; "false" if the padding should stay the same (based on the maximum padding of all the states). Enabling this feature requires that you deal with performing layout when the state changes, which is often not supported (default).
ITEM ELEMENT:
- <item>— Required. Defines a drawable to use during certain states, as described by its attributes. Must be a child of a <selector> element.
ITEM ATTRIBUTES:
Except for the drawable attribute (e.g., android:drawable), the other attributes accept a Boolean value (true or false).
- android:drawable—Required. Reference a drawable resource.
NOTE: Each of the state is prefixed with android: which is not shown in the table to avoid redundancy and to save space.
State |
True-if item is used when the object: |
False-if item is used when the object: |
state_pressed |
is pressed (e.g., when a button is touched/clicked) |
is in the non-pressed state (default) |
state_focused |
has input focus (e.g., when the user selects a text input) |
Is in the non-focused state (default) |
state_hovered |
is being hovered over by a cursor |
Is in the non-hovered state (default) |
state_selected |
is the current user selection when navigating with a directional control |
is not selected. |
state_checkable |
is checkable |
is not checkable |
state_checked |
is checked |
is un-checked |
state_enabled |
is enabled |
is disabled |
state_activated |
is activated as the persistent selection |
is not activated |
state_window_
focused |
app window is in the foreground |
app window is in the background (e.g., notification shade is pulled down or a dialog appears) |
NOTE: Often, the hovered drawable may use the same drawable as the focused state.
CAUTION: During each state change, the state list is traversed top to bottom and the first item that matches the current state is used—the selection is not based on the "best match" but simply the first item that meets the minimum criteria of the state. As a result, like CSS rules, it is best to place the DEFAULT state LAST in the list of <item> elements.
EXAMPLE 1:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- pressed state -->
<item android:state_pressed="true" android:drawable="@drawable/button_pressed" />
<!-- focused state -->
<item android:state_focused="true" android:drawable="@drawable/button_focused" />
<!-- hovered state -->
<item android:state_hovered="true" android:drawable="@drawable/button_focused" />
<!-- default state -->
<item android:drawable="@drawable/button_normal" />
</selector>
This layout XML applies the state list drawable to a Button:
<Button
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:background="@drawable/button" />
EXAMPLE 2:
In this example, we will force a checkbox to behave like a star rating widget with various states implemented.
- Select File > New > New Project and give the app a name of Star Rating App. In the dialog box that appears, select Phone and Tablet and then click the Next button.
- Select the Empty Activity template and then click on the Next button and then the Finish button.
- Copy the various states images into the appropriate drawable folder (e.g., drawable-xhdpi).
Notes states included in this example:
Order |
Image |
State |
Comment |
1 |
|
Star_rating_unchecked.png |
Initial state |
2 |
|
Star_rating_checked.png |
When star is clicked on and released |
3 |
|
Star_rating_checked_and_pressed.png |
When star is pressed but is already checked |
4 |
|
Star_rating_unchecked_and_pressed.png |
When star is unchecked and is being pressed on |
5 |
|
Star_rating_unchecked_and_focused.png |
When star is unchecked and is receiving tab focus |
6 |
|
Star_rating_checked_and_focused.png |
When star is already checked and is receiving tab focus |
- Delete the default text component (Hello, World).
- Drag-and-drop a checkbox component to the center of the layout and remove the Text property.
- Create a stateless drawable file by right-clicking on the drawable folder and select New > Drawable > Drawable Resource file and in the dialog box that appears, give the file a name (e.g., custom_rating and a Root Tag name of Selector and then click the OK button.
- In the custom_rating.xml file add the following highlighted code:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:drawable ="@drawable/star_rating_checked" />
<item android:state_checked="false" android:drawable ="@drawable/star_rating_unchecked" />
</selector>
- Click on the checkbox and in the Properties panel, scroll down to the Button property, click on the elliptical button and in the Resource dialog box that appears, click on the Project tab, expand the drawable category and select custom_rating.
NOTE: The property you used for the custom state depends on the type of component. For example, for a button, you used the background property; whereas, for a checkbox, you use the button property.
- CHECK POINT: Run the app in an emulator, and click on the star rating image to see how it changes from the checked to the unchecked state each time you click on it. These are the two basic states. In the upcoming steps, additional states will be added.
- Add the following two highlighted items to the star_rating.xml file in the correct order:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:state_checked="true" android:drawable="@drawable/star_rating_checked_and_pressed"/>
<item android:state_pressed="true" android:state_checked="false" android:drawable="@drawable/star_rating_unchecked_and_pressed"/>
<item android:state_checked="true" android:drawable ="@drawable/star_rating_checked" />
<item android:state_checked="false" android:drawable ="@drawable/star_rating_unchecked" />
</selector>
NOTE: It is important to note that the pressed state comes BEFORE the checked state.
- CHECK POINT: Run the app in an emulator, and click on the star rating image to see how it changes from the checked to the unchecked state each time you click on it. Press the star without releasing to see the pressed but unchecked state. With the star_rated checked, press it AGAIN to see the pressed with already checked state.
- Add the following two highlighted items to the star_rating.xml file in the correct order:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:state_checked="true" android:drawable="@drawable/star_rating_checked_and_focused"/>
<item android:state_pressed="true" android:state_checked="true" android:drawable="@drawable/star_rating_unchecked_and_focused"/>
<item android:state_pressed="true" android:state_checked="true" android:drawable="@drawable/star_rating_checked_and_presses"/>
<item android:state_pressed="true" android:state_checked="false" android:drawable="@drawable/star_rating_unchecked_and_pressed"/>
<item android:state_checked="true" android:drawable ="@drawable/star_rating_checked" />
<item android:state_checked="false" android:drawable ="@drawable/star_rating_unchecked" />
</selector>
NOTE: It is important to note that the focus state comes AFTER the pressed state but BEFORE the checked states.
- CHECK POINT: Run the app in an emulator, and press the D-pad to see how it changes states as it receive focus.
EXAMPLE 3:
In this example, we will create a custom button with various states implemented.
- Select File > New > New Project and give the app a name of Custom Button App. In the dialog box that appears, select Phone and Tablet and then click the Next button.
- Select the Empty Activity, click on the Next button and then the Finish button.
- Copy the various states images into the appropriate drawable folder (e.g., drawable).
Notes states included in this example:
Image |
State |
Comment |
|
custom_button_normal.png |
Initial state |
|
custom_button_enabled.png |
When the button is clicked on |
|
custom_button_disabled.png |
When the button is disabled (programmatically) |
- Delete the default text component (Hello, World).
- Drag-and-drop an Image Button component to the center of the layout.
- Create a stateless drawable file by right-clicking on the drawable folder and select New > Drawable > Drawable Resource file and in the dialog box that appears, give the file a name (e.g., custom_button and a Root Tag name of Selector and then click the OK button.
- In the custom_button.xml file add the following highlighted code:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="@drawable/custom_button_enabled"/>
<item android:state_enabled="false" android:drawable="@drawable/custom_button_disabled"/>
<item android:drawable="@drawable/custom_button_normal" />
</selector>
NOTE: Notice that the default state does not have a state property.
- Click on the button and in the Properties panel, scroll down to the Background property, click on the elliptical button and in the Resource dialog box that appears, click on the Project tab, expand the drawable category and select custom_button.
NOTE: The property you used for the custom state depends on the type of component. For example, for a button, you used the background property; whereas, for a checkbox, you use the button property.
- CHECK POINT: Run the app in an emulator and click on the button to see how it changes state each time you click on it. These are the two basic states. In the upcoming steps, we will disable the button programmatically because imageButtton does not respect the XML attributes.
- Add the following two highlighted code in the MainActivity.java file:
public class MainActivity extends AppCompatActivity {
private ImageButton disableButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
disableButton = (ImageButton) findViewById(R.id.imageButton);
disableButton.setEnabled(false);
}
}
- CHECK POINT: Run the app in an emulator. You should see the disabled button state.
Nine-Patch
There are times when you will want to use a SINGLE image that can scale without distortion. This is accomplished by a process called Nine-Patch.
Material Design
Introduced in version 5 (Lollipop), Material Design is a complete guide for visual, motion and interaction design across multiple platforms (app, Bootstrap) and devices and it has some backward compatible with older versions of Android using the AppCompat v21 support library. To find more information about Material Design, go to http://www.google.com/design/spec/style/color.html or https://www.materialpalette.com.
- z property – to represent the view elevation
- smooth transitions – between screens and other UI components
- color palettes – predefined colors for UI elements
There are a series of XML file that are responsible for creating the themes:
- styles.xml (where you can overwrite properties from its parent theme)
- values.xml (automatically generated by the SDK)
- colors.xml (defines the colors for the theme)
There are two themes in the AndroidManifest.xml. One for the app (e.g., @style/AppTheme) and one for the default activity (e.g., @style/AppTheme.NoActionBar).
To see these themes CTRL+CLICK on either of them to open a resource file name styles.xml in the values folder that will show each of the theme within style tags. However, you will also see a comment to where you can customize your theme.
The styles.xml inherits properties from its parent (e.g. Theme.AppCompat.Light.DarkActionBar). If you CTRL+CLICK on it, you will see the values.xml file that was automatically generated by the SDK. You don’t want to edit this file; however, like CSS, you can overwrite properties in this file by modifying the styles.xml file. In fact, the first three <item> tags in the styles.xml are overwriting colors (e.g., colorPrimary, colorPrimaryDark, colorAccent) in the values.xml:
- colorPrimary is used to define the background color of the ActionBar.
- colorPrimaryDark is used to define background color of the SystemBar at the very top of the device where the system icons are displayed.
- colorAccent is used to define
Like the values.xml, if you CTRL+CLICK on a resource color (e.g., @color/colorPrimary) in the styles.xml, it will open the colors.xml file where you can see where the colors were defined.
EXAMPLE: Change Theme Colors
- Go to the colors.xml file and change any of the color elements to a new hexadecimal value (e.g., #3F5185 to #0000FF).
NOTE: You can see a preview of the color in the left margin of the screen as a small square color swatch.
<color name=“colorPrimary”>#0000FF</color>
<color name=“colorPrimaryDark”>#000000</color>
<color name=“colorAccent”>#FF4081</color>
- Run the app in an emulator or a real device and you will see the color changes.