动态访问自定义 ViewGroup 实例中的子视图
我想创建一个自定义 CardView,在创建实例时可以在其中添加其他子组件,如下所示:
<com.example.app.CardComponent
tools:context=".MainActivity"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:title_text="title"
app:description_text="description"
app:clickable_button="true"
xmlns:android="http://schemas.android.com/apk/res/android">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="testButton"/>
</com.example.app.CardComponent>
其中 CardComponent 是我创建的自定义 CardView,testButton 是我想要插入到 CardComponent 中的附加视图的示例。我想将其插入到这一层中,而不是直接插入到 CardComponent 的 xml 文件中,以实现自定义目的和可重用性。
问题是我不知道如何动态访问自定义视图组实例的子视图(例如 CardComponent 类中的 testButton),以便将它们动态添加到布局等。
以下是 CardComponent 类和 xml 文件以及CardComponent 的 attr 文件。
class CardComponent @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) :
MaterialCardView(context, attrs, defStyleAttr) {
private val bindings: CardComponentBinding = CardComponentBinding.inflate(LayoutInflater.from(context), this, true)
init {
attrs?.let {
val styledAttributes = context.obtainStyledAttributes(it, R.styleable.CardComponent)
val titleText = styledAttributes.getString(R.styleable.CardComponent_title_text)
bindings.cardTitle.text = titleText
val descriptionText = styledAttributes.getString(R.styleable.CardComponent_description_text)
bindings.cardDescription.text = descriptionText
val clickableButton = styledAttributes.getBoolean(R.styleable.CardComponent_clickable_button, false)
if (clickableButton){
bindings.cardDescriptionButton.setOnClickListener{
val v = bindings.retractableLayout.visibility
bindings.retractableLayout.visibility = if(v == GONE) VISIBLE else GONE
}
}
// Here I would have something like this but can't find a way to do it:
// val button = styledAttributes.getChild()
// bindings.relative_layout.addChild(button)
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:tools="http://schemas.android.com/tools">
<LinearLayout
android:animateLayoutChanges="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
tools:layout_editor_absoluteX="1dp"
tools:layout_editor_absoluteY="1dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/card_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:padding="15dp"/>
<Button
android:id="@+id/card_description_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:padding="15dp"
android:text="test"/>
</RelativeLayout>
<RelativeLayout
android:id="@+id/retractable_layout"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/card_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"/>
</RelativeLayout>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="CardComponent">
<attr name="title_text" format="string"/>
<attr name="description_text" format="string"/>
<attr name="clickable_button" format="boolean"/>
</declare-styleable>
</resources>
感谢您的帮助 !
I would like to create a Custom CardView where I can add additional child components when I create an instance as follows :
<com.example.app.CardComponent
tools:context=".MainActivity"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:title_text="title"
app:description_text="description"
app:clickable_button="true"
xmlns:android="http://schemas.android.com/apk/res/android">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="testButton"/>
</com.example.app.CardComponent>
where CardComponent is the custom CardView I created and testButton an example of an additional view I'd like to insert in my CardComponent. I would like to insert it in this layer and not directly in the xml file of the CardComponent for customization purposes and reusability.
The problem is I don't know how to dynamically access child views of a custom viewgroup instance like this testButton in the CardComponent class in order to then dynamically add them to the layout, etc.
Here are the CardComponent class and xml file as well as the attr file for the CardComponent.
class CardComponent @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) :
MaterialCardView(context, attrs, defStyleAttr) {
private val bindings: CardComponentBinding = CardComponentBinding.inflate(LayoutInflater.from(context), this, true)
init {
attrs?.let {
val styledAttributes = context.obtainStyledAttributes(it, R.styleable.CardComponent)
val titleText = styledAttributes.getString(R.styleable.CardComponent_title_text)
bindings.cardTitle.text = titleText
val descriptionText = styledAttributes.getString(R.styleable.CardComponent_description_text)
bindings.cardDescription.text = descriptionText
val clickableButton = styledAttributes.getBoolean(R.styleable.CardComponent_clickable_button, false)
if (clickableButton){
bindings.cardDescriptionButton.setOnClickListener{
val v = bindings.retractableLayout.visibility
bindings.retractableLayout.visibility = if(v == GONE) VISIBLE else GONE
}
}
// Here I would have something like this but can't find a way to do it:
// val button = styledAttributes.getChild()
// bindings.relative_layout.addChild(button)
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:tools="http://schemas.android.com/tools">
<LinearLayout
android:animateLayoutChanges="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
tools:layout_editor_absoluteX="1dp"
tools:layout_editor_absoluteY="1dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/card_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:padding="15dp"/>
<Button
android:id="@+id/card_description_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:padding="15dp"
android:text="test"/>
</RelativeLayout>
<RelativeLayout
android:id="@+id/retractable_layout"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/card_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"/>
</RelativeLayout>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="CardComponent">
<attr name="title_text" format="string"/>
<attr name="description_text" format="string"/>
<attr name="clickable_button" format="boolean"/>
</declare-styleable>
</resources>
Thank you for your help !
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我的解决方案是使用 OnFinishInflate 方法,在该方法中获取 CardComponent 的子级(第一张图片),删除它们的父视图并将它们添加到我在自定义视图的 xml 文件中设置的正确布局(第三张图片) 。我最终跳过第一个子项,因为它是 MaterialCardView 的一个实例(这个子项代表我制作的自定义卡片,第三张图片),然后将所有剩余的子项添加到合适的位置。
My solution was to use the OnFinishInflate method where I get the children of my CardComponent (1st picture), I delete their parent view and add them to the correct layout I'd set up in the xml file of my custom view (3rd picture). I eventually skip the first child because it's an instance of MaterialCardView (this child represents the custom Card I made, 3rd picture) and then take all the remaining children and add them to the good spot.