Android项目资源文件命名规范参考

本文提出一套Android项目的资源文件命令规范,可用于大型Android项目。参考了Android系统自带资源文件的命名风格。

文中的例子只是用于示意说明,并非来自真实的项目。

资源文件分类

先简单讨论一下Android中资源文件的分类。

资源类型上,Android中的资源文件包括layout、drawable、color、dimen、anim、array、style等不同类型,分别对应为R文件中的不同class,例如R.layoutR.color等。

物理形式上,资源文件默认放在res目录下(可以通过gradle配置修改)。有些资源文件对应的是文件夹中的一个xml或二进制文件,有些对应的是res/values文件夹下xml文件中<resource>标签内的一个子标签。

一种类型的资源文件可能有不同的物理形式,例如drawable可能是xml文件,可能是二进制文件,也可能是value中的标签。

示例:

XML文件

  • res/layout/activity_main.xml
  • res/drawable/button_pressed.xml
  • res/color/button_bg.xml

二进制文件

  • res/drawable/ic_user.png
  • res/raw/welcome.mp4

标签(res/values/xxx.xml文件)

1
2
3
4
<resources>
<color name="colorPrimary">#6facc6</color>
<drawable name="new_button">@drawable/button</drawable>
</resources>

大小写风格

资源名称默认使用小写加下划线,如layout_test.xml@+id:/txt_testcolor/theme_light

大小写方面的特例是,应用于Window的主题样式(即Application / Activity / Dialog等使用的style)使用首字母大写、点号分割的形式,如AppTheme.NoActionBar。而应用于View组件的style,还是使用小写加下划线形式,例如app_login_button

完整命名格式

资源文件默认的完整命名格式如下:

项目名_(工程名)_模块名_(子模块名)_(页面)_(组件名称)_描述

举例:

  • drawable: xxapp_account_login_button_background,某App(xxapp),用户账户模块(account),登录页面(login),按钮的背景。
  • string: xxapp_common_network_error,某App(xxapp),全局通用功能模块(common),网络异常的文本提示。
  • layout:xxapp_comment_activity_comment_detail,某App(xxapp),用户评论模块(comment),评价详情页面的layout布局。

项目模块拆分与前缀

对于一个复杂项目(对应一个App),可能包含多个子项目,每个子项目也可能有多个工程(对应AAR),一个工程中可能包含多个业务功能模块,模块中又包含若干个页面(对应Activity和Fragment)。项目/工程/模块/页面并没有绝对的界限,会随着业务发展不断调整。

不同的项目/工程/模块/页面可能由不同的团队/个人负责。为了避免命名冲突,以及方便开发(特别是提高找资源文件的效率),需要通过合适的前缀加以区分。

项目/工程/模块/页面级别的前缀,应该由各个项目/工程/模块/页面的负责人共同制定,所有相应的资源文件应完全符合前缀规则,还可以配合静态代码检查技术加以约束。而模块内部的命名规则即前缀之后的部分,可以由模块内部人员自行做出少量合理的调整。

对于会在多个工程/模块/页面中复用的组件,前缀可以用common代替,或者省略掉部分前缀。例如app_common_button_background

举例

假设某App有用户评价功能,用户评价相关的业务都被划分到comment模块。一开始代码规模较小时,没有子模块,命名可能是这样的:

1
2
3
4
app_comment_ic_edit
app_comment_ic_user
app_comment_ic_xxx
app_comment_img_xxx

之后评价功能越来越复杂,comment模块代码规模不断增大,以app_comment为前缀的资源文件数量太多,也不便于查找。

于是根据业务拆成多个子模块,例如app_comment_edit(编辑评价),app_comment_list(评价列表),app_comment_image(评论图片编辑相关)。按照命名规范,在前缀中添加子模块。由于在IDE中是按照文件名排序的,因此每个子模块的资源文件就会被聚合到一起,方便开发。

此时的命名可能是这样:

1
2
3
4
5
6
7
app_comment_edit_ic_xxx
app_comment_edit_bg_xxx

app_comment_list_ic_xxx
app_comment_list_img_xxx

app_comment_image_ic_xxx

单词使用规范

  1. 使用英文:避免使用拼音、缩写等不容易理解的单词,避免拼写错误。反面案例:zxkf(在线客服,取了首字母),例如good(商品,应该是goods)。
  2. 缩写规范:可以使用一些约定俗成的常见缩写,例如ic(icon)lang(language)bg(background),lib(library),img(image)
  3. 使用拼音的情况:商标、域名、专有名词,极少数难以翻译成英文的词等,在保证不影响理解的情况下,可以使用拼音,例如baidu(百度)。
  4. 特例:用于表示APP或者模块、需要大量使用的通用前缀,为了缩短长度提高输入效率和便于阅读,可以不受上述限制,但应该经过相关开发人员共同确认。例如wx(微信)。

组件名称

组件指的是一个或一组View,可大可小,例如页面、弹窗、按钮、文本标签等。

layout资源常用组件名

  • activity
  • fragment
  • adapter
  • layout
  • view
  • dialog
  • actionbar

view和layout的区别:view通常是嵌套层级较少、尺寸也比较小的组件(可能是View也可能是ViewGroup),例如一个左侧带有Icon的文本组件,虽然可能是用LinearLayout实现的,但视觉上更像是一个独立的View。layout一般是比较复杂、显示尺寸大的组件(对应ViewGroup),从视觉上明显包含很多子组件,例如微信会话列表中的一个Item,包含了头像、名称、最新消息、时间等内容。

完整示例:

  • app_comment_list_activity
  • app_comment_list_adapter

其他常用组件名

