Android中使用TextView自定义样式时属性解析错误的解决方法
问题解决:Android弹窗加载布局时自定义属性解析失败
问题背景
自定义主题MyAppTheme中定义了一系列自定义属性,其中planesTextColor被用于CustomTextViewStyle的文本颜色配置:
<style name="MyAppTheme" parent="@style/Theme.AppCompat.Light.NoActionBar"> <!-- 系统主题属性省略 --> <item name="planesTextColor">@color/colorAmber700</item> <!-- 其他自定义属性省略 --> </style> <style name="CustomTextViewStyle" parent="@style/Widget.AppCompat.TextView"> <item name="android:textColor">?planesTextColor</item> </style>
弹窗布局help_popup.xml中使用了该自定义样式:
<TextView android:id="@+id/popup_help_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="10dip" android:textSize="20dp" android:textStyle="bold" style="@style/CustomTextViewStyle" android:text="@string/help"/>
弹窗通过applicationContext加载布局:
val inflater = m_Context.getSystemService(AppCompatActivity.LAYOUT_INFLATER_SERVICE) as LayoutInflater val popupView = inflater.inflate(R.layout.help_popup, null)
此时抛出错误:
Caused by: java.lang.UnsupportedOperationException: Failed to resolve attribute at index 5: TypedValue{t=0x2/d=0x7f040323 a=6} at android.content.res.TypedArray.getColorStateList(TypedArray.java:596) at android.widget.TextView.readTextAppearance(TextView.java:3961)
但在Fragment中使用相同样式却正常工作,Fragment布局加载方式为:
binding = FragmentLoginBinding.inflate(inflater, container, false)
问题原因
applicationContext使用的是应用默认主题,而非你自定义的MyAppTheme,而planesTextColor这类自定义属性仅在MyAppTheme中定义,因此LayoutInflater解析布局时无法找到属性定义,导致报错。
Fragment能正常工作是因为它的LayoutInflater继承了所在Activity的主题,而Activity已应用MyAppTheme。
解决方案
方案1:改用Activity上下文
将弹窗初始化时传入的上下文改为当前Activity实例,而非applicationContext:
val helpPopup = HelpPopup(this@YourActivity, m_MainLayout, mSelectedItem, ::startTutorialFragment)
这样LayoutInflater会自动使用Activity的自定义主题,正确解析自定义属性。
方案2:手动为LayoutInflater设置自定义主题
如果必须使用applicationContext,可以克隆LayoutInflater并绑定自定义主题:
val inflater = LayoutInflater.from(m_Context).cloneInContext(ContextThemeWrapper(m_Context, R.style.MyAppTheme)) val popupView = inflater.inflate(R.layout.help_popup, null)
方案3:直接引用颜色资源(不推荐)
若不需要主题切换能力,可修改CustomTextViewStyle直接使用颜色资源:
<style name="CustomTextViewStyle" parent="@style/Widget.AppCompat.TextView"> <item name="android:textColor">@color/colorAmber700</item> </style>
此方法会丧失主题切换灵活性,仅适合固定配色场景。
内容的提问来源于stack exchange,提问作者Cristi
相关产品推荐
相关产品推荐

