如何创建自定义布局并向自定义布局类传递图片引用?
问题解决步骤
1. 修正属性定义(attr.xml)
将start_icon的格式从string改为reference,因为我们要引用drawable资源而非字符串:
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="SettingsElementView"> <attr name="title_text" format="string"/> <attr name="main_text" format="string"/> <attr name="start_icon" format="reference"/> <!-- 修改此处 --> </declare-styleable> </resources>
2. 替换ImageView为AppCompatImageView(推荐)
为了兼容srcCompat特性(比如矢量图支持),把布局中的ImageView替换为AppCompatImageView:
<androidx.appcompat.widget.AppCompatImageView android:id="@+id/settings_element_start_icon" android:layout_width="32dp" android:layout_height="32dp" android:layout_marginStart="4dp" android:layout_gravity="center" />
3. 修复自定义View的图标加载逻辑
原代码错误地将资源引用当作文件路径处理,现在改为获取资源ID并正确加载Drawable:
package com.example.dummyapp.view import android.content.Context import android.util.AttributeSet import android.view.LayoutInflater import android.widget.LinearLayout import android.widget.TextView import androidx.appcompat.widget.AppCompatImageView import com.example.dummyapp.R import androidx.core.content.ContextCompat class SettingsElementView @JvmOverloads constructor( context: Context, attributeSet: AttributeSet? = null, defStyleAttr: Int = 0, ) : LinearLayout(context, attributeSet, defStyleAttr) { private val mainText: TextView private val titleText: TextView private val iconView: AppCompatImageView init { LayoutInflater.from(context).inflate(R.layout.settings_element_view, this, true) mainText = findViewById(R.id.settings_element_textview) titleText = findViewById(R.id.settings_element_textview_title) iconView = findViewById(R.id.settings_element_start_icon) val typedArray = context.obtainStyledAttributes(attributeSet, R.styleable.SettingsElementView) val mainTextStr = typedArray.getString(R.styleable.SettingsElementView_main_text) val titleTextStr = typedArray.getString(R.styleable.SettingsElementView_title_text) // 获取图标资源ID,默认0表示未设置 val iconResId = typedArray.getResourceId(R.styleable.SettingsElementView_start_icon, 0) typedArray.recycle() mainText.text = mainTextStr titleText.text = titleTextStr // 加载图标 if (iconResId != 0) { // 方式1:用ContextCompat兼容不同Android版本 val drawable = ContextCompat.getDrawable(context, iconResId) iconView.setImageDrawable(drawable) // 方式2:直接设置资源ID,更简洁 // iconView.setImageResource(iconResId) } } fun setMainText(text: String) { mainText.text = text } // 新增动态设置图标的方法 fun setStartIcon(iconResId: Int) { if (iconResId != 0) { iconView.setImageResource(iconResId) } } }
问题根源说明
- 你之前将
start_icon的格式定义为string,但@drawable/xxx是资源引用,需要用reference格式才能正确解析。 - 原代码用
getString获取的是资源的字符串标识(比如@drawable/phone_icon),而Drawable.createFromPath()无法识别这种格式,导致图标加载失败。 - 改为
getResourceId获取资源ID后,通过ContextCompat.getDrawable()或setImageResource()就能正确加载drawable资源。
内容的提问来源于stack exchange,提问作者Artur
相关产品推荐
相关产品推荐

