Types of Props
The Components page details how to declare a component and its props as standard val
properties. This page covers two more ways for a parent component to configure its children with props: Common props and Tree props.
Common Propsβ
A common prop is one of a set of properties that can be applied to any primitive component.
Common props are supported by all primitive components. They include View properties like onClick
and background
, visibility events like onVisible
, as well as layout parameters like margin
.
Common props are specified using the Style
API, which enables one or more common props to be chained together into a Style object that is passed to the components as a prop, as shown in the following example:
val style = Style.margin(all = 4.px)
.backgroundColor(Color.RED)
.viewTag("my_view")
For a component to be configured with a Style, it should declare a Style prop (such as val style: Style? = null
). It should then pass that Style object to one of the components it renders to, usually the root component it returns from render
. In this way, the Style will eventually end up on a primitive component (for example, Text
or Row)
. All common props end up being materialized by primitive components, as shown in the following example:
class StyledHelloComponent(private val name: String, private val style: Style? = null) :
KComponent() {
override fun ComponentScope.render(): Component {
return Text(style = style, text = "Hello $name!")
}
}
val componentWithOnClick =
StyledHelloComponent(name = "Common Props", style = Style.onClick { log("clicked!") })
Combining a Style from above with a local Styleβ
The following 'more advanced' example shows how you can combine a Style taken from above with the Style the component itself wants to define:
class OuterTextComponent : KComponent() {
override fun ComponentScope.render(): Component {
return InnerTextComponent(style = Style.margin(all = 8.dp))
}
}
class InnerTextComponent(private val style: Style? = null) : KComponent() {
override fun ComponentScope.render(): Component {
return Text(
style = Style.padding(all = 8.dp).alpha(.5f) + style,
text = "I accept style from a parent!")
}
}
Working with Styleβ
In the above example, you may have noticed the use of +
to combine the Style passed from OuterTextComponent
and the styles that InnerTextComponent
defines. The +
operator combines two Styles into a single Style without mutating either:
val alphaStyle = Style.alpha(1f)
val combinedStyle = alphaStyle + Style.padding(all = 8.dp).margin(all = 8.dp)
// Result:
// alphaStyle: (alpha: 1f)
// combinedStyle: (alpha: 1f) <- (padding-all: 8.dp) <- (margin-all: 8.dp)
Note that ordering around +
matters: if a Style property is defined twice, the last definition takes precendence:
val alphaStyle = Style.alpha(1f)
val combinedStyle = alphaStyle + Style.padding(all = 8.dp).alpha(.5f)
// Result:
// combinedStyle will apply padding of 8.dp and alpha of .5f
Generally, Style
objects are immutable: any time you combine styles or add new properties to a style, you get a new Style
instance that contains all the properties of the previous style plus the new properties.
Java - Kotlin compatibilityβ
If you need to pass down a style from a Java class to a Kotlin component, use StyleCompat
:
@LayoutSpec
class OuterStyleComponentSpec {
@OnCreateLayout
static Component onCreateLayout(ComponentContext c) {
return new InnerTextComponent(StyleCompat.marginDip(YogaEdge.ALL, 8).build());
}
}
For passing style from Kotlin code to a Java Spec component, you can use .kotlinStyle()
, which is equivalent to setting all the common props the Style
defines:
class OuterStyleKComponent : KComponent() {
override fun ComponentScope.render(): Component {
val style = Style.margin(all = 8.dp)
return OuterStyleComponent.create(context).kotlinStyle(style).build()
}
}
See alsoβ
- Tree Props - provides a way to give access to contextual objects, like a theme or logging utility, to all components in a sub-tree without having to manually pass them.