김지섭
김지섭

Reputation: 21

How can I use val from secondary constructor?

I'm making my custom view. Before I add constructor contain defStyleRes, the original constructor is primary constructor. so I can use attrs at init. How can I use it now?

class StoreTotalPanel : RelativeLayout {
    @JvmOverloads
    constructor(
        context: Context,
        attrs: AttributeSet? = null,
        defStyleAttr: Int = 0)
            : super(context, attrs, defStyleAttr)

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    constructor(
        context: Context,
        attrs: AttributeSet?,
        defStyleAttr: Int,
        defStyleRes: Int)
            : super(context, attrs, defStyleAttr, defStyleRes)

    init {
        LayoutInflater.from(context)
            .inflate(layout.panel_store_total, this, true)

        attrs?.let { // <- Here is error
            val typedArray = context.obtainStyledAttributes(it, R.styleable.custom_card_view)
            val myString = typedArray.getString(R.styleable.custom_card_view_command)
        }
    }
    ...
}

Upvotes: 1

Views: 79

Answers (2)

Michiel
Michiel

Reputation: 768

It is because init relies on the primary constructor. Since there is none, it fails to find attrs. The solution is to replace init with your own function, which is called by both secondary connstructors:

class StoreTotalPanel : RelativeLayout {

    @JvmOverloads
    constructor(
        context: Context,
        attrs: AttributeSet? = null,
        defStyleAttr: Int = 0
    ) : super(context, attrs, defStyleAttr) {
        init(context, attrs)
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    constructor(
        context: Context,
        attrs: AttributeSet?,
        defStyleAttr: Int,
        defStyleRes: Int
    ) : super(context, attrs, defStyleAttr, defStyleRes) {
        init(context, attrs)
    }


    private fun init(context: Context, attrs: AttributeSet?) {
        LayoutInflater.from(context).inflate(layout.panel_store_total, this, true)

        attrs?.let {
            val typedArray = context.obtainStyledAttributes(it, R.styleable.custom_card_view)
            val myString = typedArray.getString(R.styleable.custom_card_view_command)
        }
    }
}

Be aware that inflate() returns a view which you do not use yet; the layout will be empty with this code snippet.

Upvotes: 2

Bruno Martins
Bruno Martins

Reputation: 1436

Have you tried to create a val on constructor itself?

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
    constructor(
        context: Context,
        attrs: AttributeSet?,
        defStyleAttr: Int,
        private val defStyleRes: Int)
            : super(context, attrs, defStyleAttr, defStyleRes)

Upvotes: 0

Related Questions