最近一个月把代码重构了一遍, 感觉舒服多了, 但总体开发进度没有变化.. 今天聊聊把style属性转换成Java代码的办法

先说结论: 引用系统style是无法完美的实现的, 我们如果有写成Java代码的需求, 请尽量避免使用系统style. 自定义style没问题.

style是什么?

(参考链接) http://developer.android.com/guide/topics/resources/style-resource.html

" A style resource defines the format and look for a UI. A style can be applied to an individual View (from within a layout file) or to an entireActivity or application (from within the manifest file)."

更通俗的理解是, style其实是放置一组attribute的宏, 在控件中指定这个style, 将在xml解析时将style的一组属性应用到该控件中. 举个栗子:

这里有个style, 定义在res/value中:

<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="CustomText" parent="@style/Text">
<item name="android:textSize">20sp</item>
<item name="android:textColor">#008</item>
</style>
</resources>

然后我们在layout中的某个控件引用了这个style:

<?xml version="1.0" encoding="utf-8"?>
<EditText
style="@style/CustomText"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello, World!" />

实际上, 他是等于:

<?xml version="1.0" encoding="utf-8"?>
<EditText
android:textSize="20sp"
android:textColor="#008"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello, World!" />

有点宏替换的味道, 如果接触过html的同学可以很容易想到CSS这种东西, 两个想要做的基本是一样的.

需要指明的是: style的属性的优先级是最低的, 会被控件的其他相同属性覆盖掉. 这是理所当然的, 不然控件里的attribute要不服了(你都把我写出来了, 居然和我说我没用, 要被style那货覆盖掉?!)

让我们再回到这个被我们定义的style上, 会发现他还有一个叫parent的属性. 这里我们用面向对象的父类来理解, 就是子style会继承父类的属性. 同样的, 父类的属性要比子类属性优先级要低. (你都把我写出来了, 居然和我说我没用, 要被老爸的style覆盖掉?!)

style不是什么?

style不属于android Namespace中的属性 (不以android:开头), 没有对应的setStyle方法可以使用, 我的理解是它属于xml预加载的一种"机制".

自定义style的翻译:

那么对于自定义的style, 翻译就很简单了.

对于一个style, 将其替换成style中的attribute集合, 并向上 (父类) 继续增加父类集合, 并注意优先级 (子类可以覆盖父类attribute).

系统style的翻译:

系统style的翻译主要存在两个问题:

