第七课 样式与主题

我很喜欢Ionic的原因是,默认的组件都是开箱即用型的。一切看起来很整齐,平滑,整洁,同时也有点枯燥。我喜欢简单,平平淡淡才是真,但是,也许你不想你的应用看起来跟其他应用没什么两样。举一下我们在模板中讲过的例子:
sample

界面看起来简单明了,但是明显没有赢得任何设计大奖的可能性。他使用的都是默认的样式,没有半点自定义的东西。如果你看一下我本课程中制作的应用的时候,会发现他们基本上都有自定义样式:
Giflist

一些应用只有简单的自定义样式,而简单的自定义样式就可以让它耳目一新。一些应用有更复杂的自定义样式,他完全使项目焕然一新。
我当然不是设计大神,但是我觉得我给这些应用创建的主题让他们看起来更舒服也给了应用一些特色。本课程中将给你展示使用不同方法自定义你的Ionic 2应用, 以及主题背后的原理。

介绍Ionic 2主题

给Ionic 2应用定制样式在本质上和给网站定制样式没什么区别。我经常看到这样的问题:

我可以在Ionic里面制作[插入元素/界面]吗?

答案是yes。你可以在普通网页上做吗?如果可以的话,那么在Ionic里面也可以。
大部分人都是通过修改CSS文件来改变样式,但是Ionic稍微复杂些,因为Ionic使用的是SASS。同样,SASS不是Ionic或者移动网页应用开发特有的 —— 在很多普通页面上也可以使用 —— 但是很多人对SASS不熟悉所以他们选择使用老旧的CSS。
如果你还不熟悉,.scss是SASS的文件类型或者Syntactically Awesome Style Sheets牛逼闪闪语法样式表。如果你是第一次看到这个,建议你阅读文档熟悉一下SASS是什么以及他做什么。对于那些着急上手的人们,你在.scss里面放的和你在.css放的是一样的东西,你可以在里面做很多很酷的东西,例如定义变量然后在不同地方使用。.scss文件然后会编译成.css文件(和我们在Ionic 2的理念是一样的,我们用有趣的ES6功能去编写代码,然后转译成浏览器实际支持的ES5代码)。
当给你的应用定制主题的时候,主要是去编辑你的 .html模板文件 和 .scss样式表 —— 绝对不要直接去编辑 .css 文件。 .css 文件是从.scss文件生成的,所以你对 .css 文件做的任何更改都将被覆盖。
当你查看创建项目的时候自动生成的文件是,你可以在theme文件夹里面看到一些.scss文件,我们现在快速了解一下他们是干嘛用的。

  • src/theme/app.scss用于声明在应用中全局使用的样式
  • theme/variables.scss 用于修改应用共享变量。在这里你可以编辑一些默认值,例如用于设置应用默认颜色的 $color,还有$list-background-color$checkbox-ios-background-color-on等等。这个的目的是Ionic使用此处定义的变量来决定许多组件的样式,所以此处是快速变更的绝佳之选。所有此处可以覆盖的变量可以查阅本页

在你的theme文件夹里的这些.scss文件之上,你每个自定义组件都有一个对应的。刷新一下你的记忆,Ionic 2中大部分你创建的组件看起来是这样的:
my-component

  • my-component.ts
  • my-component.html
  • my-component.scss

.ts里面是类定义,.html是模板文件,.scss就是组件的样式文件了。虽然不是严格要求的,但是你还是要创建 .scss 文件,而不是通过 app.core.scss 文件来定义他的样式。如果你是使用Ionic CLI命令来生成组件的时候,.scss 文件会自动生成。
为啥?虽然你可以将所有样式放到app.core.scss文件里面,但是像上面这样单独创建一个样式表可以带来两个好处:

  • 架构 —— 将代码分离出来可以让你的文件保持较小的体积,功能上是一样的,。由于每个组件的样式都有单独定义的 .scss,这样一样就不用费心费力的去找他的定义了。
  • 模块性 —— Angular 2和Ionic 2使用这样的组件样式结构上因为模块性。之前的版本,代码互相交织难以分离和重用。现在,特殊组件需要的特殊功能都包含在他自己的文件夹里面,这样一来他就可以很轻松的重用以及拖入到其他项目。

