花了一整天的时间试图弄清楚这一点之后,我几乎肯定这是材料组件库中的一个错误。这是我的配置的相关部分(删除了不相关的元素):
styles.xml:
<style name="MaterialAppTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryVariant">@color/colorPrimary900</item>
<item name="colorSecondary">@color/colorSecondary</item>
<item name="colorSecondaryVariant">@color/colorSecondary900</item>
<item name="android:statusBarColor">@android:color/transparent</item>
</style>
AndroidManifest:
<application
android:name=".AndroidApplication"
android:theme="@style/MaterialAppTheme">
MainActivity:
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:launchMode="singleTop"
android:theme="@style/MaterialAppTheme">
依赖版本:
materialComponents: '1.1.0-alpha02',
constraintLayout : '2.0.0-alpha3',
appCompat : '1.1.0-alpha01'
我在向登录页面添加MaterialButton时没有问题。问题始于我的MainActivity的第一个列表片段。尝试以MaterialCardView作为每个项目的根目录显示回收者视图项目时,出现ThemeEnforcement错误。我尝试添加MaterialTextButton时也是如此。这是我的MaterialCardView xml声明的样子:
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/tripCard"
style="@style/Widget.MaterialComponents.CardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
card_view:cardBackgroundColor="@color/colorSurface"
card_view:cardCornerRadius="@dimen/widget_corner_radius"
card_view:cardElevation="@dimen/card_elevation">
在MaterialComponents库中进行断点处理时,我注意到它有时无法验证主题。以下是一些显示库失败代码的代码(在ThemeEnforcement.java中):
if (enforceMaterialTheme) {
TypedValue isMaterialTheme = new TypedValue();
boolean resolvedValue =
context.getTheme().resolveAttribute(R.attr.isMaterialTheme, isMaterialTheme, true);
if (!resolvedValue
|| (isMaterialTheme.type == TypedValue.TYPE_INT_BOOLEAN && isMaterialTheme.data == 0)) {
// If we were unable to resolve isMaterialTheme boolean attribute, or isMaterialTheme is
// false, check for Material Theme color attributes
checkMaterialTheme(context);
}
}
public static void checkMaterialTheme(Context context) {
checkTheme(context, MATERIAL_CHECK_ATTRS, MATERIAL_THEME_NAME);
}
private static final int[] MATERIAL_CHECK_ATTRS = {R.attr.colorPrimaryVariant};
据我所知,Theme Enforcer尝试解析isMaterialTheme属性(尽管在这种情况下它可能有时可以做到),然后继续进行操作并检查是否存在实质性主题颜色属性(检查colorPrimaryVariant)并再次失败(我也在应用程序主题中定义了它。)
如果有人有解决方案或任何建议,我将继续提交错误,将不胜感激!
答案 0 :(得分:2)
要跟进评论:使用从正确主题的LayoutInflater
中检索到的Context
是很重要的。应用程序上下文将无法满足此要求。
好消息是您不必担心将上下文注入适配器。这不是立即显而易见的,但是适配器提供了获得正确上下文所需的一切。
看看onCreateViewHolder()
骨架:
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
// ...
}
所有View
实例都有一个getContext()
方法,并且保证parent
参数为非null ...因此您可以从父级检索上下文并将其用于获取您的LayoutInflater:
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View itemView = inflater.inflate(R.layout.my_item_view, parent, false);
return new MyViewHolder(itemView);
}
类似地,在ViewHolder
内,您可以使用相同的技术来获取上下文对象。每个ViewHolder
实例都有一个itemView
字段,保证该字段为非空,因此您可以从中检索上下文。
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
Context context = holder.itemView.getContext();
// ...
}