一方面可以根据控件的类型划分,例如CheckBox,RatingBar,ProgressBar;一方面可以根据UI特点来划分,例如divider、border、dot、label等。

关于缩写:缩写建议和Android自身的资源命名保持一致。使用频度高的基本组件一般都有常用且容易理解的写法,例如btn。对于使用频度不高但名称较长的组件,例如ProgressBarRatingBar,不建议使用含义不明确的rb(RadioButton)pb(ProgressBar)等首字母缩写;建议取多个单词中的某一个含义明确的词,例如progress(ProgressBar)rating(RatingBar)

举例

  • btn:按钮
  • text:文本
  • checkbox(CheckBox)
  • rating(RatingBar)
  • progress(ProgressBar):Loading、进度条
  • list:ListView
  • label:用于展示的文字标签
  • border:边框
  • divider:分割线
  • dot:小圆点
  • avatar:头像
  • popup:浮层

drawable的命名

主要是指出几种图片的区分

  • ic / icon:图标,多用于展示尺寸较小、图形简单的图标。
  • img / image:图片,尺寸相比图标较大,且图形复杂,一般用于前景。
  • bg / background:背景,背景多用于View的background属性,9-patch格式的图比较常见,背景上方一般会有其他内容。

selector的命名

每种状态对应的资源文件加后缀,最终产生的selector文件不加后缀。

常用后缀

  • normal:常态(默认态)
  • highlight:高亮,常包含pressed、focused、highlight等多种状态
  • pressed:按下
  • checked:勾选
  • selected:选中
  • unselected:未选中(selected=false)
  • disable:不可用(enable=false)

举例:CheckBox的定义

selector文件名为checkbox_green.xml,并引用checkbox_green_checkedcheckbox_green_normal两个drawable资源。

标准的写法:定义checked和normal

1
2
3
4
5
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/checkbox_green_checked" android:state_checked="true"/>
<item android:drawable="@drawable/checkbox_green_normal"/>
</selector>

不合理的写法:定义checked和unchecked,unchecked含义不准确

1
2
3
4
5
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/checkbox_green_checked" android:state_checked="true"/>
<item android:drawable="@drawable/checkbox_green_unchecked"/>
</selector>

color、dimen的命名

color的名称,可以不再加color的表述,例如color/app_theme而不是color/app_theme_color

dimen的名称,根据需要会添加和尺寸相关的表述,例如dimen/app_common_btn_widthdimen/app_common_btn_heightdimen/app_common_activity_margin

string的命名

string的命名,描述部分可以是对字符串作用的描述,例如app_common_share_tips,有时也可以是字符串直接对应的英文翻译,例如app_no_comment

有时模块名和后续描述重复了,读起来会比较奇怪。例如评论页面的“没有评论”,命名为app_comment_no_comment,可以考虑改为app_comment_no_content

id的命名

由于只要保证BindView时控件的id名称不冲突(例如Adapter中的每个Item内的id不冲突即可,Item之间id相同也没有影响),因此id的命名要求可以相对宽松。一般以控件类型_描述的形式即可。

常用控件类型例如:

  • txt:文本
  • img:图片
  • btn:按钮
  • view:不需要关心一个View的具体实现形式时,可以直接视为view。例如分割线,既可以用View实现,也可以用ImageView实现,代码中只关心分割线是否可见(同时在代码中也不指定具体变量类型,这样后续在xml中直接改view的类型时,不需要改id和Java代码)。
  • layout:不需要关心Layout的具体类型,可直接视为layout,同上。

主题样式的命名

Application默认的style命名为AppTheme;用于Activity的style,统一命名为AppTheme.XXX;用于Dialog的style,统一命名为Dialog.XXX

示例:

  • AppTheme:Application默认的主题
  • AppTheme.NoActionBar:隐藏自带ActionBar的Activity
  • AppTheme.NoActionBar.FullScreen:全屏Activity,隐藏了ActionBar和状态栏
  • AppTheme.Transparent:透明的Activity
  • AppTheme.NoActionBar.Login:登录页面

Style默认会按照名称中的点号分隔自动继承Parent。例如名为AppTheme.Login的style会自动继承AppTheme中的属性。也可以自行指定Parent,示例如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<style name="AppTheme">
</style>

<!-- 默认parent为AppTheme -->
<style name="AppTheme.MyActivityName">
<item name="android:windowIsTranslucent">true</item>
</style>

<!-- 指定使用其他parent -->
<style name="AppTheme.MyActivityName" parent="AppCompat.Light">
<item name="android:windowIsTranslucent">true</item>
</style>

<!-- 不需要parent -->
<style name="AppTheme.MyActivityName" parent="">
<item name="android:windowIsTranslucent">true</item>
</style>

文件的组织

res/value目录下的文件拆分

value目录下按照资源类型拆分成不同的文件,例如styles.xmldimens.xmlcolors.xml

有时候项目会拆分出SDK,在公司内的多个App之间复用,例如用户账户SDK,接入到多个App时通过覆盖资源文件实现不同的主题色。如果需要覆盖SDK中的资源,可以单独建一个专用于覆写SDK的文件,并写好注释避免误删,例如res/value/resourse_sdks.xml。如果某个SDK需要覆盖很多资源时,可以进一步拆分到单独的文件中。例如res/value/resourse_account_sdk.xml

Drawable存放目录

由于开发成本、减少包大小等原因,一些实际项目中并没有对不同密度的屏幕分别提供png图片,而是使用同一套2x图片,因此统一放在res/drawable-xhdpi中,其density=2,即1dp=2px。

而xml格式的Drawable应该统一放在res/drawable中。

容易放错目录的xml

<animated-rotate/><animation-list/>是实现了Animatable接口的Drawable,不是Animation,应该放在drawable目录而不是anim目录。