Как использовать привязку представлений для пользовательских представлений

Привязка просмотра была выпущена с 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)
    }

}
  1. Автоматически созданный класс: result_profile.xml -> ResultProfileBinding(название макета, с добавлением Binding)
  2. Надуть переплет

    ResultProfileBinding.inflate(LayoutInflater.from(context))
    
  3. Использовать 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
    }
}

В этом ответе мне нравятся две вещи:

  1. binding это val вместо var. Я стараюсь ограничить количество varкак можно больше.
  2. В addView тесно связан с val binding используя also {} функция области видимости вместо init {} предложение, создавая экземпляр View чувствую себя гораздо более декларативным.

Можно утверждать, что addView() действительно побочный эффект и должен быть init {} раздел, чтобы он был отделен от объявления bindingval. Я бы сказал наоборот - объявив val затем скармливание его части кода, которая в нем нуждается, не кажется мне побочным эффектом.

Другие вопросы по тегам