Как ссылаться на другие взгляды в Anko DSL?
Я использую Anko в своем проекте Android, но я не знаю, как он может ссылаться на дочерние представления, которые я создал в 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()
5 ответов
На мой взгляд, есть два пути. Супер хакерский способ - объявить положительную кнопку внутри 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()
Я предлагаю использовать 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 для элементов, на которые вы будете ссылаться позже, и 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))