Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to access constructor argument that's not member variable in init function?

Tags:

android

kotlin

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?

like image 812
Elye Avatar asked May 27 '17 06:05

Elye


People also ask

How do you pass a constructor as an argument in Java?

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.

What parameters are required to pass to a class constructor?

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.

When declaring a parameter to a method or a constructor this is provided for that parameter?

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.

Does every class need a constructor Python?

Remember, every class must have a constructor, even if it only relies on the default constructor.


1 Answers

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.

like image 87
nhaarman Avatar answered Sep 26 '22 07:09

nhaarman