原理我们已经熟悉了,现在我们来开始学习给Ionic 2应用定制样式。

Ionic 2应用定制主题的方法

以下我将讲到一些不同的定制主题的方式,你可以任意选择。有可能什么方式做什么事情有点不大清晰,因为在很多案例中你可以通过不同的方式来达到相同的目的。一般而言,你应该尽量不要通过创建自定义样式的方式来达到你的目的(这个最后讲)。你应该先通过预定义属性或者覆盖SASS变量来达到你的目的。如果这样无法做到的话,你在考虑创建你的自定义样式。不要担心,尽量使事情简单化。

1.属性

改变样式最简单的方式是给元素添加你正在使用的属性。如上所述,SASS用来定义一些颜色:

  • primary
  • secondary
  • danger
  • light
  • dark
  • favorite

你可以在app.variables.scss文件中看到他们的定义:

  1. $colors: (
  2. primary: #387ef5,
  3. secondary: #32db64,
  4. danger: #f53d3d,
  5. light: #f4f4f4,
  6. dark: #222,
  7. favorite: #69BB7B
  8. );

可以看到Ionic提供的这些默认的颜色是什么,你也可以覆盖以上颜色为任意你喜欢的色值。大部分你添加primary属性的元素将会变成蓝色,添加danger属性的会变成红色。如果你更改他们的话primary可以显示为紫色,danger可以将元素变成粉色。
如果想要对一个按钮使用secondary的话,我们应当这么做:

  1. <button color="secondary"></button>

但是如果我想对一个导航条使用secondary颜色的话:

  1. <ion-navbar color="secondary"></ion-navbar>

记住,这些属性不只是改变每个元素的颜色这么简单,一些属性还可以改变元素的位置:

  1. <ion-navbar color="secondary">
  2. <ion-buttons end>
  3. <button ion-button color="primary">I'm a primary coloured button in the end position of the nav bar</button>
  4. </ion-buttons>
  5. </ion-navbar>

上面的代码中用到了end属性来决定按钮在哪里显示。同时,我们对button使用了ion-button属性,这样Ionic知道对这个按钮应用样式。我们也可以控制一个列表是否可以有边缘:

  1. <ion-list no-lines></ion-list>

甚至用来控制列表条目是否显示箭头来说明是是否被点击:

  1. <ion-item detail-none></ion-item>

还有大量的其他这样的属性,所以在使用Ionic制作组件之前一定要多看看文档。no-lines属性对于从列表中移除线条真的非常简单,但是如果你不知道这个属性的存在的话(可能性还蛮大的),那么你就不能继续创建你的自定义样式了。这就是我为什么建议你优先使用属性,因为可以帮你节省大量的工作量。

2.SASS变量

接下来可以用来控制应用样式的方法是更改默认的SASS变量(例如编辑我们上面提到过的$color)。这个方法非常方便,因为他可以让你大范围的对指定的事物进行变更。我之前也提及SASS变量,但是基本上在你的.scss中你可以这样:

  1. $my-variable: red;

然后在所有的.scss文件中你可以用$my-variable。这样一来,假设你想将20个不同元素的背景设置为红色,与对每个进行如下变更:

  1. background-color: red;

对比,你可以这样去操作:

  1. background-color: $my-variable;

这样做的好处是当你想把背景色从红色环岛绿色的时候,你只需要把这一个变量设为绿色即可— 用不着去一个一个的编辑。这就是为啥你发现变量的都是以primarydanger的方式去命名,而不是具体的bluered。有时候当你想将你的主色变为紫色,但是如果你给一个名为$my-blue-color设为紫色的话,会让你的代码看起来很混乱。
可能你需要自己定义的变量不多,但是Ionic定义和使用了大量的变量,你可以很轻松的将他们覆盖为其他东西。我们看一下其中一些变量:

  • $background-color
  • $link-color
  • $list-background-color
  • $list-border-color
  • $menu-width
  • $segment-button-ios-activated-transition

