2022年12月6日火曜日

ParentDataModifier

ParentDataModifier は、親の Layout にデータを提供するための Modifier です。
ParentDataModifier の Density.modifyParentData() で返したデータが IntrinsicMeasurable.parentData に格納されます。

Measureable が IntrinsicMeasurable を実装しているので、MeasurePolicy の MeasureScope.measure() でこのデータを利用できます。 Layout( content = content, modifier = modifier ) { measurables, constraints -> measurables.forEach { val parentData = measurable.parentData ... } ... } ParentDataModifier interface を実装している Modifier として
  • LayoutId
  • BoxChildData
  • LayoutWeightImpl
  • HorizontalAlignModifier
  • VerticalAlignModifier
  • SiblingsAlignedModifier
などがあります。

この中で LayoutId は自分の Layout でも使うことができます。 Layout( content = { Icon( imageVector = Icons.Default.Home, contentDescription = "home", modifier = Modifier.layoutId("icon") ) Text( text = "home", modifier = Modifier.layoutId("text") ) }, modifier = modifier ) { measurables, constraints -> val iconMeasurable = measurables.first { it.layoutId == "icon" } val textMeasurable = measurables.first { it.layoutId == "text" } ... } Modifier.layoutId() は LayoutId を適用した Modifier を返すメソッドです。 @Stable fun Modifier.layoutId(layoutId: Any) = this.then( LayoutId( layoutId = layoutId, inspectorInfo = debugInspectorInfo { name = "layoutId" value = layoutId } ) ) LayoutId は ParentDataModifier と LayoutIdParentData を実装した Modifier で、Density.modifyParentData() では LayoutId 自身を返します。 @Immutable private class LayoutId( override val layoutId: Any, inspectorInfo: InspectorInfo.() -> Unit ) : ParentDataModifier, LayoutIdParentData, InspectorValueInfo(inspectorInfo) { override fun Density.modifyParentData(parentData: Any?): Any? { return this@LayoutId } ... } interface LayoutIdParentData { val layoutId: Any } Measurable.layoutId は parentData から Modifier.layoutId() で渡した layoutId を取得する便利メソッドです。 val Measurable.layoutId: Any? get() = (parentData as? LayoutIdParentData)?.layoutId

ParentDataModifier を実装した独自 Modifier を用意することができます。 @Immutable interface MyLayoutScope { @Stable fun Modifier.myLayoutData(index: Int): Modifier } internal object MyLayoutScopeInstance : MyLayoutScope { @Stable override fun Modifier.myLayoutData(index: Int): Modifier { return this.then(MyLayoutData(index = index)) } } @Immutable private data class MyLayoutData(val index: Int) : ParentDataModifier { override fun Density.modifyParentData(parentData: Any?): Any? { return this@MyLayoutData } } val Measurable.index: Int? get() = (parentData as? MyLayoutData)?.index



0 件のコメント:

コメントを投稿