第七课:制作引导滑页与定制主题

这是本应用的最后一节课,我们将添加一些最终的方案来优化用户体验。我们将添加一个滑页手册来向用户展示如何使用本应用(只会在第一次打开应用的时候展示),然后添加一些样式让应用看起来漂亮一些。
我们先来看看滑页。

滑动组件

使用滑动卡片手册来向用户做应用介绍说非常通用的一个做法。Ionice有一个内置的滑动组件,所以我们将用它来实现,然后确保用户不用每次打开应用都看到他。
滑动组件本身就很简单,可以用来展示一系列的图片,最后一个滑动页里面是一个按钮用于进入应用。
首先,我们创建好滑动组件,然后我们研究如何将他整合到我们的应用中。我们从创建模板开始。
> 修改src/pages/intro/intro.html 如下:

  1. <ion-content>
  2. <ion-slides [options]="slideOptions">
  3. <ion-slide>
  4. <img src="assets/images/slide1.png" />
  5. </ion-slide>
  6. <ion-slide>
  7. <img src="assets/images/slide2.png" />
  8. </ion-slide>
  9. <ion-slide>
  10. <img src="assets/images/slide3.png" />
  11. </ion-slide>
  12. <ion-slide>
  13. <ion-row>
  14. <ion-col>
  15. <button ion-button color="light" (click)="goToHome()" style="margin-top:20px;">Start Using Quicklists</button>
  16. </ion-col>
  17. </ion-row>
  18. <ion-row>
  19. <ion-col>
  20. <img src="assets/images/slide4.png" />
  21. </ion-col>
  22. </ion-row>
  23. </ion-slide>
  24. </ion-slides>
  25. </ion-content>

第一眼你就会发现模板里并没有navbar,只有内容区域。并不是所有的页面都需要包含导航条的,我们这里就不需要。余下的代码就非常简单了,我们用到了一个带有options属性的,这样我们稍后可以在类定义中给他配置一些选项,每个滑动页都是以来定义的。
这样一来,以上代码中用户首先会看到一个容纳了slide1图片的滑动也,然后放他们滑动的时候将火看到slide2等等知道他们到最后一个页面,上面有一个按钮直达home页。
最后一个滑动也稍微复杂些,因为我们用到了这样我们可以随心所欲的摆放按钮。这两个指令组成了Ionic 2的grid栅格系统,row是一个一个堆起来的,col是边靠边列出来的。一下图标可以清晰的表达这一点:
行与列

这是个比较简单的范例,我们只是想让按钮显示到图片的顶部,但是你也可以通过给列提供宽度来制作更复杂的布局:

  1. <ion-row>
  2. <ion-col width-10></ion-col>
  3. <ion-col width-50></ion-col>
  4. </ion-row>

你可以嵌套任意你想要的层数。咱们的栅格布局效果图是这样的:
介绍页

现在我们来定义intro组件的类。
> 修改 src/pages/intro/intro.ts为如下:

  1. import { Component } from '@angular/core';
  2. import { NavController } from 'ionic-angular';
  3. import { HomePage } from '../home/home';
  4. @Component({
  5. selector: 'page-intro',
  6. templateUrl: 'intro.html'
  7. })
  8. export class IntroPage {
  9. slideOptions: any;
  10. constructor(public nav: NavController){
  11. this.slideOptions = {
  12. pager: true
  13. };
  14. }
  15. goToHome(): void {
  16. this.nav.setRoot(HomePage);
  17. }
  18. }

这是不是迄今为止见过的最简单的类?他所作的知识导入home页面,给我们的slider设置pager属性,当调用goToHome的时候通过NavController改变根页面。这样我们在最后一个滑动页点击按钮的时候就可以跳转到home页面,但是我们可能会遇到点问题。当用户每次打开这个原因的时候都要看一遍这个用户手册。要解决这个问题的时候,我们需要对home.ts做一个改动。
> 修改 src/pages/home/home.ts为如下:

  1. import { Component } from '@angular/core';
  2. import { NavController, AlertController, Platform } from 'ionic-angular';
  3. import { ChecklistPage } from '../checklist/checklist';
  4. import { ChecklistModel } from '../../models/checklist-model';
  5. import { Data } from '../../providers/data';
  6. import { Keyboard } from 'ionic-native';
  7. import { IntroPage } from '../intro/intro';
  8. import { Storage } from '@ionic/storage';

> 修改 src/pages/home/home.ts 的ionViewDidLoad方法如下:

  1. checklists: ChecklistModel[] = [];
  2. constructor(public nav: NavController, public dataService: Data, public alertCtrl: AlertController, public storage: Storage, public platform:Platform) {
  3. }
  4. ionViewDidLoad(){
  5. this.platform.ready().then(() => {
  6. this.storage.get('introShown').then((result) => {
  7. if(!result){
  8. this.storage.set('introShown', true);
  9. this.nav.setRoot(IntroPage);
  10. }
  11. });
  12. this.dataService.getData().then((checklists) => {
  13. let savedChecklists: any = false;
  14. if(typeof(checklists) != "undefined"){
  15. savedChecklists = JSON.parse(checklists);
  16. }
  17. if(savedChecklists){
  18. savedChecklists.forEach((savedChecklist) => {
  19. let loadChecklist = new ChecklistModel(savedChecklist.title, savedChecklist.items);
  20. this.checklists.push(loadChecklist);
  21. loadChecklist.checklist.subscribe(update => {
  22. this.save();
  23. });
  24. });
  25. }
  26. });
  27. });
  28. }

