Котлин: как получить доступ к 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)
            }
        }
    }
}