【问题标题】:Adding buttons to view dynamically wipes existing views添加按钮以动态擦除现有视图
【发布时间】:2021-12-25 23:43:28
【问题描述】:

我有一个字符串列表,我想在线性布局中创建按钮,其文本来自该列表。我在 XML 文件中的线性布局是:

...other stuff...
<LinearLayout
    android:id="@+id/my_linear_layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"/>

然后在onCreate我有以下代码:

buttons = viewModel.myLiveDataList.value!!.map {
    val button = Button(binding.myLinearLayout.context)
    button.layoutParams = LinearLayout.LayoutParams(
        LinearLayout.LayoutParams.WRAP_CONTENT,
        LinearLayout.LayoutParams.WRAP_CONTENT)
    button.text = it.displayName
    return button
}

我觉得我做的不对,因为我从来没有在线性布局上调用 addView,这是我见过的所有示例,但是当我尝试调用 addView 时,我收到了关于按钮的错误已经有了父母。

这段代码的结果是片段只显示一个按钮,其文本是列表的第一个条目。它不显示线性布局之前存在的“其他东西”,也不显示列表中任何其他条目的按钮。

我已经通过日志验证了列表本身确实有多个条目,但 map 函数只在第一个条目上执行,我不知道为什么视图中的其他所有内容都被删除了,我只得到一个按钮。

谁能向我解释我做错了什么?

编辑:根据要求,我最初尝试按照示例here 编写以下内容:

buttons = viewModel.myLiveDataList.value!!.map {
    val button = Button(this)
    button.layoutParams = LinearLayout.LayoutParams(
        LinearLayout.LayoutParams.WRAP_CONTENT,
        LinearLayout.LayoutParams.WRAP_CONTENT)
    button.text = it.displayName
    binding.myLinearLayout.addView(button)
    return button
}

这不会编译,因为 Button 需要上下文,所以我将其更改为 Button(this.context),然后它在 addView 上崩溃并显示消息

java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.

【问题讨论】:

  • 示例here 有帮助吗?您确实需要addView,因此您可能应该将您的称呼方式添加到问题中
  • 您是否考虑过使用RecyclerViewdeveloper.android.com/guide/topics/ui/layout/recyclerview
  • @TylerV:该示例的问题在于,这些类的接口在 Kotlin 中与在 Java 中似乎不同。例如,我不能传入this 来创建一个按钮,我需要传入一个上下文,并且我不能将按钮传递给addView,因为我收到一个关于需要从它的父级中删除它的错误.
  • @ChocolateChapta:我没有。如果我无法得到我想要做的工作,那么我想我会针对尝试 #2 进行调查,谢谢。
  • 将您尝试的代码添加到问题中。回收者视图是个好主意。

标签: android kotlin android-layout


【解决方案1】:

您的代码很接近,但是当您在 Kotlin 的内部范围内使用 thisreturn 时,您有时需要指定这些参数的范围。你得到一个错误,因为this 指的是地图 lambda,而不是活动,这就是它说它需要一个上下文的原因。

这对我有用 - 成功地将三个按钮添加到线性布局。注意使用this@MainActivity 来获取封闭的活动和return@map。您也可以只在最后一行输入button 而无需return 语句,有时它可以正确推断this 的正确范围而无需@,但通常最好指定它。

val linearLayout = findViewById<LinearLayout>(R.id.my_linear_layout)

val buttonText = listOf("Button A","Button B","Button C")
val buttons = buttonText.map { txt ->
    val button = Button(this@MainActivity)
    button.layoutParams = LinearLayout.LayoutParams(
        LinearLayout.LayoutParams.WRAP_CONTENT,
        LinearLayout.LayoutParams.WRAP_CONTENT)
    button.text = txt
    linearLayout.addView(button)
    return@map button // or just "button" by itself without a "return"
}

注意:当我第一次复制您的代码时,我看到了同样的错误,即需要 Button 的上下文,但在随后尝试复制它时,this 似乎工作正常。我不知道为什么它以前不工作而现在工作,但使用 @ 符号不会受到伤害。在 Android Studio 中,您可以将鼠标悬停在 this 文本上以查看它所指的范围。

结果布局

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-09
    • 1970-01-01
    • 1970-01-01
    • 2013-06-01
    • 2014-07-15
    • 1970-01-01
    相关资源
    最近更新 更多