我们再次导入和用到了Storage。我们会用他来存储一个标记告诉我们是否有展示过用户手册。
这样我们设置好了新的存储,检查introShown标记的存在。如果不存在的话我们将转到介绍页面然后将标记值设为true这样下次他就不会展示了。
注意:测试的时候,如果你想清除此标记值,那么直需要删除浏览器创建的WebSQL就可以了。在Chrome上,访问chrome://settings/cookies,查找localhost,然后删除其中的_ionicstorage。这样当然会删除在WebSQL中存储的所有数据,不不止是introShown标记。

定制主题

当前应用的功能已经100%完成了。我们需要给应用添加一个样式让他比现在看起来更漂亮些。
你应该记得基础部分里面有一些不同的给应用添加样式的方法。我们将给每个组件添加指定的样式,我们将在核心文件中添加一些通用样式,然后在变量文件内覆盖一些SASS变量。如果你跳过了那部分,或者还不大清楚我讲的什么的话,建议你回去重新读一下基础部分的定制主题。
由于我们在Ionic 2中用SASS来制作CSS,我们可以嵌入CSS样式。由于每个页面是他自己的组件,我们可以在组件里有目的的针对元素。尽管如此,我们的每个组件都有独立的.scss文件,CSS规则还是全局应用的。如果在其中一个组件中添加如下样式:

  1. p {
  2. font-size: 1.2em !important;
  3. }

他将会被应用到应用内的每个组件。
> 修改 src/pages/intro/intro.scss 为如下:

  1. page-intro {
  2. ion-slide {
  3. background-color: #32db64;
  4. }
  5. ion-slide img {
  6. height: 85vh !important;
  7. width: auto !important;
  8. }
  9. }

我们在page-intro里面定义了页面的样式,这样一来他只会在页面添加到DOM的时候应用到元素(因为这个组件有一个page-intro 选择器selector)里面的元素上,而不是整个应用。这个样式会把滑动组件的背景色设为绿色,将滑动页里面的图片设置为视图高度的85%。
其他组件需要添加其他一些类到模板中,这里我直接po代码了。
> 修改 src/pages/home/home.html 为如下:

  1. <ion-header>
  2. <ion-navbar color="secondary">
  3. <ion-title>
  4. <img src = "assets/images/logo.png" />
  5. </ion-title>
  6. <ion-buttons end>
  7. <button ion-button icon-only (click)="addChecklist()"><ion-icon name="add-circle"></ion-icon></button>
  8. </ion-buttons>
  9. </ion-navbar>
  10. </ion-header>
  11. <ion-content>
  12. <ion-list no-lines>
  13. <ion-item-sliding *ngFor="let checklist of checklists">
  14. <button ion-item (click)="viewChecklist(checklist)" class="home-item">
  15. {{checklist.title}}
  16. <span class="secondary-detail">{{checklist.items.length}} items</span>
  17. </button>
  18. <ion-item-options>
  19. <button ion-button icon-only color="light" (click)="renameChecklist(checklist)"><ion-icon
  20. name="clipboard"></ion-icon></button>
  21. <button ion-button icon-only color="danger" (click)="removeChecklist(checklist)"><ion-icon
  22. name="trash"></ion-icon></button>
  23. </ion-item-options>
  24. </ion-item-sliding>
  25. </ion-list>
  26. </ion-content>

> 修改 src/pages/home/home.scss 为如下:

  1. page-home {
  2. ion-item-sliding {
  3. margin: 5px;
  4. }
  5. .home-item {
  6. font-size: 1.2em;
  7. font-weight: bold;
  8. color: #282828;
  9. padding-top: 10px;
  10. padding-bottom: 10px;
  11. }
  12. .secondary-detail {
  13. display: block;
  14. color: #cecece;
  15. font-weight: 400;
  16. margin-top: 10px;
  17. }
  18. }

我们这里没有做什么疯狂的事情,只是对边距,间隔和颜色做了一些调整。接着我们对checklist页面做相同的事情。
> 修改 src/pages/checklist/checklist.scss 为如下:

  1. page-checklist {
  2. ion-item-sliding {
  3. margin: 5px;
  4. }
  5. ion-checkbox {
  6. font-size: 0.9em;
  7. font-weight: bold;
  8. color: #282828;
  9. padding-top: 0px;
  10. padding-bottom: 0px;
  11. padding-left: 4px;
  12. border: none !important;
  13. }
  14. ion-item-content {
  15. border: none !important;
  16. }
  17. ion-checkbox {
  18. border-bottom: none !important;
  19. }
  20. ion-checkbox .item-inner {
  21. border-bottom: none !important;
  22. }
  23. }

同样,只是一些轻微的调整。我们现在来对整个应用添加一些样式。
> 添加以下样式到 src/app/app.scss :

  1. ion-content {
  2. background-color: #32db64 !important;
  3. }
  4. .logo {
  5. max-height: 39px;
  6. }
  7. button {
  8. border: none !important;
  9. }

这里我们让整个应用的背景色变成了绿色,我们设置了logo的最大高度,然后移除了按钮的边缘。最后,我们将覆盖一些SASS变量。
> 修改 src/theme/variables.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特有样式(名字很明显)。Ionic 2最酷的事情之一是他可以很好的操作iOS和Android不同的UI,大部分情况下,他都很完美。当你在iOS和Android上实际看的话,会看到他们之间的不同:
iOS和Android的不同

注意:一个比较便利的查看iOS和Android不同的途径是利用Ionic Lab,可以通过命令ionic serve -l来激活。可以发现通过Ionic Lab查看应用的时候侧边有滚动条,我觉得这是个bug,他在真实设备上运行的时候不会出现(Chrome Dev Tools模拟器也不会有)。
可以看到,Ionic 2自动适配应用当前运行平台的规范。

总结

就这样!应用现在就宣告完成,看起来也挺不错的。