I have a custom layout as below
class CustomComponent : FrameLayout {
    constructor(context: Context?) : super(context)
    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) {
        initAttrs(attrs)
    }
    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
        initAttrs(attrs)
    }
    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes) {
        initAttrs(attrs)
    }
    init {
        LayoutInflater.from(context).inflate(R.layout.view_custom_component, this, true)
    }
    fun initAttrs(attrs: AttributeSet?) {
        val typedArray = context.obtainStyledAttributes(attrs, R.styleable.custom_component_attributes, 0, 0)
        my_title.text = resources.getText(typedArray
                .getResourceId(R.styleable.custom_component_attributes_custom_component_title, R.string.component_one))
        typedArray.recycle()
    }
}
Now for each constructor, I have to explicitly call initAttrs(attrs) as I can't find  way to access attrs in my init function.
Is there a way I could access attrs in init function, so I could call initAttrs(attrs) from init instead of having to explicitly call it in each of the constructor?
Constructors can be passed as arugments to methods using a method reference, somewhat like a function pointer in C++. This can be a Function type with one argument or a BiFunction type with two arguments, either way its a lambda returning a class of the type it constructs.
This method has four parameters: the loan amount, the interest rate, the future value and the number of periods. The first three are double-precision floating point numbers, and the fourth is an integer.
Argument Names When you declare an argument to a method or a constructor, you provide a name for that argument. This name is used within the method body to refer to the data. The name of an argument must be unique in its scope.
Remember, every class must have a constructor, even if it only relies on the default constructor.
Use a constructor with default arguments:
class CustomComponent @JvmOverloads constructor(
  context: Context, 
  attrs: AttributeSet? = null, 
  defStyle: Int = 0
) : FrameLayout(context, attrs, defStyle) {
    fun init {
      // Initialize your view
    }
}
The @JvmOverloads annotation tells Kotlin to generate three overloaded constructors so they can be called in Java as well.
In your init function, attrs becomes available as a nullable type:
fun init {
  LayoutInflater.from(context).inflate(R.layout.view_custom_component, this, true)
  attrs?.let {
        val typedArray = context.obtainStyledAttributes(it, R.styleable.custom_component_attributes, 0, 0)
        my_title.text = resources.getText(typedArray
                .getResourceId(R.styleable.custom_component_attributes_custom_component_title, R.string.component_one))
        typedArray.recycle()
  }
}
Note the usage of it in the let block.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With