细说 AppCompat 主题引发的坑:You need to use a Theme.AppCompat theme with this activity!

article/2025/10/18 19:31:30
12-widget

一般来说按照文档的建议去做,出现问题的概率很低。但很多人的情况不同,每每会发生意外状况,就比如这次没有使用 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;}
}

如何解决这个问题呢?

  1. 主题改为扩展自 AppCompat 系主题。 但如果自己的主题覆写的地方很多,这将耗费很长时间,而且很多自定义的属性可能还会和 AppCompat 主题产生冲突,需要逐个分析、细细调整

  2. Activity 改用 SDK 版本,即 android.app.Activity 但随着 Jetpack 框架的日渐成熟和流行,很多重要的框架非常依赖于 AppCompatActivity 的支持,比如 Lifecycle 框架、ViewModel 框架、Preference 等。这可能导致其他的框架功能发生问题,也不是很好

  3. 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 画面:

12-widget

等等,复选框设置条目的 CheckBox 怎么不见了?

12-widget

查看了 CheckBoxPreference 的源码,没有发现什么特别的处理。

通过 Layout Inspector 看了下布局,发现了一点线索:视图当中,CheckBox 的实例是存在的,只是 Width 变成了0。而且 CheckBox 的实现类名变成了 AppCompatCheckBox

突然想起 AppCompat 框架为了让低版本系统能使用上诸如 Auto SizeBackground 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种解决方案:

  1. 主题改为扩展自 AppCompat 系主题

  2. Activity 改用 SDK 版本的 android.app.Activity

  3. 手动解决AppCompat 的兼容性问题

毋庸置疑的是 AppCompat 框架对主题的限制源于后续的 UI 逻辑与其紧密相连,所以最佳解决办法肯定是方案1,即提供 AppCompat 系主题。

  • 如果确实不需要 Jetpack 其他框架的协同(虽然这极不可能),那么可以选择方案2
  • 如果现有主题太过庞大,一时半会儿无法切换到 AppCompat 主题,而且影响的画面很少、不复杂。那么可以试试方案3去逐个解决

推荐阅读

AppCompat发布两年了,还没了解?


http://chatgpt.dhexx.cn/article/2nLGdu15.shtml

相关文章

Android Jetpack基础组件之AppCompat

1.简介 相比苹果封闭的IOS系统&#xff0c;Android系统的开放性带来了很多的优势。与此同时&#xff0c;也带来了严重的碎片化问题&#xff0c;包括硬件的碎片化和软件碎片化。这里&#xff0c;我们主要说的是软件方面。各Android设备厂商&#xff0c;受限于成本和技术原因&am…

AppCompat发布两年了,还没了解?

近日随笔 近期疫情日渐严峻&#xff0c;大家多多保重&#xff0c;出门记得戴口罩。希望河北&#xff0c;黑龙江能尽早控制住好局面迎来拐点&#xff0c;全国人民过个好年。 为了能够让低版本的Android系统能够运行新特性&#xff0c;AppCompat框架自Support时代就已推出。但随着…

AppCompat (AppCompatActivity) Jetpack

进入AppCompat章节后&#xff0c;我们发现它又被分为了4个部分&#xff0c;这4个部分被称为“key class”&#xff0c;也就是重点类&#xff0c;它们分别是&#xff1a; ActionBar&#xff1a;提供Actionbar用户界面模式的实现&#xff1b;AppCompatActivity&#xff1a;添加可…

【5】SpringBoot日志存储路径和设置日志格式

SpringBoot日志存储路径和设置日志格式 文章目录 SpringBoot日志存储路径和设置日志格式01、分析02、解决方案03、Springboot的日志的解决方案&#xff08;掌握&#xff09;04、查看springboot的日志的整个体系05、slf4j、logback和log4j三者的关系06、springboot的日志搭配07、…

nginx日志格式分析及修改

修改nginx日志打印格式 一. 打开终端&#xff0c;登录服务器并输入服务器密码 //ssh 用户名服务器ip ssh root192.168.0.132二. 切换到nginx目录 cd /var/log/nginx/三. 查看nginx日志 tail -f access.log日志说明&#xff1a; //默认的nginx标准日志格式 192.168.10.251 …

Nginx配置-日志格式配置

Nginx配置-日志格式配置 一、默认的日志格式二、我使用的日志格式三、参数四、测试效果 五一上线了一个小的预约程序&#xff0c;配置通过Nginx进行访问入口&#xff0c;默认的日志是没有请求时间的&#xff0c;因此需要配置一下&#xff0c;将每一次的请求的访问响应时间记录出…

Apache日志记录格式-LogFormat配置详解

Apache日志记录格式-LogFormat配置详解 前言 定制日志文件的格式涉及到三个指令&#xff0c;即LogFormat指令和CustomLog指令和ErrorLog指令&#xff0c;默认httpd.conf文件提供了关于这两个指令的几个示例。 格式设置 LogFormat LogFormat指令定义格式并为格式指定一个名…

springboot项目中日志使用----自定义日志格式(可直接使用)

