Kotlin: Как получить доступ к Attrs для CustomView
Я создаю пользовательский вид в Kotlin и хотел бы получить к нему доступ атрибут Resource.
Ниже мой код
class CustomCardView : FrameLayout {
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
init {
LayoutInflater.from(context).inflate(R.layout.view_custom_card, this, true)
if (attrs != null) {
val a = context.obtainStyledAttributes(attrs, R.styleable.custom_card_view)
if (a.hasValue(R.styleable.custom_card_view_command)) {
var myString = a.getString(R.styleable.custom_card_view_command)
}
}
}
}
Обратите внимание, что это будет ошибка в attrs
в функции init. Мне интересно, как получить доступ к attrs
?
Ответы
Ответ 1
Вы не можете получить доступ к второму конструкторному параметру из блока init
. Но есть как минимум два способа реализации аналогичной функциональности.
В первом подходе используется один первичный конструктор с параметрами по умолчанию вместо нескольких вторичных конструкторов. В этом случае вы должны применить аннотацию @JvmOverloads
к конструктору, чтобы заставить Kotlin генерировать три разных конструктора.
class CustomCardView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : FrameLayout {
init {
LayoutInflater.from(context).inflate(R.layout.view_custom_card, this, true)
if (attrs != null) {
val a = context.obtainStyledAttributes(attrs, R.styleable.custom_card_view)
if (a.hasValue(R.styleable.custom_card_view_command)) {
var myString = a.getString(R.styleable.custom_card_view_command)
}
}
}
}
Подход секунд - это два цепных конструктора и перемещение содержимого блока init в конструктор с тремя аргументами.
class CustomCardView : FrameLayout {
constructor(context: Context) :
this(context, null)
constructor(context: Context, attrs: AttributeSet) :
this(context, attrs, 0)
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) :
super(context, attrs, defStyleAttr) {
LayoutInflater.from(context).inflate(R.layout.view_custom_card, this, true)
if (attrs != null) {
val a = context.obtainStyledAttributes(attrs, R.styleable.custom_card_view)
if (a.hasValue(R.styleable.custom_card_view_command)) {
var myString = a.getString(R.styleable.custom_card_view_command)
}
}
}
}
Ответ 2
Почему бы вам просто не пропустить эти подробные конструкторы со значениями по умолчанию и сделать это так:
class CustomCardView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {
init {
inflate(context, R.layout.view_custom_card, this)
attrs?.let {
val typedArray = context.obtainStyledAttributes(it, R.styleable.custom_card_view)
val myString = typedArray.getString(R.styleable.custom_card_view_command)
}
}
Ответ 3
Адаптируя свой код, я думаю, вы также можете сделать что-то вроде этого:
class CustomCardView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) :
FrameLayout(context, attrs, defStyleAttr) {
constructor(context: Context) : this(context, null)
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
init {
LayoutInflater.from(context).inflate(R.layout.view_custom_card, this, true)
if (attrs != null) {
val a = context.obtainStyledAttributes(attrs, R.styleable.custom_card_view)
if (a.hasValue(R.styleable.custom_card_view_command)) {
var myString = a.getString(R.styleable.custom_card_view_command)
}
a.recycle()
}
}
}
Ответ 4
Это немного многословно, но должно работать как положено при любых условиях:
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.FrameLayout
class CustomCardView: FrameLayout {
constructor(context: Context) : super(context) {
initialize(context, null)
}
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
initialize(context, attrs)
}
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
initialize(context, attrs)
}
private fun initialize(context: Context, attrs: AttributeSet?) {
LayoutInflater.from(context).inflate(R.layout.view_custom_card, this, true)
attrs?.let {
val a = context.obtainStyledAttributes(it, R.styleable.custom_card_view)
if (a.hasValue(R.styleable.custom_card_view_command)) {
var myString = a.getString(R.styleable.custom_card_view_command)
}
}
}
}