通过overlay切换多主题遇到layout里这个组件inflate异常 <com.google.android.material.appbar.AppBarLayout
Caused by: java.lang.IllegalArgumentException: The style on this component requires your app theme to be Theme.AppCompat (or a descendant).
做了几次尝试:
1.将activity主题换为Theme.AppCompat // 失败

2.将application主题也换位Theme.AppCompat // 失败

3.将<com.google.android.material.appbar.AppBarLayout去掉 // OK,但功能需要不能去掉

4.研究源码,找到异常点
com.google.android.material.internal.ThemeEnforcement#checkAppCompatTheme

public static void checkAppCompatTheme(@NonNull Context context) {
  checkTheme(context, APPCOMPAT_CHECK_ATTRS, APPCOMPAT_THEME_NAME);
}

这个组件会检测主题,通过代码看到
 

private static final int[] APPCOMPAT_CHECK_ATTRS = {R.attr.colorPrimary};

也就是要检测主题colorPrimary属性

private static void checkTheme(
    @NonNull Context context, @NonNull int[] themeAttributes, String themeName) {
  if (!isTheme(context, themeAttributes)) {
    throw new IllegalArgumentException(
        "The style on this component requires your app theme to be "
            + themeName
            + " (or a descendant).");
  }
}

这里可以看到异常信息,关键点在于com.google.android.material.internal.ThemeEnforcement#isTheme
 

private static boolean isTheme(@NonNull Context context, @NonNull int[] themeAttributes) {
  TypedArray a = context.obtainStyledAttributes(themeAttributes);
  for (int i = 0; i < themeAttributes.length; i++) {
    if (!a.hasValue(i)) {
      a.recycle();
      return false;
    }
  }
  a.recycle();
  return true;
}

从方法名可以看出是判断是否主题,这里有点不是太明白为啥是这个名字,不过无关紧要,这个方法就是检测传进来的主题属性是否在当前主题里都存在,如果有一个不存在则认为不是主题,从上面可以看出其实就是检测R.attr.colorPrimary属性是否存在,不存在就让你异常,所以解决办法自然有了,那就是在主题里添加这个属性,不过一般加三个,单独加colorPrimary也可以解决问题

<item name="colorAccent">@color/color_cursor</item>
<item name="colorPrimaryDark">@color/primary_dark_material_dark</item>
<item name="colorPrimary">@color/primary_material_dark</item>
Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