Newsletter Issue #84

Published: 2021-09-28

This week, we look at composable sizes and what to do if things do not quite fit. We look at keyboard handling, theme swapping, and simulating classic LED matrix displays. We offer users scrollable pickers of numbers, times, or, well, anything. And I wonder how we are going to cope with the “just copy it” recommendation for dealing with Compose Material inflexibility.

One Off the Stack, One Off the Slack

You’ve got questions. That’s understandable!

Use Different Layout if Text Does Not Fit

Gracefully dealing with different font scales is a challenge in Android app development, inside or outside of Compose. Occasionally, you may want to more substantively change your UI for scaled-up fonts… but that implies that you know how much space the text takes up. See how to accomplish that in this week’s highlighted StackOverflow question.

How Do We Have Default Sizes?

You might want to create a composable that has a default size, yet allows that size to be overridden by modifiers. That gets complicated, given the way that conflicting modifiers “negotiate” a size, as we see in this week’s highlighted Kotlinlang #compose Slack thread.

Composable Commentary

Posts, videos, and other new information related to Jetpack Compose!

Video: Why We Need to Embrace Declarative UI

Amanda Scheetz delivered a presentation for Women Who Code that explores the distinction between imperative and declarative UIs like Compose and what benefits the declarative model offers.

Medium: Android Keyboard Handling Using Jetpack Compose

Siva Ganesh Kantamani continues to poke at the Compose UI API, this time examining the KeyboardOptions and KeyboardActions that we can pass into TextField() and related composables. Siva also explores using the FocusManager and KeyboardController composition locals, for things like manually changing the focus or dismissing the soft keyboard.

Medium: Supporting User-selected Themes with Jetpack Compose

Matt Robertson looks at a standard recipe for having your composables react to the system dark mode setting… and then looks at what powers that recipe. In particular, Matt looks at how you can have more complex business rules for your composable theme, based on the system dark mode setting, manual user options, and anything else that you need.

Style Navigation Bar on Android

Peng Jiang likes bottom navigation… so much so that Peng wrote a post about how to style bottom navigation using both BottomNavigationView from the Material Components for Android and Compose UI. Peng briefly covers how to control colors, badges, and the like for each of these bottom nav implementations.

Benefits of building components instead of screens

Alex Zhukovich encourages you to create custom components first, and build screens out of those components. This runs a bit counter to how we tend to build UIs in the classic View system, simply because creating custom views is a significant headache. Compose UI dramatically simplifies this, and Alex argues that building a robust component library is key for any significant Compose UI app.

Building an Animated LED Matrix Display in Jetpack Compose

Vishnu Haridas wanted an old-school 5x7 LED matrix display for displaying digits in a Compose UI app. Vishnu’s post shows one approach, using a 5x7 set of Box() composables, along with animated effects for switching between digits, custom shapes and colors for the individual dots in the display, and more!

Resource Roundup

100% pure code!

GitHub: theapache64 / create-compose-app

A couple of months ago, I pointed out the work that GitHub user theapache64 did in creating a project generator for Compose for Desktop theapache64 has created an expanded version of that generator, supporting multiple project templates, including a standard Compose UI project, Compose for Web, and more!

GitHub: ChargeMap / Compose-NumberPicker

Number pickers, where users can scroll through a series of values, are fairly common in mobile apps. Raphaël Bertin created a composable library supporting pickers for integers and times.

GitHub: RugerMcCarthy / ScrollableSelectLayout

If you need that same sort of picker UI, but for arbitrary collections of content, GitHub user RugerMcCarthy created a ScrollableSelectLayout() composable for that purpose.

GitHub: takahirom / Kotree

Every now and then, we need a reminder that while Compose UI is important, Compose overall is useful for other sorts of trees. In this project, Takahiro Menju demonstrates setting up a tree of nodes, then printing those in an ASCII tree that you might find in command-line output (e.g., a Gradle dependency report).

…And One More Thing

A couple of weeks ago, on Kotlinlang Slack, Zoltan Demant wanted to know:

Is there a sensible way to support a smaller TextField (width) than the material design one?

It turns out that TextField and OutlinedTextField have a minimum width of 280.dp, and its documentation (“you can override it by applying Modifier.widthIn directly on a text field”) apparently is incorrect.

Google’s Adam Powell pointed in Google’s standard direction for this, telling Zoltan to copy the code:

I think what you’d ideally want here is a way to implement your own text entry from the soft keyboard relationship on up. Drawing the text at all is something you want to have full control over.

BasicTextField is the place to start with the current API but I think we have some work to do in compose-ui itself to expose some lower level building blocks

As a result, Zoltan surrendered:

Alright 🙂 Ill leave it alone for now, the material library has covered all my needs thus far and I think that if I dabble with BasicTextField in an attempt to mimic 99% of the TextField functionality/look, itll just crush my hopes \& dreams in the long run with maintenance work. I appreciate the responses, thank you!

After all, even if we assume that all that is needed is to fork TextField(), that is at least 800 lines of code. Copying that code and making the adjustment would not be that hard the first time, to result in some TextFieldWithSmallerMinWidth() composable. But now Zoltan would be responsible for also re-copying that code on every Compose Material release and re-making that adjustment. Otherwise, at best, the customized TextFieldWithSmallerMinWidth() would steadily depart from the then-current TextField() implementation. At worst, TextFieldWithSmallerMinWidth() would start to fail, if it depends on stuff that Google changes.

Compose Material is an opinionated library. I get that. However, IMHO, ideally Google would have gone with “opinions as overridable defaults” more than “my way or the highway”. This is particularly true for constants like minimum width and height, where the cost for allowing an override is just a slot in the API.

Of course, not all customizations will be simple constants. For example, Zoltan later asked:

Is it possible to make the label of a TextField float to the top even though the input is empty?

Once again, the behavior of hint-versus-floating-label is opinionated within Material Design.

In truth, API design is hard regardless of whether you have a function-based or a class-based API. A constant like a minimum width might not be in a place in a class where it could be overridden, for example. It is just that we have a lot of experience with class-based APIs and where/how to provide flexibility. We will need to learn the equivalent techniques for a function-based API.

Also, we may need to start figuring out three-way merges or some means of being able to copy composables, make minor tweaks, and still adopt changes made to the original composables.