细说 AppCompat 主题引发的坑:You need to use a Theme.AppCompat theme with this activity!
一般来说按照文档的建议去做,出现问题的概率很低。但很多人的情况不同,每每会发生意外状况,就比如这次没有使用 AppCompat 主题引发的坑!
AppCompat
框架作为 Jetpack
集合的基石,非常重要。Android Studio 上创建的默认项目都会自动集成 AppCompat 框架,并采用其提供的 AppCompatActivity
作为 Activity Base。
App 侧给 Activity 配置的主题一般扩展自 SDK 提供的系统主题或 AppCompat 提供的主题,前者的话极有可能引发一些 AppCompat 框架的使用异常。
非 AppCompat 主题引发了异常
如果配置的是扩展自 SDK 的主题,Activity 必然无法启动,并发生如下异常:
RuntimeException: Unable to start activity xxx: java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity.
原因很简单,AppCompat 框架的诸多后续处理紧密关联该主题配置的属性。因此在加载画面前将严格检查是否采用了 AppCompat 系主题,否则将抛出异常。
class AppCompatDelegateImpl ... {private ViewGroup createSubDecor() {TypedArray a = mContext.obtainStyledAttributes(R.styleable.AppCompatTheme);if (!a.hasValue(R.styleable.AppCompatTheme_windowActionBar)) {a.recycle();throw new IllegalStateException("You need to use a Theme.AppCompat theme (or descendant) with this activity.");}...return subDecor;}
}
如何解决这个问题呢?
主题改为扩展自 AppCompat 系主题。 但如果自己的主题覆写的地方很多,这将耗费很长时间,而且很多自定义的属性可能还会和 AppCompat 主题产生冲突,需要逐个分析、细细调整
Activity 改用 SDK 版本,即
android.app.Activity
。 但随着 Jetpack 框架的日渐成熟和流行,很多重要的框架非常依赖于 AppCompatActivity 的支持,比如Lifecycle
框架、ViewModel
框架、Preference
等。这可能导致其他的框架功能发生问题,也不是很好AppCompat 哪里有兼容性问题解决哪里的回避方案。 比如上面的异常其实就是检查是否配置了 AppCompat 框架提供的
windowActionBar
属性而已,那么我们在自己的主题里加上该属性的引用就可以了。不好的地方就在于,很多不是异常的 UI 展示问题,如果没有发现的话,很容易被忽略。也就是说,这个方案容易改得不全,产生遗漏
前2个方案没啥好说,我们具体来分析下第3个方案具体怎么操作。
如何使用非 AppCompat 主题
在扩展自 SDK 的主题里额外配置下 windowActionBar 属性即可,true 或者 false 依需而定。
<style name="Theme.MaterialExtension" parent="android:Theme.Material.Light">...
</style><style name="Theme.MaterialExtension.Customize"><item name="windowActionBar">true</item>
</style>
成功启动后的 Activity 画面:
等等,复选框设置条目的 CheckBox
怎么不见了?
查看了 CheckBoxPreference
的源码,没有发现什么特别的处理。
通过 Layout Inspector
看了下布局,发现了一点线索:视图当中,CheckBox 的实例是存在的,只是 Width 变成了0。而且 CheckBox 的实现类名变成了 AppCompatCheckBox
。
突然想起 AppCompat 框架为了让低版本系统能使用上诸如 Auto Size
和 Background Tint
的新功能,会给 SDK 的大部分控件重新扩展一个 AppCompat 前缀的同名控件。所以猜测,AppCompatCheckBox 依赖的兼容性属性,我们的主题里没有配置。
如何兼容 AppCompat 控件
来看下 AppCompatCheckBox 控件的源码,我们发现构造函数里针对复选按钮有特别的实现。
public AppCompatCheckBox( ... ) {...mCompoundButtonHelper = new AppCompatCompoundButtonHelper(this);mCompoundButtonHelper.loadFromAttributes(attrs, defStyleAttr);
}
具体就是通过 AppCompatCompoundButtonHelper 去加载 buttonCompat 属性配置的复选按钮图片。
void loadFromAttributes(@Nullable AttributeSet attrs, int defStyleAttr) {TintTypedArray a =TintTypedArray.obtainStyledAttributes(mView.getContext(), attrs,R.styleable.CompoundButton, defStyleAttr, 0);ViewCompat.saveAttributeDataForStyleable(mView, mView.getContext(),R.styleable.CompoundButton, attrs, a.getWrappedTypeArray(), defStyleAttr, 0);try {boolean buttonDrawableLoaded = false;if (a.hasValue(R.styleable.CompoundButton_buttonCompat)) {final int resourceId = a.getResourceId(R.styleable.CompoundButton_buttonCompat, 0);if (resourceId != 0) {try {mView.setButtonDrawable(AppCompatResources.getDrawable(mView.getContext(), resourceId));buttonDrawableLoaded = true;} ...}}...} finally {a.recycle();}
}
很明显,我们的主题里没有配置这个属性,所以 CheckBox 显示不出来。
当然可以直接在我们的主题里配置这个属性,但如果能和 AppCompat 框架设置一样的,省去了提供复选框资源,岂不更好。
<declare-styleable name="CompoundButton"><attr name="android:button"/><!-- Compat attr to load backported drawable types --><attr format="reference" name="buttonCompat"/>...
</>
通过搜索发现 AppCompat 主题给 CheckBox 控件配置的 Style 里使用了 buttonCompat
的 Attr。
<style name="Base.Widget.AppCompat.CompoundButton.CheckBox" parent="android:Widget.CompoundButton.CheckBox"><item name="android:button">?android:attr/listChoiceIndicatorMultiple</item><item name="buttonCompat">?attr/listChoiceIndicatorMultipleAnimated</item><item name="android:background">?attr/controlBackground</item>
</style><style name="Widget.AppCompat.CompoundButton.CheckBox" parent="Base.Widget.AppCompat.CompoundButton.CheckBox"/><style name="Base.V7.Theme.AppCompat.Light" parent="Platform.AppCompat.Light"><item name="checkboxStyle">@style/Widget.AppCompat.CompoundButton.CheckBox</item>
</style>
这样的话,在我们的主题里同样应用这个 Style 就行了。
<style name="Theme.MaterialExtension.Customize">...<item name="checkboxStyle">@style/Widget.AppCompat.CompoundButton.CheckBox</item>
</style>
更快速的兼容方法
如果发现哪个控件有问题,都像上面的办法一样去查的话着实花时间。其实直接到 AppCompat 主题的实现里搜索控件相关的兼容性 Style,拷贝过来即可。
比如一步步找到 AppCompat 主题的具体实现,在里面搜索得到 CheckBox 关键字的 Style。
<style name="Theme.AppCompat.DayNight.DarkActionBar" parent="Theme.AppCompat.Light.DarkActionBar"/><style name="Theme.AppCompat.Light.DarkActionBar" parent="Base.Theme.AppCompat.Light.DarkActionBar"/><style name="Base.Theme.AppCompat.Light.DarkActionBar" parent="Base.Theme.AppCompat.Light"><style name="Base.Theme.AppCompat.Light" parent="Base.V7.Theme.AppCompat.Light"><style name="Base.V7.Theme.AppCompat.Light" parent="Platform.AppCompat.Light">...<item name="editTextStyle">@style/Widget.AppCompat.EditText</item><item name="editTextBackground">@drawable/abc_edit_text_material</item><item name="editTextColor">?android:attr/textColorPrimary</item>...<!-- CheckBox 的兼容性 Style 藏在这里 --><item name="checkboxStyle">@style/Widget.AppCompat.CompoundButton.CheckBox</item>
</style>
注意
除了 AppCompatActivity,AppCompat 框架里提供的 AppCompatDialog
同样也有主题的限制,需要留意一下。AppCompatDialog 内视图发生兼容问题的话, 和 Activity 的 AppCompat 控件一样处理。
结语
针对非 AppCompat
主题的使用问题有3种解决方案:
主题改为扩展自 AppCompat 系主题
Activity 改用 SDK 版本的
android.app.Activity
手动解决AppCompat 的兼容性问题
毋庸置疑的是 AppCompat 框架对主题的限制源于后续的 UI 逻辑与其紧密相连,所以最佳解决办法肯定是方案1,即提供 AppCompat 系主题。
- 如果确实不需要
Jetpack
其他框架的协同(虽然这极不可能),那么可以选择方案2 - 如果现有主题太过庞大,一时半会儿无法切换到 AppCompat 主题,而且影响的画面很少、不复杂。那么可以试试方案3去逐个解决
推荐阅读
AppCompat发布两年了,还没了解?
细说 AppCompat 主题引发的坑:You need to use a Theme.AppCompat theme with this activity!相关推荐
- android style边界显示兼容问题,android – IDE“无法解析@ style/Theme.Appcompat”时使用v7兼容性支持主题...
这不是一个真正的问题,因为我的项目仍然构建和运行正确(使用gradle),但我有麻烦让Android Studio来识别在API 18 SDK中发布的应用程序兼容性主题(允许操作栏支持android ...
- Theme.AppCompat无全屏主题解决办法
V7包中的Theme.AppCompat主题系列中并没有全屏样式,这个是为什么,只有作者知道-- 解决办法: 自定义主题 <style name="Theme.AppCompat.Li ...
- 【小坑】Android 实现对话框会报错 (You need to use a Theme.AppCompat theme (or descendant) with this activity)
效果演示 有的时候,我们想Activity以小窗口的形式展示. 其实只需要添加上这么一行就可以了. android:theme="@style/Theme.AppCompat.Light.D ...
- Android 10深色主题适配踩坑记录
1. 问题简述 Android 10 推出了深色主题,便于用户根据白天和夜晚自由切换合适的主题.在适配的过程中,要特别注意,切换主题会导致当前activity被重建,也就是会重新走一遍Activity ...
- 无法为新的Android ActionBar支持找到Theme.AppCompat.Light
本文翻译自:Can't Find Theme.AppCompat.Light for New Android ActionBar Support I am trying to implement th ...
- 【错误记录】Android 应用运行报错 ( You need to use a Theme.AppCompat theme (or descendant) with this activity. )
文章目录 一.报错信息 二.解决方案 一.报错信息 运行 Android 应用时 , 报错 ; 报错信息如下 : 2021-08-04 21:04:12.067 26338-26338/com.exa ...
- Android关于Theme.AppCompat相关问题的深入分析
先来看这样一个错误: No resource found that matches the given name '@style/Theme.AppCompat.Light' 对于这个错误,相信大部分 ...
- Android安卓开发-'Theme.AppCompat.Light'无法找到的解决方案
error: Error retrieving parent for item: No resource found that matches the given name 'Theme.AppCom ...
- [android] No resource found that matches the given name 'Theme.AppCompat.Light'
在整合android过程中导入别人的项目出现下面的错误: <style name="AppBaseTheme" parent="Theme.AppC ...
- Android之You need to use a Theme.AppCompat theme (or descendant) with this activity.
1 问题 点击activity的时候,崩溃日志如下 You need to use a Theme.AppCompat theme (or descendant) with this activity ...
最新文章
- unsupported operand type(s) for + NoneType and int
- 导入python库linux_Linux下Python安装PyMySQL成功,但无法导入的问题
- c语言 编码规范 C Coding Standard
- java 环境网站404_配置JavaWeb项目环境,修改jdbc配置文件,浏览器报404错误,不修改可以正常部署,jdbc没有改错...
- 工作中用到的java反射机制_(转)JAVA-反射机制的使用
- ECCV2020论文-稀疏性表示-Neural Sparse Representation for Image Restoration翻译
- MySQL也有潜规则 – Select 语句不加 Order By 如何排序?
- 深入浅出Java多线程
- label里面的文字换行_批量识别图中文字自动命名,让你1秒找到骚图!太强大了!...
- Weka--Explorer基本流程
- linux 列出指定目录下所有文件的 列表集合
- OpenGL超级宝典 纹理(一)
- java 苹果支付(内购)
- 《Linux内核设计与实现》读书笔记(四)- 进程的调度
- 页脚代码html,博客园页脚 HTML 代码 .html
- JavaScript的prompt用法
- 我的世界中国版服务器账号封了,Hypixel中国版服务器停止运营公告
- 使用pandas对excel表格筛选
- ALLOCATE语句分配FORTRAN动态数组方法
- kali内开启键盘背光
热门文章
- CSF视频文件格式转换
- 修改vscode代码字体大小
- 基于Android的海康威视的二次开发
- 绿联串口线linux驱动下载,绿联USB转DB9串口线驱动 V1.6.1 Mac版
- python 繁体字与简体字互相转换
- Java学习笔记2——java的安装和配置
- Flash loader demo下载与使用之最小系统STM32C8T6使用USB转TTL串口下载
- 计算器与计算机小键盘的使用,会计神器!用上Cherry轴的计算器还能当小键盘用...
- javascript 推拉式菜单
- 仿探探交友小程序V7.0.2 完整安装包+小程序前端