【Appetite】ionic3实录(六)首页实现

前文再续,书接上一回,上上回说到自定义组件,本节应该讲怎么做自定义组件的同时怎么调用的,只是本实例应做自定义组件的有好几个,不可能每个都写出来讲解,这会显得冗余了,所以决定只把其中一个较有代表性的做成自定义组件。在写这个组件前,我们按照页面的顺序先逐个实现。不知道一个小时能写完不,赶上班…

仍然是先上UI设计图:

image.png

观察之,发布者和内容的文本信息可以用ionic现有的组件实现,而视频播放和图片画廊(如果是轮播图可以用slides组件,它是阉割并封装过的swiper,好像现在这样的效果不能实现)需要使用第三方组件。步骤如下:

一、准备素材:

鸡蛋两只,油两茶匙……呃,说错,应该是这些:

  1. 食物照片;
  2. 人物头像;
  3. 视频封面;
  4. 视频;

这些可以上素材网下,也可以简单点找度娘(不过小心图片版权问题):

百度食物图片

如果是远程地址则先保存地址,如果是放本地的就在src/assets里面找个地方放,呆会要把地址作为数据一部分,我这选择存放本地。

二、准备数据:

我仍是图省事,这里采用本地数据,在src/assets里面新建data文件夹,再在里面建一个friend-news.json文件,为了便于观察,整理了内容如下:

{
    "success": "true",
    "result":[{
        "headImg": "assets/imgs/girl2.jpg",
        "name": "Amy Hinez", "createTime": "May 24,2016", "content": "Some content", "favorites": "1225", "comments": "198",
        "type":"0", 
        "cover": "", 
        "medias":[
            {"id": "1", "src": "../assets/imgs/foods/1.jpg"},
            {"id": "2", "src": "../assets/imgs/foods/2.jpg"},
            {"id": "3", "src": "../assets/imgs/foods/3.jpg"},
            {"id": "4", "src": "../assets/imgs/foods/4.jpg"}
        ]
    },{
        "headImg": "../assets/imgs/girl2.jpg",
        "name": "Amy Hinez", "createTime": "May 24,2016", "content": "Some content", "favorites": "1225", "comments": "198",
        "type":"1", 
        "cover": "../assets/imgs/foods/cover1.jpg", 
        "medias":[
            {"id": "1", "src": "../assets/data/oceans.mp4"}
        ]
    },{
        "headImg": "../assets/imgs/girl2.jpg",
        "name": "Amy Hinez", "createTime": "May 24,2016", "content": "Some content", "favorites": "1225", "comments": "198",
        "type":"0", 
        "cover": "", 
        "medias":[
            {"id": "1", "src": "../assets/imgs/foods/1.jpg"},
            {"id": "2", "src": "../assets/imgs/foods/2.jpg"},
            {"id": "3", "src": "../assets/imgs/foods/3.jpg"},
            {"id": "4", "src": "../assets/imgs/foods/4.jpg"}
        ]
    }]
}

这类似一个服务接口返回来的数据,success属性是为了和上一节的基本网络服务格式一致而设定的属性,type属性为0表示画廊,1为视频,其它的应该从字段名称大致知道是什么东西吧?

接着我们执行命令新建一个HomeProvider用来统一管理首页的数据处理方法(这里按页面逻辑来划分的,当然你也可以按业务类型来划分):

ionic g provider home

命令执行完成,打开文件写入一个方法:

  getFriendNews(){
    //第二个参数为false表示使用相对路径
    return this.commonProvider.get("../assets/data/friend-news.json", false);
  }

最后记得在app.module.ts里面的providers里添加配置它,至此数据就准备好了。

三、安装视频播放组件

用的是videogular2,可参考我另一篇文章:《【技巧】ionic3视频播放》

四、安装swiper组件

npm install swiper --save

四、实现首页

打开home.ts文件,修改内容为:

import { Component, ViewChildren, ChangeDetectorRef } from '@angular/core';
import { NavController } from 'ionic-angular';
import { HomeProvider } from '../../providers/home/home';

import Swiper from 'swiper';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {

  frendNews: any[] = [];
  constructor(public navCtrl: NavController, private cd: ChangeDetectorRef, private homeProvider: HomeProvider) {
  }

  ionViewDidLoad(){
    this.getFriendNews();
  }

  //获取数据
  getFriendNews(){
    this.homeProvider.getFriendNews().then((res: any)=>{
      if(res.success){
        this.frendNews = res.result;
        this.cd.detectChanges();
        this.initSwiper();
      }else{
        //如提示框等错误提示
        console.log(res.msg);
      }
    });
  }

  //初始化Swiper
  initSwiper(){
     new Swiper('.swiper-container', {
        paginationClickable: true,
        slidesPerView:  2,
        width: 280,
        spaceBetween : 10,
        watchActiveIndex: true,
        initialSlide: 0,//初始化显示第几个
        zoom: true,//双击,手势缩放
        loop: false,//循环切换
        lazyLoading: true,//延迟加载
        lazyLoadingOnTransitionStart: true,
        lazyLoadingInPrevNext : true
      });
  }
}

