第三课:布局

我发现制作一个应用最好从基础布局开始 — 他基本可以看作是线图联系,帮助固化应用的需求。我们这个应用的布局没啥特别的东西,但是有一个需要添加的用户界面元素需要一点点技巧。
我们这个应用有两个页面,主页和滑页,本课中将会制作他们的模板。滑页非常简单,所以本课的大部分都是关于主页的。

Home页

主页有一个用户拍的照片的列表,用户可以在其中删除它们,一个拍新的照片的选项(只有在当日没拍的情况下),一个展示图片滑页的选项。效果图上这样的:
首页

这个布局最有技巧性的是顶部的“SMILE!”图片,实际上是一个按钮,用于拍照的按钮,同时,他也只会在用户当日没有拍照的情况下才显示。如果用户当日没有拍照的话就不会显示的。
我们先从基础布局入手,然后看怎么实现拍照按钮。
> 修改src/pages/home/home.html 为如下:

  1. <ion-header>
  2. <ion-navbar color="danger">
  3. <ion-title>
  4. <img src="assets/images/logo.png" />
  5. </ion-title>
  6. <ion-buttons end>
  7. <button ion-button icon-only (click)="playSlideshow()"><ion-icon name="play"></ion-icon></button>
  8. </ion-buttons>
  9. </ion-navbar>
  10. </ion-header>
  11. <ion-content>
  12. <ion-list>
  13. <ion-item-sliding>
  14. <ion-item>
  15. <img src="http://placehold.it/100x100" />
  16. <ion-badge item-right light>0 days ago</ion-badge>
  17. </ion-item>
  18. <ion-item-options>
  19. <button ion-button icon-only light (click)="removePhoto(photo)"><ion-icon name="trash"></ion-icon></button>
  20. </ion-item-options>
  21. </ion-item-sliding>
  22. </ion-list>
  23. </ion-content>

我们把这个模板打碎来讲解。模板的第一个部分是导航条:

  1. <ion-navbar color="danger">
  2. <ion-title>
  3. <img src="assets/images/logo.png" />
  4. </ion-title>
  5. <ion-buttons end>
  6. <button ion-button icon-only (click)="playSlideshow()"><ion-icon name="play"></ion-icon></button>
  7. </ion-buttons>
  8. </ion-navbar>

ion-navbar 允许我们添加一个页首条到我们的应用顶部用于持有按钮,标题,甚至在需要的时候直接整合Ionic导航系统来展示一个回退按钮。
我们给navbar添加了danger属性将他样式化到我们的danger颜色,这个颜色变了色在variables.scss中定义的(后续会配置)。
在navbar中我们用到了ion-title,基本就是用来展示当前页面的文本标题和logo的。同时我们也用到了ion-buttons来创建按钮。通过指定end属性,所有按钮将被排列在右边,当我们指定的是‘start’属性的时候,将会从左边开始排列。
最后,我们将所有按钮列入ion-buttons中。这个按钮用到了一个play图标,有一个点击处理器,处理器将调用home.ts文件里的playSlideshow()函数(这个函数当前未创建)。
模板接下来的部分是内容部分,包括了一个列表:

  1. <ion-content>
  2. <ion-list>
  3. <ion-item-sliding>
  4. <ion-item>
  5. <img src="http://placehold.it/100x100" />
  6. <ion-badge item-right light>0 days ago</ion-badge>
  7. </ion-item>
  8. <ion-item-options>
  9. <button ion-button icon-only color="light" (click)="removePhoto(photo)"><ion-icon name="trash"></ion-icon></button>
  10. </ion-item-options>
  11. </ion-item-sliding>
  12. </ion-list>
  13. </ion-content>

在看列表之前,我们看到所有东西都被包围在ion-content里 — 这就是页面主体内容展示的地方,在大部分情况下除了导航条外的所有内容都要放在这里。
跟一个普通列表其实也差不多,看:

  1. <ul>
  2. <li></li>
  3. <li></li>
  4. <li></li>
  5. </ul>

Ionic里面创建列表的方式基本一样:

  1. <ion-list>
  2. <ion-item></ion-item>
  3. <ion-item></ion-item>
  4. <ion-item></ion-item>
  5. </ion-list>

