Compose for Put on: CurvedRow() and CurvedText()

Compose for Put on: CurvedRow() and CurvedText()

Compose UI is not only for telephones, tablets, foldables, notebooks, and desktops.
Compose UI is for watches as properly, through the Compose for Put on set of libraries.

(Google calls it “Put on Compose” on that web page, however that simply makes me assume
“Put on Compose? There! There Compose!”).

(and, sure, I’m outdated)

Compose for Put on has a bunch of composables designed for the watch expertise.
Particularly, Compose for Put on has help for having content material curve to match
the perimeters of a spherical Put on OS machine.

The Compose for Put on version of Scaffold() has a timeText parameter. This
is a slot API, taking a composable as a price, the place usually you will note that
composable delegate purely to TimeText(). That offers you the present time
throughout the highest of the watch display screen, together with curving that point on spherical screens:

TimeText() on a Round Watch

The implementation of TimeText() makes use of CurvedRow() and CurvedText() to perform this,
if the code is operating on a spherical machine. In any other case, it makes use of the traditional Row() and
Textual content() composables,

TimeText() is a bit overblown, notably for a weblog publish, so
this pattern mission
has a SimpleTimeText() composable with a subset of the performance:

enjoyable SimpleTimeText(
    modifier: Modifier = Modifier,
    timeSource: TimeSource = TimeTextDefaults.timeSource(TimeTextDefaults.timeFormat()),
    timeTextStyle: TextStyle = TimeTextDefaults.timeTextStyle(),
    contentPadding: PaddingValues = PaddingValues(4.dp)
) {
    val timeText = timeSource.currentTime

    if (LocalConfiguration.present.isScreenRound) {
        CurvedRow(modifier.padding(contentPadding)) {
                textual content = timeText,
                type = CurvedTextStyle(timeTextStyle)
    } else {
            modifier = modifier
            verticalAlignment = Alignment.High,
            horizontalArrangement = Association.Heart
        ) {
            Textual content(
                textual content = timeText,
                type = timeTextStyle,

We will decide whether or not or not the display screen is spherical from the isScreenRound
property on the Configuration, which we get through LocalConfiguration.present.
If the display screen is spherical, we show the present time in a CurvedText() and wrap
that in a CurvedRow(). CurvedText() is aware of find out how to have the letters of the textual content
comply with the curve of the display screen, and CurvedRow() is aware of find out how to have baby composables
comply with the curve of the display screen.

The timeText slot parameter in Scaffold() places the time on the prime of the
display screen by default. That place is managed by the anchor parameter to
CurvedRow(), the place the default anchor is 270f. anchor is measured in levels,
and 270f is the worth for the highest of the display screen (most likely for historic causes).

SampleRow() in that pattern mission lets us show a number of separate strings
through particular person CurvedText() composables, in a CurvedRow() with a customized anchor worth:

non-public enjoyable SampleRow(anchor: Float, modifier: Modifier, vararg textBits: String) {
        modifier = modifier.padding(4.dp),
        anchor = anchor
    ) {
        textBits.forEach { CurvedText(it, modifier = Modifier.padding(finish = 8.dp)) }

SampleRow() accepts a Modifier and tailors it so as to add a little bit of padding to the CurvedRow().

We will then use SampleRow() to show textual content in different positions on the display screen:

enjoyable MainScreen() {
        timeText = {
        content material = {
            Field(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Heart) {
                Textual content(textual content = "Hiya, world!")

                SampleRow(anchor = 180f, modifier = Modifier.align(Alignment.CenterStart), "one", "two", "three")
                SampleRow(anchor = 0f, modifier = Modifier.align(Alignment.CenterEnd), "uno", "dos", "tres")
                SampleRow(anchor = 90f, modifier = Modifier.align(Alignment.BottomCenter), "eins", "zwei", "drei")

An anchor of 0f is the top fringe of the display screen, 90f is the underside, and 180f is the beginning edge.
Observe that we additionally use align() to manage the positioning throughout the Field(), with values
that line up with our chosen anchor values.

The result’s that we’ve got textual content on all 4 edges, plus a centered “Hiya, world!”:

Sample Compose UI on a Round Watch

CurvedRow() doesn’t deal with consecutive bits of CurvedText() all that properly —
ideally, use a single CurvedText() with the mixed textual content. Nonetheless, CurvedRow()
isn’t restricted to CurvedText(), and I hope to discover that extra in a future weblog publish.