Как использовать привязку представлений для пользовательских представлений
Привязка просмотра была выпущена с v3.6.
Документы: https://developer.android.com/topic/libraries/view-binding
Мой вопрос в том, как использовать привязку представлений с настраиваемыми представлениями. В документации Google есть только Activity и фрагмент с указанием витрины.
Я пробовал это, но ничего не было показано.
LayoutInflater inflater = LayoutInflater.from(getContext());
А потом я использовал этот, но опять же безуспешно.
LayoutInflater inflater = (LayoutInflater)
getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
Я предполагаю, может быть, я не нацелен на правильный надувной макет для моего представления, но не уверен в этом.
6 ответов
Просто сообщите рут, и хотите ли вы к нему прикрепить
init { // inflate binding and add as view
binding = ResultProfileBinding.inflate(LayoutInflater.from(context), this, true)
}
Чтобы использовать привязку вида, вам необходимо использовать сгенерированный класс привязки, а не LayoutInflater
, например, если имя макета result_profile.xml
тогда вам нужно использовать ResultProfileBinding
как:
class CustomView @kotlin.jvm.JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {
private lateinit var binding: ResultProfileBinding
init { // inflate binding and add as view
binding = ResultProfileBinding.inflate(LayoutInflater.from(context))
addView(binding.root)
}
}
- Автоматически созданный класс:
result_profile.xml
->ResultProfileBinding
(название макета, с добавлениемBinding
) Надуть переплет
ResultProfileBinding.inflate(LayoutInflater.from(context))
Использовать
addView
чтобы добавить представление в иерархию как:addView(binding.root)
Примечание: если вы расширяетесь с ConstraintLayout
(является родительским классом), затем используйте набор ограничений
Вы можете сразу же инициализировать свойство привязки представления
private val binding = CustomViewBinding.inflate(LayoutInflater.from(context), this, true)
Если вы пытаетесь использовать привязку представления с корневым представлением, это работает для меня:
class CustomView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : ConstraintLayout(context, attrs, defStyleAttr) {
private lateinit var binding: CustomViewBinding
override fun onFinishInflate() {
super.onFinishInflate()
binding = CustomViewBinding.bind(this)
}
}
Вы можете использовать DataBindingUtil
binding = DataBindingUtil.inflate(
LayoutInflater.from(context),
R.layout.your_layout_id,
this,
true
)
Это самый простой ответ котлина, который я могу придумать. Это настраиваемое представление, которое просто обертывает один TextView и предоставляет
update(s:String)
функция для обновления текста.
<!-- view_stub.xml -->
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<TextView android:id="@+id/myTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</layout>
// StubView.kt
class StubView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : FrameLayout(context,attrs,defStyleAttr) {
val binding = ViewStubBinding.inflate(context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater)
.also { addView(it.root) }
fun update(updatedText: String) {
binding.myTextView.text = updatedText
}
}
В этом ответе мне нравятся две вещи:
binding
этоval
вместоvar
. Я стараюсь ограничить количествоvar
как можно больше.- В
addView
тесно связан сval binding
используяalso {}
функция области видимости вместоinit {}
предложение, создавая экземплярView
чувствую себя гораздо более декларативным.
Можно утверждать, что
addView()
действительно побочный эффект и должен быть
init {}
раздел, чтобы он был отделен от объявления
binding
val. Я бы сказал наоборот - объявив
val
затем скармливание его части кода, которая в нем нуждается, не кажется мне побочным эффектом.