如何引用Anko DSL中的其他视图?

我在我的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() 

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

 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() 

我建议使用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() 

您始终可以提升视图,手动传递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}" } } 

我通常在一个带有lateinit修饰符的类中声明一个属性。 这种方式不是可以空的,大部分视图都在一个地方声明,提高了可读性:

 lateinit var toolbar: Toolbar ... appBarLayout { toolbar = toolbar {}.lparams(width = matchParent, height = matchParent) }.lparams(width = matchParent) ... setSupportActionBar(toolbar) 

可能最好的方法是使用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))