Build applications using components with the HMRC look and feel.
First add Bintray to the list of repositories in build.gradle:
repositories {
maven {
url "https://dl.bintray.com/hmrc-mobile/mobile-releases"
}
}Then add the following to your list of dependencies:
implementation 'uk.gov.hmrc.components:components:{version}'
androidTestImplementation 'uk.gov.hmrc.components:components-test:{version}'The latest release can be found here.
Changing your app theme to inherit from Theme.Components or Theme.Components.ActionBar is the recommended approach:
<style name="Theme.MyApp" parent="@style/Theme.Components">
...
</style>If you cannot change your theme to inherit from Theme.Components, inherit from a Material Components theme and set the following attributes:
<style name="Theme.MyApp" parent="@style/Theme.MaterialComponents.DayNight">
<item name="colorError">@color/hmrc_red</item>
<item name="materialTextButtonStyle">@style/MaterialTextButtonNoInset</item>
<item name="materialIconButtonStyle">@style/MaterialTextIconButtonNoInset</item>
<item name="materialCardViewStyle">@style/Widget.Components.CardView</item>
</style>Components fall into one of three types:
- Atoms - individual UI element (e.g. label, button)
- Molecules - reusable combination of atoms (e.g. Body label + H3 label)
- Organisms - complex view, with multiple molecules and/or atoms, may contain functionality (e,g, Headline Card pictured)
<uk.gov.hmrc.components.atom.button.PrimaryButton
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Primary Button" /><uk.gov.hmrc.components.atom.button.SecondaryButton
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Secondary Button" /><uk.gov.hmrc.components.atom.button.IconButton
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Icon Button"
app:icon="@drawable/icon" /><TextView
style="@style/Text.H3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="H3 Text" />A H3 styled TextView identified as a visual heading for accessibility purposes.
<uk.gov.hmrc.components.atom.header.Heading3
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Heading3 Text" /><TextView
style="@style/Text.H4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="H4 Text" />A H4 styled TextView identified as a visual heading for accessibility purposes.
<uk.gov.hmrc.components.atom.header.Heading4
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Heading4 Text" /><TextView
style="@style/Text.H5"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="H5 Text" />A H5 styled TextView identified as a visual heading for accessibility purposes.
<uk.gov.hmrc.components.atom.header.Heading5
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Heading5 Text" /><TextView
style="@style/Text.Bold"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Bold Text" /><TextView
style="@style/Text.Body"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Body Text" /><TextView
style="@style/Text.Info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Info Text" /><TextView
style="@style/Text.Link"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Link Text" /><TextView
style="@style/Text.Error"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Error Text" /><uk.gov.hmrc.components.atom.bullet.BulletedTextView
style="@style/Text.Body"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Bullet Text" /><View style="@style/Divider" />or
@drawable/divider if you need a drawable resource
A view with an inset on the left side. Nest content inside of this view to display it on the right side of the inset
<uk.gov.hmrc.components.molecule.inset.InsetView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!-- Nested content goes here -->
</uk.gov.hmrc.components.molecule.inset.InsetView>A preconfigured version of Inset View, where a nested text view is ready for immediate use via the xml text attribute
<uk.gov.hmrc.components.molecule.inset.InsetTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:text="@string/inset_text" /><uk.gov.hmrc.components.molecule.item.MultiColumnRowView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:text1="@string/text1"
app:text2="@string/text2"
app:text3="@string/text3"
app:text1ContentDescription="@string/text1_desc"
app:text2ContentDescription="@string/text2_desc"
app:text3ContentDescription="@string/text3_desc"
app:text1IsSelectable="false"
app:text2IsSelectable="true"
app:text3IsSelectable="true"
app:textStyle="@style/Text.Body"
app:textStyle2="@style/Text.Body"
app:textStyle3="@style/Text.Bold"
app:text1Heading="true" />This component can display a row with one, two or three columns of equal spacing, using the number of strings you provide.
The text style and heading can also be configured programmatically:
multi_column_row.setTextStyle(R.style.Text_Bold)
multi_column_row.setText1AsHeading(true)<uk.gov.hmrc.components.molecule.input.TextInputView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:text="@string/text"
app:overrideHintContentDescription="@string/content_description"
app:counterEnabled="true"
app:counterMaxLength="@integer/max_length"
app:hintText="@string/hint_text" />TextInputView represents an input for text. This includes the following features:
- Hint text
- Custom content description
- Max length limits
- Character counters
<uk.gov.hmrc.components.molecule.input.CurrencyInputView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:text="@string/text"
app:contentDescription="@string/content_description"
app:counterEnabled="true"
app:counterMaxLength="@integer/max_length"
app:hintText="@string/hint_text"
app:decimalEnabled="false" />CurrencyInputView represents an input for currency. This includes the following features:
- Prefix text for currency
- Preset keyboard input for currency
- Preset disabled character counters
- Hint text
- Custom content description
- Max length limits
- Enable or disable decimals
<uk.gov.hmrc.components.molecule.item.SwitchRowView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:title="@string/title"
app:body="@string/body"
app:showBody="true"
app:checked="true"
app:switchContentDescription="@string/content_description" />This component can display a row with a title, body and a switch.
The body can be hidden by calling showBody(false) - it is visible by default.
You can set a listener for when the switch state has changed by calling:
setCheckedChangedListener()
Example usage:
switch_row_example_1.setEnabledListener { Toast.makeText(context, "Example 1 state: $it", Toast.LENGTH_SHORT).show() }<uk.gov.hmrc.components.molecule.header.H4TitleBodyView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:title="@string/title"
app:body="@string/body" /><uk.gov.hmrc.components.molecule.header.H5TitleBodyView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:title="@string/title"
app:body="@string/body" /><uk.gov.hmrc.components.molecule.header.BoldTitleBodyView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:title="@string/title"
app:body="@string/body" /><uk.gov.hmrc.components.molecule.status.StatusView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:body="@string/status_card_placeholder_body"
app:bodyContentDesc="@string/status_card_placeholder_body_content_desc"
app:icon="@drawable/ic_maintenance"
app:iconTintColor="@color/hmrc_grey_1"
app:title="@string/status_card_placeholder_title"
app:textColor="@color/hmrc_green_1"
app:primaryButtonText="@string/status_card_placeholder_primary_button"
app:secondaryButtonText="@string/status_card_placeholder_secondary_button"
app:infoText="@string/status_card_placeholder_info_text" />status.setBodyGravity(Gravity.START) // defaults to CENTER if not set
status.onPrimaryButtonClickedListener = { // do something }
status.onSecondaryButtonClickedListener = { // do something }<uk.gov.hmrc.components.molecule.warning.WarningView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:text="@string/warning_placeholder_title"
app:textColor="@color/hmrc_black"
app:icon="@drawable/ic_warning"
app:iconTintColor="@color/hmrc_black"/><uk.gov.hmrc.components.molecule.tabbar.TabBarView
style="@style/TabBar"
android:layout_width="match_parent"
android:layout_height="wrap_content" />There are 2 styles available for the Tab Bar, TabBar and TabBar.Dark. The component extends the TabLayout Android class, so you can add tabs using either the TabLayout.addTab methods or by using 'TabLayout.setUpWithViewPager'.
<uk.gov.hmrc.components.molecule.selectrow.SelectRowGroup
android:id="@+id/select_row_tick_group"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<uk.gov.hmrc.components.molecule.selectrow.SelectRowView
android:id="@+id/select_row_tick_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:button="@drawable/select_row_tick"
app:text="First row" />
<uk.gov.hmrc.components.molecule.selectrow.SelectRowView
android:id="@+id/select_row_tick_2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:button="@drawable/select_row_tick"
app:text="Second row"/>
</uk.gov.hmrc.components.molecule.selectrow.SelectRowGroup>In order to be notified of a row being selected, SelectRowViews should be a direct child of a SelectRowGroup and a listener should be set on the SelectRowGroup using setOnRowSelectedListener(listener: OnRowSelectedListener?)
<uk.gov.hmrc.components.organism.headline.HeadlineCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:title="@string/title"
app:headline="@string/headline">
<!-- Add optional child views to the card here -->
</uk.gov.hmrc.components.organism.headline.HeadlineCardView>If you want to explicitly state the padding for the child views (eg. for secondary buttons) then use the removeDefaultChildPadding() method to remove any default padding from the children, or in xml set app:childPadding="false".
<uk.gov.hmrc.components.organism.status.StatusCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:body="@string/status_card_placeholder_body"
app:bodyContentDesc="@string/status_card_placeholder_body_content_desc"
app:icon="@drawable/ic_maintenance"
app:iconTintColor="@color/hmrc_grey_1"
app:title="@string/status_card_placeholder_title">
<!-- Add optional child views to the card here -->
</uk.gov.hmrc.components.organism.status.StatusCardView>status_card.setBodyGravity(Gravity.START) // defaults to CENTER if not setIf you want to explicitly state the padding for the child views (eg. for secondary buttons) then use the removeDefaultChildPadding() method to remove any default padding from the children, or in xml set app:childPadding="false".
<uk.gov.hmrc.components.organism.primary.PrimaryCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:title="@string/title">
<!-- Add optional child views to the card here -->
</uk.gov.hmrc.components.organism.primary.PrimaryCardView>If you want to explicitly state the padding for the child views (eg. for secondary buttons) then use the removeDefaultChildPadding() method to remove any default padding from the children, or in xml set app:childPadding="false".
<uk.gov.hmrc.components.organism.expandable.ExpandingRowView
android:id="@+id/expandable"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:title="Title"
app:subtitle="Subtitle"
app:icon="@drawable/ic_icon"
app:clickTogglesExpansion="false"
app:expanded="false">
<!-- Content to expand or collapse -->
</uk.gov.hmrc.components.organism.expandable.ExpandingRowView>You can then add an expansion listener to detect when the expansion state (expanded or collapsed) changes via:
expandable.addExpansionListener {
Toast.makeText(context!!, if (it) "Expanded" else "Collapsed", Toast.LENGTH_SHORT).show()
}You may also remove any previously set listener via:
expandable.removeExpansionListener(listener)or remove all listeners via:
expandable.clearExpansionListeners()<uk.gov.hmrc.components.organism.card.IconButtonCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:accessibilityMessage="@string/accessibility_message"
app:icon="@drawable/icon"
app:title="@string/title" />icon_button_card.setOnClickListener { // do something on click }<uk.gov.hmrc.components.organism.summary.SummaryRowView
android:id="@+id/summary_row_placeholder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:readerTrait="info"
app:rowStyle="@style/summary_row_style"
app:title="@string/summary_row_placeholder_title"
app:titleTextAppearance="@style/summary_row_title_style"
app:titleMaxLines="2" />This component contains a title, which can be set via xml or directly in the code, and a list of MultiColumnRow molecules, set via code.
val placeholderRow = MultiColumnRowView(context)
placeholderRow.setText(
getString(R.string.summary_row_placeholder_row1_text1),
getString(R.string.summary_row_placeholder_row1_text2),
getString(R.string.summary_row_placeholder_row1_text3))
summary_row_placeholder.setRows(arrayListOf(placeholderRow))
summary_row_placeholder.setOnClickListener { // do something on click }
summary_row_placeholder.setChevronContentDescription(getString(R.string.accessibility_message)
summary_row_placeholder.setAccessibilityMessage(getString(R.string.accessibility_message))If the Summary Row is to be used as a clickable button in the app, then you can use the setButtonAccessibilityMessage(buttonText, action) method to set the announcement you want read out in the form "[buttonText]; button. Double tap to [action]".
Note: This method should be used with the simple readerTrait defined. There may be duplicate talkback announcements if the info readerTrait is selected.
The readerTrait attribute changes the way the component is read out by TalkBack.
Note: If setting readerTrait programmatically instead of in an xml file, this attribute needs to be set before setRows() is called.
-
info- Specifies that the row will be read out element by element when read by TalkBack. This is the default trait. -
simple- Specifies that the row will be read out as one element by TalkBack.
<uk.gov.hmrc.components.container.SeparatedViewContainer
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Item 1" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Item 2" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Item 3" />
</uk.gov.hmrc.components.container.SeparatedViewContainer>This component is a container view that is essentially a custom LinearLayout. Child views inside this layout will have dividers applied between them.
You can change the divider via:
- XML
android:divider="@drawable/divider": see https://developer.android.com/reference/android/widget/LinearLayout#attr_android:divider or - By calling
setDividerDrawable()in code: see https://developer.android.com/reference/android/widget/LinearLayout.html#setDividerDrawable(android.graphics.drawable.Drawable)
By default the divider will be @drawable/divider. If you specify a divider, that will override the default divider.
You can change the dividers that are shown via:
- XML
android:showDividers="beginning,android:showDividers="middle,android:showDividers="end"or - By calling
setShowDividers()in code: see https://developer.android.com/reference/android/widget/LinearLayout#setShowDividers(int) With the options listed in https://developer.android.com/reference/android/widget/LinearLayout#SHOW_DIVIDER_BEGINNING
If you do not set showDividers via XML or code, it will default to show beginning, middle and end - so all the dividers.
If you specify SHOW_DIVIDER_NONE as per https://developer.android.com/reference/android/widget/LinearLayout#SHOW_DIVIDER_NONE, then it will revert to default behaviour as mentioned above.
If you need padding on your dividers, you can set android:dividerPadding="@dimen/hmrc_spacing_16" in the xml.
<uk.gov.hmrc.components.organism.information.InformationMessageCardView
android:id="@+id/info_message_placeholder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/hmrc_spacing_16"
app:headline="@string/info_message_placeholder_headline"
app:headlineContentDescription="@string/headlineContentDescription"
app:headlineIcon="@drawable/ic_info"
app:type="urgent" />Optionally, buttons can be added to the headline section using setHeadlineButtons(buttons: List<SecondaryButton>).
<uk.gov.hmrc.components.organism.menu.MenuPanelRowView
android:id="@+id/menu_placeholder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="@dimen/hmrc_spacing_16"
android:layout_marginStart="@dimen/hmrc_spacing_16"
android:layout_marginEnd="@dimen/hmrc_spacing_16"
android:layout_marginBottom="@dimen/hmrc_spacing_8"
app:body="@string/menu_panel_placeholder_body"
app:title="@string/menu_panel_placeholder_title" />Optionally, a choice of notification can be added to the right side of the title with showNotification(notificationCount: Int = 0).
Providing a notificationCount greater than 0, will show a notification with a number inside a rounded square, otherwise it'll be a blank circle notification.
The notification can also be removed by using hideNotification().
| Spacing | Usage |
|---|---|
| 4dp | @dimen/hmrc_spacing_4 |
| 8dp | @dimen/hmrc_spacing_8 |
| 16dp | @dimen/hmrc_spacing_16 |
| 24dp | @dimen/hmrc_spacing_24 |
| 32dp | @dimen/hmrc_spacing_32 |
| 48dp | @dimen/hmrc_spacing_48 |
The test library includes custom ViewMatchers and ViewActions for easier testing of HMRC components using espresso.
In order to release the library, you need to provide a Github personal access token with repo scope via a GITHUB_TOKEN environment variable - you can create a new token on Github.
To release the library, run bundle exec fastlane tag_release and choose to bump either the major, minor or patch when prompted. This will create a new tag, update the changelog and trigger the publish workflow on Bitrise.