我正在通过Android开发人员进行工作 online tutorial for 1st Android apps.

我有C编程背景,但面向对象的经验非常有限.

当我使用"修饰符"调用一个方法时,我正在试图理清发生了什么.VS"修饰语".我假设小写版本调用传递给它的对象上的方法,而大写版本不知何故是作为参数调用它的子对象的本地新对象.小写版本似乎会影响先前应用于该"父对象"的方法.这里有一个两者的例子,有观察到的行为.这两个示例之间的唯一区别是在第一个Text()调用中的"Modify"调用中的"m"的大小写.

第一个例子是所需的行为.在第一个"Text"调用中,我使用了"Modify"(大写).This preserves the centered vertical arrangement of the parent column.("One象限"函数被调用4次,如下图所示为预览面板)

enter image description here

@Composable
fun OneQuadrant(title: String, info: String, bColor: Color, modifier: Modifier)
{
   Column (
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center,
        modifier = modifier
            .fillMaxHeight()
            .background(bColor)
            .padding(16.dp)
    )
    {
        Text(
            text = title,
            fontWeight = Bold,
            modifier = Modifier.padding(bottom=16.dp)
        )
        Text(
            text = info,
            textAlign = TextAlign.Justify,
        )
    }
}

第二个例子是不受欢迎的行为.第一个"Text"调用使用"Modify"(小写).This evidently overrides the centered vertical arrangement in the parent column.

enter image description here

@Composable
fun OneQuadrant(title: String, info: String, bColor: Color, modifier: Modifier)
{
   Column (
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center,
        modifier = modifier
            .fillMaxHeight()
            .background(bColor)
            .padding(16.dp)
    )
    {
        Text(
            text = title,
            fontWeight = Bold,
            modifier = modifier.padding(bottom=16.dp)
        )
        Text(
            text = info,
            textAlign = TextAlign.Justify,
        )
    }
}

问题1:在第二个例子中,即使小写版本作用于父级,为什么会取消居中的垂直排列?我看到底部填充和居中不一致,很可能最后一次调用占上风.但是,该列还需要在Arrangement.Center语句之后进行填充,这可以正常工作.

Q2:如果是映射回父级,为什么"Column"中的调用不也映射回100 Parent,因为它是作为参数传递的?

问题3:什么是正确的心理模型,才能理解正在发生的事情?我想我在某种程度上被底层的对象搞糊涂了.可组合函数的名称暗示对象,但它们实际上是作用于其他对象的函数(S)……是真的吗?

我确实读了Kotlin 的《伴随物》,但这并没有真正起到什么作用.我猜这在某种程度上与Kotlin中的按引用传递行为有关,但我无法理解.你能给我解释一下,或者让我参考一个明确的参考资料吗?谢谢!

如果有用,下面是调用OneQuadant 4次的函数.

fun DisplayQuadrants(modifier: Modifier = Modifier) {
    Column (modifier.fillMaxWidth()) {
        Row (modifier.weight(1f)){
            OneQuadrant(
                title = stringResource(R.string.text_composable),
                info = stringResource(R.string.displays_text),
                bColor = Color(0xFFEADDFF),
                modifier = modifier.weight(1f)
            )
            OneQuadrant(
                title = stringResource(R.string.image_composable),
                info = stringResource(R.string.creates_composable),
                bColor = Color(0xFFD0BCFF),
                modifier = modifier.weight(1f)
            )
        }
        Row (modifier.weight(1f)){
            OneQuadrant (
                title = stringResource(R.string.row_composable),
                info = stringResource(R.string.a_layout),
                bColor = Color(0xFFD0BCFF),
                modifier = modifier.weight(1f)
            )
            OneQuadrant(
                title = stringResource(R.string.column_composable),
                info = stringResource(R.string.vertical),
                bColor = Color(0xFFF6EDFF),
                modifier = modifier.weight(1f)
            )
        }
    }
}

此DisplayQuadrants在MainActivity中的调用如下:

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            QuadrantsTheme {
                // A surface container using the 'background' color from the theme
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    DisplayQuadrants(modifier = Modifier)
                }
            }
        }
    }
}

推荐答案

为了回答你的问题,让我们来看看修改器是如何在内部工作的.
根据documentation条,修饰符基本上是不变的列表:

可以将多个修饰符链接在一起,以装饰或增强可组合对象.此链是通过表示ordered, immutable list of single Modifier.Elements的修改器界面创建的.

当我们执行代码时

1    val aModifier = Modifier.fillMaxHeight()      // = [fillMaxHeight]
2    val bModifier = aModifier.wrapContentWidth()  // = [fillMaxHeight, wrapContentWidth]
3    val cModifier = aModifier.fillMaxWidth()      // = [fillMaxHeight, fillMaxWidth]
4    // aModifier = [fillMaxHeight]

然后

  • aModifier本身将在第2行和第3行中修改为not
  • bModifier将接收一个新的修改器实例,该实例具有从aModifier复制的所有Modifier.Elements以及附加的修改器wrapContentWidth()
  • cModifier将接收一个新的修改器实例,该实例具有从aModifier复制的所有Modifier.Elements以及附加的修改器fillMaxWidth()

因此,一般来说,如果像这样多次使用相同的aModifier个实例,Composable中不会有任何副作用:

val aModifier = Modifier.fillMaxWidth()
Text(
    modifier = aModifier.background(Color.Red)  // = [fillMaxWidth, background]
    text = "Text with red background"
)

Text(
    modifier = aModifier.border(width = 2.dp, color = Color.Green)  // = [fillMaxWidth, border]
    text = "Text with green border"
)

第一个文本将具有fillMaxWidthbackground个Modifier.Element.
第二个文本将具有fillMaxWidthborder个Modifier.Element.
第一个文本不影响第二个文本,因为aModifier本身永远不会被修改.


Now let's analyze your code.

在你的OneQuadrant个Composable中,一切都很好.在那里使用的修改器不会对彼此产生副作用.

有问题的部分出现在DisplayQuadrants个可合成成分中:

OneQuadrant(
    // ...
    modifier = modifier.weight(1f)
)

传入一个新的Modifier实例,该实例具有weight Modifier.Element.让我们看看这对OneQuadrant中的可组合件有什么影响:

fun OneQuadrant(title: String, info: String, bColor: Color, modifier: Modifier)
{
   Column (
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center,
        modifier = modifier  // = [weight, fillMaxHeight, background, padding]
            .fillMaxHeight()
            .background(bColor)
            .padding(16.dp)
    )
    {
        Text(
            text = title,
            fontWeight = Bold,
            modifier = modifier.padding(bottom=16.dp)  // = [weight, padding]
        )
        Text(
            text = info,
            textAlign = TextAlign.Justify,
        )
    }
}

As you can see, the title Text suddenly has a weight and a padding Modifier.Element.
The weight Modifier makes the Text fill the maximum remaining height within the Column.

结果,verticalArrangement看起来不再正确了,尽管它在技术上仍然可以正常工作.

当你这样做的时候

Text(
    text = title,
    fontWeight = Bold,
    modifier = Modifier.padding(bottom=16.dp)  // = [padding]
)

然后 there will be no weight Modifier.Element present, and thus the Text Composable wraps its Text.

Android相关问答推荐

滚动屏幕时更改按钮外观

如何禁用Android 34+版的TileService,但保留以前的版本?

约束布局:垂直链中的视图应将内容包裹到空间的1/3

在以XML格式设置完整屏幕视图时可见App Compat按钮

默认调度程序是否在协程中使用共享线程池?

Android布局渲染问题

当按下通知时,将Android应用程序置于前台

我们可以使用KSP读取类中变量的值吗?

未解析的引用:视图模型

Spinner - onItemLongClick 从未执行

如何避免多次调用 Jetpack Compose 的 onClick 回调

如何在 Jetpack Compose 中对齐按钮底部中心?

Compose 状态不是 recomposing

Jetpack Compose 中带有权重的行和 AnimatedVisibility 会 destruct UI

如何在 Jetpack Compose 中设置卡片高度

在compose中,为什么修改List元素的属性,LazyColumn不刷新

如何处理 com.google.gson.JsonSyntaxException: java.lang.NumberFormatException: For input string: "T1V 4Y8" Kotlin

WindowManager 内的 RecyclerView 不更新

compose FontFamily 错误:必须初始化变量

lambda 函数中的类型不匹配 - Kotlin