代码看上去长,其实没啥内容,其中图片画廊这个效果有点特别,要显示后一张的一部分,好让别人知道后面还有,所以参数要特别设定下。initSwiper方法貌似要在页面渲染完成后才能使用,而getFriendNews获取数据后未必渲染完成,故不能马上调用,所以调用this.cd.detectChanges()来处理下,关于这个可以查看我另一篇文章。此外getFriendNews没有后续操作,所以异步调用省掉return。

打开home.html文件,把<ion-content>的内容更改为下面内容:

<ion-content>
  <ion-list>
    <div *ngFor="let item of frendNews">
      <!-- 发布人信息 -->
      <ion-item>
        <ion-avatar item-start>
          ![]({{item.headImg}})
        </ion-avatar>
        <h2><strong><span color="dark">{{item.name}}</span></strong></h2>
        <ion-note item-right>{{item.createTime}}</ion-note>
      </ion-item>
      <!-- 视频播放器 -->
      <vg-player class="video-container" *ngIf="item.type == 1; else elseBlock">
        <vg-overlay-play></vg-overlay-play>
        <vg-buffering></vg-buffering>
        <vg-controls>
          <vg-play-pause></vg-play-pause>
          <vg-playback-button></vg-playback-button>

          <vg-time-display vgProperty="current" vgFormat="mm:ss"></vg-time-display>
          <vg-time-display vgProperty="left" vgFormat="mm:ss"></vg-time-display>
          <vg-time-display vgProperty="total" vgFormat="mm:ss"></vg-time-display>
          <vg-mute></vg-mute>
          <vg-volume></vg-volume>
          <vg-fullscreen></vg-fullscreen>
        </vg-controls>
        <video #myMedia [vgMedia]="myMedia" class="video-js vjs-default-skin vjs-fluid" height="400" width="600" preload="auto" poster="{{item.cover}}"
          crossorigin playsinline webkit-playsinline>
          <source *ngFor="let cItem of item.medias" src="{{cItem.src}}" type="video/mp4">
        </video>
      </vg-player>
      <!-- 画廊组件 -->
      <ng-template #elseBlock>
        <div class="swiper-container">
          <div class="swiper-wrapper">
            <div class="swiper-slide" *ngFor="let cItem of item.medias">
              ![]({{cItem.src}})
            </div>
          </div>
        </div>
      </ng-template>
      <p padding-left padding-right>{{item.content}}</p>
      <!-- 按钮组 -->
      <div class="item-block">
        <div>
          <button ion-button clear icon-left small outline (click)="onTest()">
            <ion-icon name="heart" ></ion-icon>
            <div>{{item.favorites}}</div>
          </button>
          <button ion-button clear icon-left small>
            <ion-icon name="text-outline"></ion-icon>
            <div>{{item.comments}}</div>
          </button>
        </div>
        <button ion-button clear icon-only small item-right>
            <ion-icon name="more"></ion-icon>
        </button>
      </div>
      <!-- 分隔符 -->
      <div class="item-divider-sm"></div>
    </div>
  </ion-list>
</ion-content>

看上去内容也很多,但按注释看每个部分的话就相对好理解些了。用了结构指令ngIf来选择显示视频还是画廊;按钮组可以换用grid布局;此外,为了性能考虑,应用virtualScroll,但我简单一用时布局有变形,赶时间没分析,换用现在方式。

打开home.scss文件,修改如下:

page-home {
    .swiper-slide img {
        height: 120px;
    }
}

五、微调

  1. variables.scss文件修改文字颜色和稍微调大头像:
$list-ios-text-color: color($colors, gray);
$item-ios-avatar-size: 42px;
  1. app.scss里添加分隔栏的样式
.item-divider-sm {
    height: 10px;
    background-color: color($colors, light-gray);
}

最后看下实际效果图:


实际效果图

因为赶着上班,写得有点急,微调没怎么调,特别是swiper的参数配置中的宽高有点诡异,还没摸清,另外说明内容还要补充一下,晚些再完善。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,723评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,080评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,604评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,440评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,431评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,499评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,893评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,541评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,751评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,547评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,619评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,320评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,890评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,896评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,137评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,796评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,335评论 2 342

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,579评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,368评论 25 707
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,016评论 4 62
  • 木日子阅读 199评论 0 0
  • 为什么用这句台词做标题,可能是因为《最爱》里面的濒临死亡的两个主角最好的和最真挚的愿望; 我们结婚吧,趁活着! 最...
    钱嘟嘟左卫门阅读 607评论 0 1