Published March 06, 2020
(Updated 3/20/2020 with vector drawing changed from dev07 release)
My previous blog post covers setting up an Android project with Jetpack Compose and displaying text. This post focuses on displaying icons for the Tweet’s action row.
But first, a quick detour. The Tweet content lives between the user information row and the action row. This content is wrapped in a
Text element along with an applied
TextStyle. Since this composable item is not contained in a
Row it also needs padding applied to it directly.
Next up is displaying the content in the preview to verify it looks correct. This is simplified by combining the
TweetContent composable items in another composable function. The action row will also be added to this new composable function.
@Preview function displays the current view in the preview pane in Android Studio.
With the Tweet content in place, the action row is the next item to tackle. In my implementation the action row will contain four user actions for a Tweet.
Each of these actions display an image and react to click events. The Retweet and Like actions also have a selected state to modify their appearance.
Each action requires a separate compose function. Another function combines all of these actions into a row. To get something showing in the preview,
Button is used as a placeholder for each action.
ActionRow into the
TweetView displays the action buttons in the preview.
The buttons verify that the action row displays on the screen but it does not match the Tweet view. For this, I need icons. Android Studio provides a tool to create vector assets with the default material icons. To learn how to use it, check out Vector Asset Studio.
I found suitable icons for the comment, retweet, and share actions. I use
mode comment for the comment action,
loop for the retweet action, and
share for the share action. I also set the color for these vector assets to white. White assets are easier to tint the correct color.
Surprisingly, I could not find a heart icon to use for the like action. A quick search on StackOverflow returned this page. The first answer has a vector path that is perfect for my use case (thanks Uddhav Gautam!). My only modification sets the
fillColor to white.
The action functions need to load and display these vector assets. Each function can load its icon using the
vectorResource() function. The
Button components can be removed since they are no longer needed.
When the images are loaded, the action items need a place to draw their icon. There is currently no composable item like
ImageButton but the icons can be drawn manually. There is a
Container() function that can be used to hold the vector image. Doing so requires using the
drawVector() modifier function.
It is tempting to refactor this code to a base function since they only differ in their resource IDs. This would prove painful later on since some of the buttons have different behavior than others. Having a little patience ensures I do not end up with the wrong abstraction.
Once each action item has a container with a vector asset, the preview updates to show the action row.
These icons work but they are difficult, if not impossible, to see on a light background. The
tintColor attribute on the
drawVector() function provides an easy way to specify the color of the icon.
The action row has a similar problem to the original user info row. All of the icons are pushed to the left with no padding between them. Instead of manually adding spacing between the icons, I want my icons to be evenly spaced out.
Row needs two attributes to add space. First, it needs the
LayoutWidth.Fill modifier to take up the full width of the view. This leads to a question. The action row already has the
LayoutPadding modifier, so how can another one be added?
The solution is found by looking in the
Modifier.kt file. In the comment at the top of the file is this line:
* Modifier elements may be combined using `+` Order is significant; modifier elements to the left * are applied before modifier elements to the right.
Multiple modifiers can be combined using the
+ operator. Adding in the
LayoutWidth.Fill modifier forces the row to take up the full width.
Once the row is appropriately sized, providing an
Arrangement parameter tells the row how to position the child elements. The default is
Arrangement.Begin which places all of the items at the start of the row with no padding. Other options that do not add padding are
There are three other arrangement options that provide spacing between the items:
The code comments in
Flex.kt describe what each of these do.
Place children such that they are spaced evenly across the main axis, including free space before the first child and after the last child.
Place children such that they are spaced evenly across the main axis, without free space before the first child or after the last child.
Place children such that they are spaced evenly across the main axis, including free space before the first child and after the last child, but half the amount of space existing otherwise between two consecutive children.
My preference here is for the
SpaceAround version. The row looks better with space before the comment icon and after the share icon, but not the full amount of space that
In this post I added the Tweet content and action row to the Tweet view, as well as how to load and draw vector resources, and the different arrangement options for a row. Stay tuned for the next post in the series about handling click events!