可以查看文档来具体了解这些变量以及他的默认值,虽然他们的名字很清晰的表达出来。就像你在上面的范例中看到的一样,他们简直不能更清楚了。
对这些变量进行编辑很简单,打开app.variable.scss然后插入你自己的定义就可以了。以下是本书一个例子的app.variable.scss

  1. $colors: (
  2. primary: #387ef5,
  3. secondary: #32db64,
  4. danger: #f53d3d,
  5. light: #f4f4f4,
  6. dark: #222,
  7. favorite: #69BB7B
  8. );
  9. $list-background-color: #fff;
  10. $list-ios-activated-background-color: #3aff74;
  11. $list-md-activated-background-color: #3aff74;
  12. $checkbox-ios-background-color-on: #32db64;
  13. $checkbox-ios-icon-border-color-on: #fff;
  14. $checkbox-md-icon-background-color-on: #32db64;
  15. $checkbox-md-icon-background-color-off: #fff;
  16. $checkbox-md-icon-border-color-off: #cecece;
  17. $checkbox-md-icon-border-color-on: #32db64;

以上范例中,对一些默认的颜色进行了改动,iOS和Android的一些特有样式也有覆盖。
注意这里有用到 md ,这是 material design的简写,是用于Android的。Ionic 2根据平台约定无缝调节样式显示 — 对于Android来将意味这使用了 material design。
译者: Material Design
编辑这些默认的SASS的伟大之处在于,一处修改,应用内用到之处都生效。那些使用别的变量的值的变量,如果你想在CSS中手动去修改的话,工作量可大了。

3.配置

另一个改变样式的快捷方式是修改app.module.ts里面提供给IonicModuleConfig对象。
大体上这里是用于设置应用内广泛的默认行为,例如按钮和页签的摆放,图标的使用样式,过度动画等等。通常是最好不要对他进行修改,除非你有特别的需要在这里修改的理由,因为Ionic会根据平台自动调节显示 — 跟config过不去就是跟Ionic过不去。
有时候你想强制事物一个指定行为,Config就是用来做这样的特例的。一下范例是用来这么做的:

  1. IonicModule.forRoot(MyApp, {
  2. backButtonText: 'Go Back',
  3. iconMode: 'ios',
  4. modalEnter: 'modal-slide-in',
  5. modalLeave: 'modal-slide-out',
  6. tabbarPlacement: 'bottom',
  7. pageTransition: 'ios'
  8. })

如果你想强制iOS使用Material Design你可以这样去设置Config:

  1. IonicModule.forRoot(MyApp, {
  2. mode: 'md'
  3. })

再次强调,除非有特别的理由,否则不要这样做。也许你喜欢material design,或者你习惯了material design,但是你的iOS用户看到的东西跟你的不一样。记住这一点之后,Config也允许你为特殊平台做特殊配置:

  1. IonicModule.forRoot(MyApp, {
  2. tabbarPlacement: 'bottom',
  3. platforms: {
  4. ios: {
  5. tabbarPlacement: 'top',
  6. }
  7. }
  8. })

关于Config对象的更多信息,请查阅文档

4.自定义样式

在我们聊到使用属性改变元素颜色之前,假设你可以将这些属性覆盖为你喜欢的任意值,设置primary,secondary,danger变量来匹配你的设计样稿的,然后使用它们来设置你的元素,而不是定义你的自定义CSS类,这也不是为一个好的途径。
但是有些时候,你想要定义一些简单的老CSS类来达到你的需求。如果变量是针对整个应用的话,那么可以将他定义在global.scss中,如果是单独针对某个组件的,那么可以定义在此组件的.scss中。
当然,你也可以直接在元素上通过style标签来自定义样式,但请谨慎使用。

如上,你可以通过一些不同的方法修改你的Ionic 2应用的样式。总的来讲,尽量去简单的达到你的需要。尽量使用属性和SASS变量,因为他使你的生活如此简单。

之前也说过,Ionic在iOS和Android之间平滑调节UI,所以当你越‘骇客式’或者‘暴力’的去自定义样式,你就越粗鲁地破坏了这个行为。