jetc.dev Newsletter Issue #67
Published: 2021-06-01
This week, we dive deep into how some of the Compose magic occurs, with looks at
the Kotlin compiler plugin and how recomposition works “under the hood”. We also
look at some hiccups with collectAsState()
, the current state of Lottie for
Compose, and what the newly-added Kotlin/Native support for the Compose compiler plugin means.
We also peek at an internationalization/localization library, a command-line tool
for setting up Compose for Desktop projects, and what that app widget “conceptual code”
shown in a Google I|O presentation might really mean.
One Off the Stack, One Off the Slack
You’ve got questions. That’s understandable!
Prefixes in a TextField()
Frequently, we want an input field that is not just user-entered text, but also contains
other elements. For example, for entering a phone number, you might already
know the appropriate country code from other details, and you want to allow the
user to skip typing that part in. You can accomplish this and other similar
effects using the visualTransformation
parameter, as seen in this week’s
highlighted Stack Overflow question.
Remember Your Flows
Compose often seems like magic, in part because its Kotlin compiler plugin
is magic… for some things. However, there are limits to the magic, and after
that, you need to remember arcane rules, no different than you would with any
other framework. For example, you need to be very careful about Flow
operators
when combined with collectAsState()
, if you want to avoid excessive (or perhaps infinite)
recompositions, as we explore in this week’s highlighted Kotlinlang #compose
Slack thread.
Composable Commentary
Posts, videos, and other new information related to Jetpack Compose!
Podcast: Jetpack Compose Compilation
Android Developers Backstage is a long-running podcast, hosted by Google engineers. They have started a new series on Jetpack Compose, this time with Nick Butcher and Chet Haase talking with Adam Powell and Leland Richardson on the internals of the Kotlin compiler plugin and how it and the runtime drive recomposition.
A Historical Introduction to the Compose Reactive State Model
Zach Klippenstein has been busy! This post looks at past approaches for reactivity and compares them to what composables and recomposition offers us. Then, Zach continues with another post exploring how the Compose snapshot system works, giving us what amounts to transactional semantics on in-memory structures.
Custom Weekly Schedule Layout with Jetpack Compose - Part 1
Calendars with events are popular UI constructs, ones that often times are a pain to
build. Daniel Rampelt created a weekly event schedule UI — the sort of thing that
you might see in a personal planner, conference schedule, or room reservation app.
This post, plus part 2,
cover all the details, from event cells and custom Layout()
composables for columns
to row and column headers and grid lines.
Lottie Animations in Jetpack Compose Android
Lottie is a very popular animation system, and about six months ago
it was made available for Compose as an alpha. In this post, Muhammad Danish brings
us up to date with the current Lottie for Compose beta and how to use LottieAnimation()
composables in your app.
The All-New State in Jetpack Compose
Siva Ganesh Kantamani is back, this time with an extensive review of state management
in Compose, from remember()
and state hoisting to LiveData
and MutableState
.
Compose – List / Detail: Basics
Mark Allison is starting to compose! In this post, Mark looks at the Jetpack SlidingPaneLayout
for the classic View
system and how to implement a similar setup in Compose UI,
for offering side-by-side panes on wider screens and overlapping panes on narrower
screens.
Tweets: Compose and Kotlin/Native
Andrei Shikov announced the availability of the Compose compiler for Kotlin/Native. While this does not mean that Compose for iOS is going to appear in the coming days, this is an important step towards offering Compose-style UI development for other UI systems, beyond Compose for Android, Compose for Desktop, Compose for Web, and Compose for Terminal (or however you want to categorize Jake Wharton’s Mosaic).
How to Disable Ripple Effect in Jetpack Compose
Compose Material applies the standard Material Design ripple animation. Some developers wanted that ripple for non-Material composables, which is why it is now available in a separate library. Mathan Raj wanted it gone, so in this brief post, Mathan demonstrates how to remove the standard ripple “indication” with nothing at all.
Video: Shimmer Animation (Jetpack Compose Beta)
Mitch Tabian returns with another screencast, this time showing how to implement a shimmer animation effect, designed to serve in the role of placeholder while you busily load content in the background.
Other Interesting Links
- Button Selector in Jetpack Compose Android
- Custom Font Family in Android Jetpack Compose
- Cartographing Jetpack Compose: foundation
- Creating a Curved Scroll View with Jetpack Compose
- Android Jetpack Compose Cool Status Bar Collapsable Parallax Image Effect
- Pick Image from Gallery in Jetpack Compose
- Video: Jetpack Compose Basic Setup for Android Studio
- Getting Started with JetPack Compose
Resource Roundup
100% pure code!
GitHub: adrielcafe / lyricist
Adriel Café is taking a shot at a Kotlin-centric string management system, for
internationalization and localization purposes. It code-generates a CompositionLocal
that you can use to get the translations of your strings for the current locale.
GitHub: iamjosephmj / flinger
Joseph James gives us a library that exposes an API for fling control in LazyColumn()
and LazyRow()
, allowing you to customize gravity, friction, and related properties.
GitHub: theapache64 / create-compose-desktop-app
GitHub user theapache64 created a NodeJS npm
module that supplies a command-line
Compose for Desktop project generator. You supply a display name and package name,
and it code-generates a skeleton project for you.
Other Interesting Links
- Gist: danielzfranklin / ExposedDropdownMenu.kt
- Gist: tkuenneth / MainActivity.kt (Adaptive Icon)
- GitHub: TiagoDanin / Emoji-Memory-Jetpack
- GitHub: ch8n / Compose-SpaceWars
…And One More Thing
Buried in the Google I|O presentation on app widgets, they showed off some “conceptual code” for creating app widgets using a composable API:
@Composable
fun ListWidget(items: List<Item>) {
Column {
Text("Shopping List")
items.forEach { CheckListItem(it) }
}
}
@Composable
fun CheckListItem(item: Item) {
CheckBox(
item.name,
isChecked = item.isChecked,
onStateChanged = { isChecked -> updateItem(item, isChecked) }
)
}
This has led some developers to believe that we will be creating app widgets using Compose UI. I strongly doubt that this is the case. We will be able to create app widgets using Compose, but not Compose UI.
Compose UI requires a Canvas
to draw on. In Compose for Android, that is Android’s
Canvas
. In Compose for Desktop, that is a canvas API supplied by Skia and
Skiko.
However, other Compose targets, such as Compose for Web or Jake Wharton’s Mosaic,
do not support Canvas
. And, as a result, they do not support Compose UI.
Compose for Web supports a facsimile of some of Compose UI, where they could pull off
the same basic look using the DOM and CSS. And Mosaic has an even more limited API,
given that it is targeting a terminal window rather than any sort of GUI.
Compose supports managing trees of data using composable functions. Compose UI
supports managing trees of UI elements to be drawn on a Canvas
using composable functions.
App widgets do not have a Canvas
. Even though app widgets are part of Android,
they are very different than the activities and fragments that we traditionally build.
App widgets are really an IPC protocol between an app and a launcher, where the data
passed between the process just so happens to describe a UI. That is why app widgets
are created using RemoteViews
, as that RemoteViews
structure describes the UI
and is what gets passed between the processes. RemoteViews
does not give us a Canvas
.
The most likely case is that writing app widgets with composables will look a bit like
Compose UI, but the composables will map to things that you can represent in a RemoteViews
.
So, in the code snippet shown above, the Column()
will map to a LinearLayout
,
the Text()
will map to a TextView
, and CheckBox()
will map to a CheckBox
(newly
supported in RemoteViews
in Android 12). But, you will not find TextField()
in
the app widgets API, as RemoteViews
does not support EditText
.
It would be truly wonderful if app widgets could somehow use the full suite of composables offered by Compose UI. Alas, that is unrealistic.
Or, you can subscribe to the Atom feed or follow Mark Murphy in the Fediverse.
Recent Issues:
- 2024-12-10: A Compose Multiplatform alpha! Hot reload! Presentation! Sprites! Calendars!
- 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?!?