当然,我们的看起来稍微复杂点,所以我们还是来研究研究。首先与常理不一样的是我们在ion-list加入了no-lines属性。就像给navbar添加的danger属性一样,这个属性会对我们的列表起作用,他会使列表项不显示边缘。
接下来的变得多一点技巧性,也就是我们设置滑动项的地方。一个,和普通的不同,他有两套内容 — 列表项本身,然后是在用户滑动的时候可见。
第一部分内的代码是普通的定义。项里面是用户拍的照片(我们最后还是会循环所有相片),但是现在我们只是用了个图片占了个位置。我们也在项的右边添加了一个勋章用于展示这个照片上多久之前拍的。我们现在用的都是假数据,后面再用真数据。
最后,我们来到了代码的第二部分,,仅用来展示活动展示的内容。当前应用中,我们只是添加了一个‘Delete’按钮,当点击他的时候会传入当前照片的引用。现在传入的photo引用不会有实际效果(调用的函数也不会有效果因为都没创建呢),稍后制作相片循环的时候我们在讨论如何建立这个应用。
现在,我们来添加之前讲到的那个条件照片按钮。
> 修改 src/pages/home/home.html 的 content 部分为如下:

  1. <ion-content>
  2. <ion-list>
  3. <button ion-item *ngIf="!photoTaken" detail-none (click)="takePhoto()">
  4. <img src="assets/images/smile.png" />
  5. </button>
  6. <ion-item-sliding>
  7. <ion-item>
  8. <img src="http://placehold.it/100x100" />
  9. <ion-badge item-right light>0 days ago</ion-badge>
  10. </ion-item>
  11. <ion-item-options>
  12. <button ion-button icon-only color="light" (click)="removePhoto(photo)"><ion-icon name="trash"></ion-icon></button>
  13. </ion-item-options>
  14. </ion-item-sliding>
  15. </ion-list>
  16. </ion-content>

注意,我们在列表里的滑动选项上面加入了一个新的项,但是我们不是直接用的而是用的button然后给他使用ion-item指令。在视觉上,这两种方法其实是一样的,但是在移动设备上除了buttona之外的点击处理都会有一点延迟。我们不想要这个延迟,所以我们使用按钮。
由于按钮会默认有自带样式的,而我们这里不想要那些样式,所以我们给他添加了detail-none属性。当然,我们也给他添加了一个点击处理器用于触发后面将会创建的takePhoto函数,但是这里最重要的还是 ngIf 指令。
ngIf 是Angular2提供的条件指令之一,允许我们根据数据改变模板显示。在现在的模板中,含有 ngIf 指令的元素只会在表达式为true的时候才会全部显示。由于我们的表达式是这样的:

  1. *ngIf="!photoTaken"

所以我们的按钮只有在photoTakenfalse的时候才会显示。稍后,我们会在home.ts中创建一个photoTaken变量用于追踪用户当日是否拍照。
现在运行以下命令的话:

  1. ionic serve

会看到如下效果图:
效果图

显然,还有很多事情需要去完成,但是目前我们只需要对主页做这么多就够了,所以,我们继续Slideshow 页。

Slideshow 页

就像我之前说过的那样,slideshow页将会超级简单。他就是一个弹出的模态框展示所有用户拍的照片的滑页。我们只需要为照片提供一个容器,一个按钮来重启滑页和一个按钮来关闭页面就可以了。
> 修改 src/pages/slideshow/slideshow.html 为如下:

  1. <ion-header>
  2. <ion-toolbar color="danger">
  3. <ion-title>Play</ion-title>
  4. <ion-buttons start>
  5. <button ion-button icon-only (click)="playPhotos()"><ion-icon name="refresh"></ion-icon></button>
  6. </ion-buttons>
  7. <ion-buttons end>
  8. <button ion-button icon-only (click)="closeModal()"><ion-icon name="close"></ion-icon></button>
  9. </ion-buttons>
  10. </ion-toolbar>
  11. </ion-header>
  12. <ion-content>
  13. <div class="image-container">
  14. <img #imagePlayer id="imagePlayer" src = "" />
  15. </div>
  16. </ion-content>

你已经知道navbar和按钮咋工作的了,所以唯一的新玩意是图片播放器(image player)。我们只是在内容显示区域添加了一个图片元素。稍后,我们会添加一些代码循环所有用户的照片,通过改变src属性来展示所有照片。我们只要在类里面拿到img的引用就可以了,所以我们创建了一个局部变量 #imagePlayer 这样可以直接在类定义中拿到他了。
目前而言,以上就是我们本课的工作量 — 告诉过你很简单的。

总结

现在,我们应用的两个页面都设置好了,下节课将会进行一些更有趣的事情。实际上,他可能是最有趣的课程之一,因为我们要学习整合本机Camera API然后用他来拍照。