Skip to main content

样式规范

大家在开发中是否经历过下面的场景:有这样两个画面 X 与 Y ,它们都有搜索功能,UI 设计与交互完全相同,交给程序员 A 与 B 进行开发,最后虽然二者开发的画面的表现与交互完全相同,但是却是完全不同的实现。过了一段时间 C 在去维护这两个看似一样的东西时,却遇到了阻力,用了双倍于计划的时间。

不同的人员开发类似的功能,虽然最终效果几乎相同,但是具体的实现可能完全不同。带来的后果就是:为维护带来了理解鸿沟,同时每个人都单独造一遍轮子,对于项目来说也是一种资源的浪费。

应用在UI层面上的代码重复与风格统一问题,是一个需要在整体工程视角上解决的问题,而不是仅仅依靠参与工程的每个独立个体就能够解决好的问题。解决这个问题的办法有两种:

  • 工程中的 UI 控件组件化(主要解决组件复用与重复造轮子的问题)。
  • 在工程层面设立样式规范(主要解决 UI 层面上的代码重复与风格不统一的问题)。

本部分内容的核心就是上面的第二点:通过样式规范来解决 UI 层面上的代码重复与风格不统一的问题。

注意,我们要提供的是一组规则,一组在 Android 开发中如何组织与使用画面颜色、间距、样式的规则,而不是具体的颜色与样式的设计方法。那些是 App 的 UI 设计人员应该关心的。


颜色#

分类#

一般情况下,为了保持应用风格的一致性,UI设计人员在进行页面设计之前,会先定义一个调色板,然后基于调色板中的颜色进行画面的配色设计。于此同时,应用开发人员在开发应用时,很多情况下不可避免的需要将用到的颜色按照使用逻辑来命名,如:
<color name="button_foreground">#FFFFFF</color>

因此,为了保持应用中在使用颜色时的逻辑清晰,我们也把应用中使用到的颜色大体上分为两类:

  • 调色板颜色(应用中用到的所有基本颜色)
  • 逻辑颜色(基于调色板定义的带有逻辑意义的颜色,选用)

调色板颜色#

调色板颜色一般由应用的设计人员给出,调色板颜色的例子:

<resources>
<!-- grayscale -->
<color name="white">#FFFFFF</color>
<!-- basic colors -->
<color name="blue">#2A91BD</color>
</resources>

向你的应用设计者去要这个调色板。

注:颜色名称不一定非要与其提供给你的相同(不一定设计提供的名称叫bluewhite,程序中就也要用相同的名字,类似于 brand_primary, brand_secondary, brand_negative 这样的名称也是可以接受的)。
使用定义调色板的这种颜色声明方式在有效的减少颜色ARGB值的重复定义的同时,也使颜色的修改和重构变得容易,并且很容易明确应用到底用到了多少种颜色。通常,对于一个美观的用户界面,减少使用的颜色种类是很重要的。

逻辑颜色(选用)#

逻辑颜色是基于调色板颜色定义的,带有逻辑意义的颜色,逻辑颜色不需要定义 ARGB 的值,它只引用调色板颜色中的值。
例:

<color name="button_foreground">@color/white</color>
<color name="button_background">@color/blue</color>

逻辑颜色按照颜色的用途,分为字体颜色非字体颜色;按照颜色的使用范围,分为共通颜色非共通颜色
将上述条件进行组合,我们得到工程中的逻辑颜色分类,为如下四种:

  • 共通字体颜色
  • 非共通字体颜色
  • 共通颜色
  • 非共通颜色
字体非字体
共通共通字体颜色共通颜色
非共通非共通字体颜色非共通颜色

组织#

所有的调色板颜色抽出到 colors.xml 中统一管理;逻辑颜色抽出到 colors_主题名.xml 中按照不同的主题进行分类管理。

命名#

颜色名所用到的单词全部小写,多个单词用下划线分隔

调色板颜色#

调色板中的颜色可以以颜色的名称来命名,如:whitebluegray 等。
也可以以该颜色在应用中的作用来命名,如:color_primarycolor_foregroundcolor_background 等。

注意,以上两种方式可以任选其一,但是尽量不要混用,以免造成混乱。

逻辑颜色#

共通颜色需要以 common_ 开头、字体颜色需要以 _font_color 结尾。

  • 共通字体颜色
    common_ 开头,以 _font_color 结尾,中间为该颜色变量的表意
    例:common_warning_font_color
  • 非共通字体颜色
    模块名称_ 开头,以 _font_color 结尾,中间为该颜色变量的表意
    例:register_next_step_btn_font_color
  • 共通颜色
    common_ 开头,以 _color 结尾,中间为该颜色变量的表意
    例:common_warning_bg_color
  • 非共通颜色
    模块名称_ 开头,以 _color 结尾,中间为该颜色变量的表意
    例:register_next_step_btn_bg_color

间距、字号#

间距#

分类#

按照间距的使用范围,将间距分为共通间距非共通间距

  • 共通间距:贯穿整个 App 的全部画面(如,共通内边距、外边距)或在 App 的多个画面中出现频率较高的间距。
  • 非共通间距:只在特定画面上出现一次或多次,在特定画面外不出现的间距。

