背景
最近在整一个前辈留下的老代码,里面有个自定义弹窗dialog, 然后自定义了一个Theme,有点看不懂,并且不用这个Theme 整个窗口弹出就出问题了。
回忆theme style 的区别和作用
有点久了,二者的功能有点淡忘了。
从程序设计上猜测思考
除非是想全盘从头设计,那么android的任何组件必然会有一种缺省配置,这些配置决定着该组件的展示样式风格,我自己也做过公共组件,一是UI实体,另外就是通过丰富的配置项来使得UI实体活起来。那么android 不仅开放了这些配置参数,而且还定义了一组组参数值,每一组参数值都是一个自成体系的风格,我们完全可以从这些官方风格中选择一个,当然某些参数可以自己继承来修改修改,(重复造轮子是不好的),那么这些配置全部都一股脑儿的包罗万象? 似乎也不好,然后窗体的整体风格归为一类,单个组件的风格归为一类,前者就是Theme,后者是style. 后面可以分析二者的参数差异
看看官方怎么说
Style
A style is a collection of properties that specify the look and format for a View or window. A style can specify properties such as height, padding, font color, font size, background color, and much more. A style is defined in an XML resource that is separate from the XML that specifies the layout.
Styles in Android share a similar philosophy to cascading stylesheets in web design—they allow you to separate the design from the content.
形式
属性集合
目标
为View 及 Window 设置视觉样式,如高度,padding,颜色,大小,背景色等等
最终是将 风格设计 和 UI的内容(比如TextView的text内容)给分离,增加复用。
Theme
A theme is a style applied to an entire Activity or application, rather than an individual View (as in the example above). When a style is applied as a theme, every View in the Activity or application will apply each style property that it supports. For example, you can apply the same CodeFont style as a theme for an Activity and then all text inside that Activity will have green monospace font.
形式
他还是一种style
目标
整个Activity 或 应用,而不是某个View
它形式上和style是一样的,(a style that you want to use as an Activity or application theme is defined in XML exactly the same as a style for a View)但是它的作用范围及作用效力更广更强,如果将某style应用到Activity中,那么该Activity下的所有View都会被应用到这些设置。
继承
继承android系统的样式
<style name="GreenText" parent="@android:style/TextAppearance">
<item name="android:textColor">#00FF00</item>
</style>
继承自定义样式
<style name="CodeFont.Red">
<item name="android:textColor">#FF0000</item>
</style>
注意: 不需要用parent了,上面继承了CodeFont,并且修改了textColor属性, Red不是属性哈(跟java类属性不一样,别混了),这个继承自CodeFont的新样式名称为 CodeFont.Red
那如果还想继承CodeFont.Red怎么办,再加,如下:
<style name="CodeFont.Red.Big">
<item name="android:textSize">30sp</item>
</style>
强调: 这种用法只限于继承自己定义的样式。
都有什么样式属性呢?
并且我们去哪里去找我们想要的属性呢?
对于单个View组件来说
如TextView在其官方说明中XML attributes就有提到
对于所有可用的样式属性呢?
参见 R.attr
关于属性的支持上
并不是每个View对每个属性都是需要的,支持的,那么如果给View设置了他所不支持的属性会怎样?结论是被忽略。
还有一些属性是专为theme使用的,只有设置给Activity和app的时候才会有作用,如”style properties for a theme can hide the application title, hide the status bar, or change the window’s background”,在R.attr中以window开头的如windowNoTitle and windowBackground 都属于这类。
强调 使用系统的,注意加上”android:”的命名空间
如何使用Theme呢?
应用给整个app,在AndroidManifest.xml中
<application android:theme="@style/CustomTheme”>
应用给某个Activity
<activity android:theme="@android:style/Theme.Dialog”>
继承系统Theme
<color name="custom_theme_color">#b0b0ff</color>
<style name="CustomTheme" parent="android:Theme.Light">
<item name="android:windowBackground">@color/custom_theme_color</item>
<item name="android:colorBackground">@color/custom_theme_color</item>
</style>
属性那么多,我们怎么查?
theme中可用到的属性
所有可用的styles
style及theme的源码
上面的styles并没有很完善的文档,更多还是看源码
Android Styles
Android Themes
IllegalStateException分析
You need to use a Theme.AppCompat theme (or descendant) with this activity.
在源码AppCompatDelegateImplBase中可以看到:
@Override
public void onCreate(Bundle savedInstanceState) {
TypedArray a = mContext.obtainStyledAttributes(R.styleable.Theme);
if (!a.hasValue(R.styleable.Theme_windowActionBar)) {
a.recycle();
throw new IllegalStateException(
"You need to use a Theme.AppCompat theme (or descendant) with this activity.");
}
如果在Theme中没有找到Theme_windowActionBar的样式的话,就会报crash.
而在application中
<application xmlns:tools="http://schemas.android.com/tools"
android:allowBackup="true"
android:fullBackupContent="true"
android:icon="@mipmap/ic_launcher"
android:theme="@style/AppTheme"//被删掉了
android:label="Sample">
原因就是android:theme=”@style/AppTheme”//被删掉了
AppTheme?
在styles.xml文件已经自动生成了
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
</style>
如果我们有页面继承了AppCompatActivity 要么在:
* application中加上android:theme=”@style/AppTheme”
* activity中加上android:theme=”@style/Theme.AppCompat.Light.DarkActionBar”