I've got a problem while adding custom view dynamically.
Below are my current codes.
attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="SkillItemView">
<attr name="skill" format="string" />
<attr name="proficiency" format="integer" />
</declare-styleable>
</resources>
skill_item.view.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/progress_item_incomplete"
android:paddingTop="@dimen/list_row_margin_default"
android:paddingBottom="@dimen/list_row_margin_default"
android:paddingLeft="@dimen/text_padding"
android:paddingRight="@dimen/text_padding"
android:layout_margin="@dimen/list_row_margin_default">
<TextView
android:id="@+id/text_skill"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/colorBlack_2"
android:textStyle="italic"
android:text="Art Direction" />
</LinearLayout>
SkillItemView.kt
class SkillItemView (context: Context, attrs: AttributeSet): LinearLayout(context, attrs) {
init {
inflate(context, R.layout.skill_item_view, this)
val textSkill: TextView = findViewById(R.id.text_skill)
val attributes = context.obtainStyledAttributes(attrs, R.styleable.SkillItemView)
textSkill.text = attributes.getString(R.styleable.SkillItemView_skill)
attributes.recycle()
}
}
And I am going to add this view dynamically in adapter
for (skill in profileList[position].getSkills()) {
var skillView = SkillItemView(context, ???)
parentView.addView(skillView)
}
The SkillItemView Constructor has 2 parameters. Context and AttributeSet. (See ??? in above codes)
What I have to write for AttributeSet?
You have to declare attrs
attribute as nullable AttributeSet?
. In that case you can instantiate SkillItemView
in the adapter:
class SkillItemView(context: Context, attrs: AttributeSet? = null) : LinearLayout(context, attrs) {
init {
inflate(context, R.layout.skill_item_view, this)
val textSkill: TextView = findViewById(R.id.text_skill)
if (attrs != null) {
val attributes = context.obtainStyledAttributes(attrs, R.styleable.SkillItemView)
textSkill.text = attributes.getString(R.styleable.SkillItemView_skill)
attributes.recycle()
}
}
}
...
for (skill in profileList[position].getSkills()) {
var skillView = SkillItemView(context)
parentView.addView(skillView)
}
If you want to pass parameters while creating SkillItemView
dynamically, you can create a custom constructor:
class SkillItemView : LinearLayout {
constructor(context: Context, attrs: AttributeSet? = null) : super(context, attrs) {
inflate(context, R.layout.skill_item_view, this)
val textSkill: TextView = findViewById(R.id.text_skill)
if (attrs != null) {
val attributes = context.obtainStyledAttributes(attrs, R.styleable.SkillItemView)
textSkill.text = attributes.getString(R.styleable.SkillItemView_skill)
attributes.recycle()
}
}
constructor(context: Context, skill:String? = null, proficiency: Int? = null) : super(context) {
inflate(context, R.layout.skill_item_view, this)
if (skill != null) {
val textSkill: TextView = findViewById(R.id.text_skill)
textSkill.text = skill
}
}
}
...
for (skill in profileList[position].getSkills()) {
var skillView = SkillItemView(context, "test skill")
parentView.addView(skillView)
}