springboot项目中日志使用 1、为什么加日志 1.1 日志是什么&#xff1f; 日志文件提供精确的系统记录&#xff0c;根据日志最终定位到错误详情和根源。日志的特点是&#xff0c;它描述一些离散的&#xff08;不连续的&#xff09;事件。例如&#xff1a;应用通过一个滚动的文…

python设置日志格式

# %(asctime)s 字符串形式的当前时间。 # %(levelname)s 文本形式的日志级别 # %(name)s Logger的名字 # %(filename)s 调用日志输出函数的模块的文件名 # %(funcName)s 调用日志输出函数的函数名 # %(lineno)d 调用日志输出函数的语句所在的代码行 # %(message)…

Log4j日志输出格式

Log4j日志输出格式 对于我才开始工作来说&#xff0c;输出日志唯一的目的就是打印代码的调试信息&#xff0c;当有项目运行什么问题或者错误可以通过查看日志快速的找到问题根源&#xff08;这也是我来公司最开始就遇到的问题&#xff09;。 先分享一个公司框架自带的通用日志…

logback 日志输出格式

强烈推荐一个大神的人工智能的教程&#xff1a;http://www.captainai.net/zhanghan​ 【前言】 日志对一个系统的重要性不言而喻&#xff1b;日志通常是在排查问题时给人看&#xff0c;一个友好的输出样式让人看到后赏心悦目&#xff0c;排查效率通常也会随之提高&#xff1b;…

Nginx的日志格式

vim /etc/logstash/conf.d/ filter模块的作用&#xff1a;过滤&#xff0c;{在一个大的真空管里面&#xff0c;中间有一个过滤网&#xff0c;只有比这个小的东西能过去&#xff0c;大的会拦住} 在grok中使用match进行选择&#xff0c;所传送过来的是下面这样。希望把他们变成i…

什么是日志文件

文章目录 什么是日志文件Centos 7 日志文件简易说明日志文件的重要性Linux常见的日志文件文件名/var/log/boot.log/var/log/cron/var/log/dmesg/var/log/lastlog/var/log/maillog或 /var/log/mail/*/var/log/messages/var/log/secure/var/log/wtmp、/var/log/faillog/var/log/h…

AE2018插件AfterCodecs v1.9.0安装教程,(AE mp4)

1.自己百度下载好 2.这2个文件夹要复制&#xff0c;其他可以不管 复制Autokroma AfterCodecs 文件夹到 C:\Program Files\Adobe\Common\Plug-ins\7.0\MediaCore 复制com.autokroma.afcpanel 文件夹到 Adobe After Effects CC 2018\Support Files\Plug-ins\Extensions&#x…

PS/PR/AE全套插件一键安装包无需注册码

注意事项&#xff1a; 1、下载前请关闭360、电脑管家等杀毒软件&#xff0c;否则会误报病毒导致无法安装&#xff1b; 2、安装PS/PR/AE插件合集前&#xff0c;请务必先安装好Adobe软件&#xff1b; 3、安装PS/PR/AE插件合集前&#xff0c;请务必关闭Adobe旗下所有软件。 安装步…

Ae 2020最新版下载地址 一键安装Windows

各类cc软件。 地址&#xff1a;https://www.yuque.com/docs/share/cf424323-49e5-43e6-a80c-4f07ce467d56 访问密码&#xff1a;关注公众号"糊糊省钱"&#xff0c;回复“ps”获取

Adobe After Effects(AE)2022软件安装[MAC]

Adobe After Effects简称“AE”&#xff0c;Adobe After Effects 2022mac是Adobe公司推出的一款图形视频处理软件&#xff0c;适用于从事设计和视频特技的机构&#xff0c;包括电视台、动画制作公司、个人后期制作工作室以及多媒体工作室&#xff0c;属于层类型后期软件。Adobe…

AE CC2018/64位安装步骤及各种出现问题!!(真的装了好久)

最近爱上录vlog&#xff0c;但是作为一个计算机学院的学生我怎么仅仅局限于手机里的剪视频软件呢&#xff01;然后我打算学一下AE&#xff0c;但是在这个py的过程中&#xff0c;真的废了快一个晚上了&#xff0c;从第一次安装出现问题我就应该立马百度&#xff0c;但是我没有&a…

2023AE软件、Adobe After Effects安装下载教程

2023AE软件是一款由Adobe公司开发的视频编辑软件&#xff0c;也被称为Adobe After Effects。它在广告、电影、电视和网络视频等领域广泛应用&#xff0c;用于制作动态图形、特效、合成和其他视觉效果。该软件支持多种视频和音频文件格式&#xff0c;具有丰富的插件和预设&#…

Adobe After Effect (AE) cc2020 安装教程【64位】

Adobe After Effects简称“AE” 是Adobe公司推出的一款图形视频处理软件&#xff0c;适用于从事设计和视频特技的机构&#xff0c;包括电视台、动画制作公司、个人后期制作工作室以及多媒体工作室。属于层类型后期软件。 ----介绍来源于百度 【软件名称】&#xff1a; After …