Bites of Compose 5

Learn Jetpack Compose one bite at a time

Guowei Lv

2 minute read

Let’s talk about Modifier.

Situation 1

What is the simplest Modifier?


Answer

Modifier

What is it? a class? an object?

It is a companion object, which implements the Modifier interface.

companion object : Modifier {
    override fun <R> foldIn(initial: R, operation: (R, Element) -> R): R = initial
    override fun <R> foldOut(initial: R, operation: (Element, R) -> R): R = initial
    override fun any(predicate: (Element) -> Boolean): Boolean = false
    override fun all(predicate: (Element) -> Boolean): Boolean = true
    override infix fun then(other: Modifier): Modifier = other
    override fun toString() = "Modifier"
}

The formal version is Modifier.Companion, but can be shortened as Modifier.

I know, this can be confusing, but let’s write a simpler example to understand it step by step.

First we need to understand that the so called companion object, is just a kind of global object attached to a class or interface itself, this is similar to the static members of a class in Java.

For example:

class Person {
    companion object {
        const val TAG = "person"
        fun talk() = print("I'm talking...")
    }
}

The “Person class” has a TAG property and a “static function” talk(). And to access this companion object we can just write Person.Companion or simply Person.

Person.TAG
Person.talk()
Person.Companion.TAG
Person.Companion.talk()

Also, the companion object can implement interface.

interface Runnable {
    fun run()
}

class Person {
    companion object : Runnable {
        const val TAG = "person"
        fun talk() = print("I'm talking...")
        override fun run() {
            print("Running...")
        }
    }
}

Person.run()

And not only classes, but interfaces can also have companion object. And if its companion object implements itself…

interface Car {
    fun drive()
    fun stop()

    companion object : Car {
        override fun drive() {
            print("drive")
        }

        override fun stop() {
            print("stop")
        }
    }
}

This is exactly how Modifer is doing.

Situation 2

What does this mean?

Box(modifer: Modifier = Modifier)

Answer

Passing in the most basic Modifier object as default parameter.

Situation 3

Is this companion object Modifier used anywhere else?


Answer

Yes, it is also used when you do something like:

Modifier.padding(4.dp)
Modifier.background(Color.Red)
...

Let’s look into the source code:

fun Modifier.background(
    color: Color,
    shape: Shape = RectangleShape
) = this.then(
    Background(
        color = color,
        shape = shape,
        inspectorInfo = debugInspectorInfo {
            name = "background"
            value = color
            properties["color"] = color
            properties["shape"] = shape
        }
    )
)

As you can see, background() is an extension function of the companion object Modifier (not the interface Modifier!).

comments powered by Disqus