组织#

  • 所有的共通间距都要抽出到 dimens.xml 中统一管理。
  • 只在特定画面上出现一次的非共通间距,可以抽出,也可以不抽出,不做硬性要求。

命名#

  • 单词全部小写,多个单词用下划线分隔。
  • 共通间距需要以 common_ 开头,表示高度时,需要以 _height 结尾,表示宽度时,需要以 _width 结尾。
    例:common_list_item_height
  • 非共通间距需要以 模块名称_ 开头,表示高度时,需要以 _height 结尾,表示宽度时,需要以 _width 结尾。
    例:profile_user_avatar_width

一般情况下,为了统一App中各个画面元素的视觉位置关系,一个好的UI设计会充分考虑整个App的间距关系,并像使用调色板那样使用数量有限的间距值。这时我们就可以将这些间距抽出为共通间距,共通间距可以理解为间距的“调色板”。

字号#

分类#

按照 UI 设计是否定义了字号的使用场景,将字号分为普通字号层级字号

  • 普通字号:在 UI 设计中未明确定义在整个 App 中的使用场景的字号。
  • 层级字号:在 UI 设计中明确定义了在整个 App 中的各种使用场景(如:画面标题、列表标题等)的字号。

组织#

  • 所有的字号都要抽出到 dimens.xml 中统一管理。
  • 字号的单位统一使用 sp

    注:字号单位 sp 与 距离单位 dp 的区别主要在于,sp 除了受屏幕密度影响外,还受到用户的字体大小影响,所以通常情况下,建议使用 sp 设定字体大小。

命名#

  • 单词全部小写,多个单词用下划线分隔。
  • 普通字号统一以 common_font_size_字号 的方式命名
    例:common_font_size_18
  • 层级字号统一以 common_font_size_level_层级号 的方式命名
    例:common_font_size_level_1

举例:#

<!--普通字号-->
<dimen name="common_font_size_23">23sp</dimen>
<dimen name="common_font_size_21">21sp</dimen>
<dimen name="common_font_size_20">20sp</dimen>
<dimen name="common_font_size_19">19sp</dimen>
<dimen name="common_font_size_18">18sp</dimen>
<dimen name="common_font_size_17">17sp</dimen>
<dimen name="common_font_size_16">16sp</dimen>
<dimen name="common_font_size_15">15sp</dimen>
<dimen name="common_font_size_14">14sp</dimen>
<dimen name="common_font_size_13">13sp</dimen>
<dimen name="common_font_size_12">12sp</dimen>
<dimen name="common_font_size_11">11sp</dimen>
<dimen name="common_font_size_10">10sp</dimen>
<!--层级字号-->
<dimen name="common_font_size_level_1">@dimen/common_font_size_18</dimen>
<dimen name="common_font_size_level_2">@dimen/common_font_size_16</dimen>
<dimen name="common_font_size_level_3">@dimen/common_font_size_14</dimen>
<dimen name="common_font_size_level_4">@dimen/common_font_size_12</dimen>

普通字号可以理解为字号的“调色板”,层级字号一般要与UI设计相对应。


样式#

样式的作用#

样式,是一组画面元素属性的集合,定义画面的元素如何显示。
使用样式可以帮助我们减少布局文件中的代码,更好的完成统一画面风格、快速变换主题等需求。

在 Android 开发中,在 styles.xml 中定义 App 中用到的样式。作为 App 的开发者,你可以为每个控件定义样式,并将其应用于你希望的任意多的页面中。如需进行全局的更新,只需简单地改变样式,然后 App 中的所有指定了该样式的元素均会进行相应的更新。

抽出原则#

相同控件的同一份属性集合在同一个页面反复出现多次(通常为 4 次及以上)或者在不同画面反复出现多次,则需抽出为样式。

注意,只有同一份属性集合出现多次的时候才有抽出样式的必要,如果仅仅出现一次,则没有抽出样式的必要。如果是为了逻辑上更加清晰而抽出样式,这种做法也是无可厚非的,但是本原则对此不做要求。

分类#

按照抽出样式的使用范围,分为共通样式非共通样式

  • 共通样式:在 App 的不同模块的多个画面中出现频率较高的样式。
  • 非共通样式:只在特定画面上出现多次或在同一模块的不同画面中出现多次的样式。

注意,样式一般都是出现多次的属性集合。

组织#

所有的样式都要抽出到 styles.xml 中统一管理。当应用规模比较大,样式比较多时,我们可以按照 styles_模块名.xml 的规则来拆分样式文件,将不同模块的样式放到相应的样式文件中。

比如,当应用中的样式非常多时,可以采用如下的组织形式:

  • styles.xml 外,额外创建 styles_home.xmlstyles_profiles.xmlstyles_forms.xml 等样式文件。
  • 共通样式放入 styles.xml 中;
  • 非共通样式分别放入styles_home.xmlstyles_profiles.xmlstyles_forms.xml 等文件中。

命名#

  • 所有的样式都要采用大驼峰命名法,必要时以 “.” 点号分隔。
  • 共通样式需要在名称前加入 Common. 前缀。
    例:Common.Button.Primary
  • 非共通样式需要在名称前加入 模块名. 前缀。
    例:Order.Button.Primary

参考资料:
futurice/Best practices in Android development
ribot/android-guidelines