jetc.dev 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!
Other Interesting Links
- How I Learned to Stop Worrying About Custom Components and Love Compose
- Skia shaders in Compose Desktop
- Medium: Jetpack Compose: Adding a Hilt ViewModel to the Navigation graph
- Google SignIn Compose
- List animations in Compose: Swipe to delete
- Medium: Jetpack Compose Hands On
- Medium: Guide on Jetpack Compose
- Medium: Jetpack Compose Side Effects — SideEffect
- Medium: Jetpack Compose. Base Layouts
- Medium: 4 Cool Facts About Jetpack Compose
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).
Other Interesting Links
- GitHub: X1nto / OverlappingPanelsCompose
- KotlinBloc
- GitHub: Tgo1014 / DraggableScaffold
- GitHub: ValeryPonomarenko / compose-shimmer
…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.
Or, you can subscribe to the Atom feed or follow Mark Murphy in the Fediverse.
Recent Issues:
- 2024-12-03: Rebecca Franks on clipping and masking! Stefano Natali on graphicsLayer()! FunkyMuse on type-safe nav results! And... if we have enough maps, do we need to store our maps in a Map?!?
- 2024-11-26: Math! Shared element transitions! Custom modifiers! Macrobenchmark! Adapting to platform-specific design systems! And... why does wrapContentSize() not wrap my content size?!?
- 2024-11-19: Compose alphas! Compose Multiplatform patch! PaddingValues! Graphics layers! Swiping! Heatmaps! Navigation! And... why did we get a new production Compose BOM?!?