2022年12月6日火曜日

ParentDataModifier

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

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

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


ParentDataModifier を実装した独自 Modifier を用意することができます。
  1. @Immutable  
  2. interface MyLayoutScope {  
  3.     @Stable  
  4.     fun Modifier.myLayoutData(index: Int): Modifier  
  5. }  
  6.   
  7. internal object MyLayoutScopeInstance : MyLayoutScope {  
  8.   
  9.     @Stable  
  10.     override fun Modifier.myLayoutData(index: Int): Modifier {  
  11.         return this.then(MyLayoutData(index = index))  
  12.     }  
  13. }  
  14.   
  15. @Immutable  
  16. private data class MyLayoutData(val index: Int) : ParentDataModifier {  
  17.     override fun Density.modifyParentData(parentData: Any?): Any? {  
  18.         return this@MyLayoutData  
  19.     }  
  20. }  
  21.     
  22. val Measurable.index: Int?  
  23.     get() = (parentData as? MyLayoutData)?.index  




0 件のコメント:

コメントを投稿