15

我在我的 Android 项目中使用 Anko,但是当被引用的视图不在我引用它的同一级别时,我不知道它如何引用我在 DSL 中创建的子视图。

以下代码有效:

alert {
    customView {
        val input = textInputLayout {
            editText {
                hint = "Name"
                textColor =resources.getColor(R.color.highlight)
            }
        }


        positiveButton("OK") { "${input.editText.text}" }
    }
}.show()

但以下代码不起作用:

alert {
    customView {
        val vertical = verticalLayout {
            textView {
                text = "Edit device name"
                textColor = resources.getColor(R.color.highlight)
                textSize = 24F
            }
            val input = textInputLayout {
                editText {
                    hint = "Name"
                    textColor = resources.getColor(R.color.highlight)
                }
            }
        }

        positiveButton("OK") { "${vertical.input.editText.text}" }  // Cannot resolve "input"
    }
}.show()
4

5 回答 5

6

在我看来,有两种方法。超级 hacky 方法是在textInputLayout块中声明正按钮。这是可能的,因为您可以从任何嵌套范围内访问所有外部范围,并且该positiveButton方法在alert范围中声明:

alert {
    customView {
        verticalLayout {
            textInputLayout {
                val editText = editText {
                    hint = "Name"
                }

                positiveButton("OK") { toast("${editText.text}") }
            }
        }
    }
}.show()

比较简单的方法是声明一个可以从两个作用域访问的变量。但是,您需要将其设为可空,因为您无法立即对其进行初始化:

alert {
    var editText: EditText? = null

    customView {
        verticalLayout {
            textInputLayout {
                editText = editText {
                    hint = "Name"
                }
            }
        }
    }

    positiveButton("OK") { toast("${editText!!.text}") } 
}.show()
于 2015-12-11T11:14:34.903 回答
2

我建议使用 findViewById()

alert {
        customView {
            val vertical = verticalLayout {
                textView {
                    text = "Edit device name"
                    textSize = 24F
                }
                val input = textInputLayout {
                    editText {
                        id = R.id.my_id_resource // put your id here
                        hint = "Name"
                    }
                }
            }
            positiveButton("OK") { "${(vertical.findViewById(R.id.my_id_resource) as? EditText)?.text}" }  
        }
    }.show()
于 2015-12-14T01:12:04.113 回答
1

您始终可以提升视图,vertical手动传递上下文:

customView {
    val vertical = verticalLayout {
        textView {
            text = "Edit device name"
            textColor = resources.getColor(R.color.highlight)
            textSize = 24F
        }
    }

    val input = /*here:*/ vertical.textInputLayout {
        editText {
            hint = "Name"
            textColor = resources.getColor(R.color.highlight)
        }
    }

    positiveButton("OK") { "${input.editText.text}" }
}
于 2015-12-14T08:58:31.947 回答
1

我通常将视图声明为具有lateinit修饰符的类中的属性;这样它就不能为空,并且大多数视图都在一个地方声明,从而提高了可读性:

lateinit var toolbar: Toolbar

...
appBarLayout {
    toolbar = toolbar {}.lparams(width = matchParent, height = matchParent)
             }.lparams(width = matchParent)
...
setSupportActionBar(toolbar)
于 2017-04-19T08:33:31.910 回答
0

可能最好的方法是将 Android ID 用于稍后需要引用的元素和find<T : View>(Int) : T函数。这允许您从任何地方引用它们,只要视图仍然存在,并且您可以访问应用程序/活动范围。

有关详细信息,请参阅Anko 文档

示例案例:向现有视图动态添加按钮

verticalLayout {
  id = R.id.button_container
}
//note that the code below here may be executed anywhere after the above in your onCreate function
//verticalLayout is a Anko subclass of LinearLayout, so using the android class is valid.
val buttonContainer = find<LinearLayout>(R.id.button_container)

val containerContext = AnkoContext.Companion.create(ctx, buttonContainer)
val button = ctx.button {
  text = "click me"
  onClick = { toast("created with IDs!") }
}
buttonContainer.addView(button.createView(containerContext, buttonContainer))
于 2016-08-01T18:58:10.073 回答