1. 系统style是内置在系统内部的, 不同的系统style并不一样, 特别是深度定制化的如MIUI, Flyme等操作系统. 如果只是使用一些简单的比较标准的style, 如progressbar等, 可以通过SDK Manager下载最新Android版本的API, 然后在路径platforms\android-20\data\res\values中找到标准的系统style, 或直接下载ASOP(路径framework/base/core/res/res/values/styles.xml. (我在项目中用到的是4.4的style文件, 5.0的sytle文件分成了多个, 而且里面的命名有点不规范)

  有些同学会发现, 如progressbar里面的style: android:attr/progressBarStyleSmall, 是用android:attr索引的. android:attr其实是在theme中定义的属性, apk的theme在AndroidManifest.xml中定义. 在解析xml过程中, 遇到android:attr的时候, 他就会在apk指定的theme中找到相应的item. 这个item对应的值就是style的值, 如:

style=?android:attr/progressBarStyleSmall
对应 最基本的Theme中的
<item name="progressBarStyleSmall">@android:style/Widget.ProgressBar.Small</item>

然后你再去styles.xml中寻找Widget.ProgressBar.Small. (这里还有个要注意的是, 就是系统的style不会声明parent属性, 但是以点"."做层级, 比如这里的Widget.ProgressBar.Small父类是Widget.ProgressBar)

这样带来的另一个问题, 深度定制的操作系统各种主题也会有改动, 这样造成更大的偏差.

2. 系统style用到的资源, 有些是我们从外部无法获取的. 还是举Widget.ProgressBar.Small的例子:

    <style name="Widget.ProgressBar.Small">
<item name="android:indeterminateDrawable">@android:drawable/progress_small_white</item>
<item name="android:minWidth">16dip</item>
<item name="android:maxWidth">16dip</item>
<item name="android:minHeight">16dip</item>
<item name="android:maxHeight">16dip</item>
</style>

他里面用到了@android:drawable/progress_small_white这个系统资源, 但是这个资源不是public的, 我们实现的时候没办法把这个资源调用出来. 有些同学会想到反射, 但反射也是不行的. 因为所有的系统资源在ASOP编译的时候会生成类似于R.java这样的资源索引文件, 这些文件用于我们使用系统资源的id来调用系统资源. 而非public是不会声明出来的, 也就是说你连id都无法知道, 也就无法获取对应资源了. 我曾大致阅读了一下xml的解析实现, 发现到最后都进入了native层, 在native层用c/c++实现, 这让我望code兴叹..

不过ProgressBar的各种样式应该可以通过api来设置出来, 这个我还没证实. 可以参考: [Android实例] Android 在Java代码中设置style属性--使用代码创建ProgressBar对象

对这个非public系统资源获取有经验的同学欢迎交流.

项目代码:

我在项目中实现了构建style元素, 使用style元素替换为attritutes, 以及style元素之间的关系, 包括对theme的android:attr寻找:

https://github.com/SickWorm/AndroidXMLToJava/blob/master/src/com/excelsecu/androidx2j/AX2JStyle.java

版权所有,转载请注明出处:

http://www.cnblogs.com/sickworm/p/4355396.html

 

【Android XML】Android XML 转 Java Code 系列之 style(3)的更多相关文章

  1. 【Android XML】Android XML 转 Java Code 系列之 介绍(1)

    最近在公司做一个项目,需要把Android界面打包进jar包给客户使用.对绝大部分开发者来说,Android界面的布局以XML文件为主,并辅以少量Java代码进行动态调整.而打包进jar包的代码,意味 ...

  2. 【Android XML】Android XML 转 Java Code 系列之 Selector(2)

    今天我们要把drawable下的selector的XML文件转换成Java代码.(打包进jar,不依赖apk) 在转换工具中的代码为: https://github.com/SickWorm/Andr ...

  3. [置顶] Android学习系列-Android中解析xml(7)

    Android学习系列-Android中解析xml(7) 一,概述 1,一个是DOM,它是生成一个树,有了树以后你搜索.查找都可以做. 2,另一种是基于流的,就是解析器从头到尾解析一遍xml文件.   ...

  4. Android(java)学习笔记187:Android中操作XML数据(使用Pull解析器)

    1. Pull解析器的运行方式与 SAX 解析器相似.它提供了类似的事件,如:开始元素和结束元素事件,使用parser.next()可以进入下一个元素并触发相应事件.跟SAX不同的是, Pull解析器 ...

  5. [Android] Android Build 时报错: java.io.IOException: Could not parse XML from android/accounts/annotations.xml

    Android构建时报错: app:lintVitalRelease[Fatal Error] :3:214: 与元素类型 “item” 相关联的 “name” 属性值不能包含 ‘<’ 字符. ...

  6. Android(java)学习笔记130:Android中操作XML数据(使用Pull解析器)

    1. Pull解析器的运行方式与 SAX 解析器相似.它提供了类似的事件,如:开始元素和结束元素事件,使用parser.next()可以进入下一个元素并触发相应事件.跟SAX不同的是, Pull解析器 ...

  7. 【Android】实现XML解析的几种技术

    本文介绍在Android平台中实现对XML的三种解析方式. XML在各种开发中都广泛应用,Android也不例外.作为承载数据的一个重要角色,如何读写XML成为Android开发中一项重要的技能. 在 ...

  8. android关于AndroidManifest.xml详细分析

    http://my.eoe.cn/1087692/archive/5927.html 一.关于AndroidManifest.xmlAndroidManifest.xml 是每个android程序中必 ...

  9. Android动画解析--XML

    动画类型 Android的animation由四种类型组成 XML中 alpha 渐变透明度动画效果 scale 渐变尺寸伸缩动画效果 translate 画面转换位置移动动画效果 rotate 画面 ...

随机推荐

  1. BZOJ 1491 社交网络(最短路)

    对于这道题,如果我们能求出s到t的最短路径数目和s由v到t的最短路径数目,剩下的很好求了. 令dis[i][j]表示i到j的最短路径,dp[i][j]表示i到j的最短路径条数,如果dis[s][v]+ ...

  2. 关于"作数类型冲突: nvarchar 与 image 不兼容"的问题

    数据库如果是Image类型,当执行插入语句时,如果插入的值是DBNull.Value时提示:操作数类型冲突: nvarchar 与 image 不兼容; 出现这个问题的原因是没有指定DbType的原因 ...

  3. Python_css选择器

    1. 概述 css是英文Cascading Style Sheets的缩写,称为层叠样式表,用于对页面进行美化. 存在方式有三种:元素内联.页面嵌入和外部引入,比较三种方式的优缺点. 语法:style ...

  4. 虚拟机如何进入BIOS

  5. [bzoj 1594]猜数游戏

    主要是怎么处理矛盾 矛盾的条件有$2$种: 第一种是当把所有相等的$a$都全部找到后,他们并没有全联通,所以矛盾,因为没有两个是相同的 第二种是在2组$(l,r,a)$,$(l1,r1,a1)$中,$ ...

  6. 国庆 Day1

    This is a 玄学 exam A.年轮蛋糕 最小的最大,二分首选 断环为链,check(x),x为答案,然后将每个大于x的子区间记录下来 如果有大于3个的话,那么x就可以是答案 那么·,在优化下 ...

  7. 【神仙题】【P4885】 灭顶之灾

    传送门 Description 请将题目名称的首字母连起来读 Scarlet有一张$n*m$的神秘表格.现在Scarlet向表格中填数字,她会从第一行中的某个格子起,按照从左往右,从上往下的顺序依次填 ...

  8. python获取当前工作目录

    py文件所在位置/test/pj/hello.py 用户所在位置:/ 用户执行命令python /test/pj/hello.py 1. os.getcwd() 返回的是执行命令的位置 / 2.sys ...

  9. shell中的颜色显示

    By francis_hao    Sep 30,2017   图片来自参考[1]     其中,"033"是八进制数,其对应的asciima也就是ESC.后面的颜色格式为:[背景 ...

  10. scanf函数用法小记

    By francis_hao    Aug 26,2017   scanf – 输入格式转换   概述 #include <stdio.h>int scanf(const char *fo ...