Котлин: как получить доступ к Attrs для CustomView
Я создаю пользовательское представление в Kotlin и хотел бы получить доступ к его ресурсу атрибутов.
ниже мой код
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
?
3 ответов
вы не можете получить доступ к вторичному параметру конструктора из 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)
}
}
}
}
an секундный подход-два цепные конструкторы и переместить содержимое блока 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)
}
}
}
}
адаптируя свой код, я думаю, вы также можете сделать что-то вроде этого:
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()
}
}
}
Это немного многословно, но должно работать, как ожидалось, при всех условиях:
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)
}
}
}
}