I create a custom view in Kotlin, and would like to access it's Attributes Resource.
Below is my code
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) } } } }
Note that this will error in the attrs
in the init function. I'm wondering how to access the attrs
?
A well-designed custom view is much like any other well-designed class. It encapsulates a specific set of functionality with an easy to use interface, it uses CPU and memory efficiently, and so on. In addition to being a well-designed class, though, a custom view should: Conform to Android standards.
AttributeSet (Android Docs)A collection of attributes, as found associated with a tag in an XML document. Basically if you are trying to create a custom view, and you want to pass in values like dimensions, colors etc, you can do so with AttributeSet .
You cannot access a secondary constructor parameter from an init
block. But there're at least two ways how you can implement similar functionality.
The first approach is using a single primary constructor with default parameters instead of multiple secondary constructors. In this case you have to apply the @JvmOverloads
annotation to the constructor in order to make Kotlin generate three different constructors.
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 the seconds approach is two chain constructors and move the init block content into the constructor with three arguments.
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) } } } }
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