現(xiàn)在應(yīng)用運(yùn)行良好 -- 來(lái)自reddit的GIF,過(guò)濾了文件格式畦娄,然后以video元素進(jìn)行展示又沾。
我們當(dāng)前設(shè)置了gifs作為默認(rèn)subdreddit,對(duì)于本應(yīng)用來(lái)講是個(gè)不錯(cuò)的選擇纷责,用戶也可以根據(jù)喜好對(duì)他進(jìn)行變更捍掺。當(dāng)你離開(kāi)應(yīng)用稍后重新進(jìn)入的時(shí)候,他會(huì)重新設(shè)置為默認(rèn)的gifssubreddit再膳。當(dāng)用戶對(duì)gifs不敢興趣的時(shí)候這會(huì)變得很煩人挺勿。
所以我們將要做的事制作一個(gè)Settings頁(yè),用戶可以在其中進(jìn)行如下操作:
- 默認(rèn)subreddit
- 每頁(yè)加載的GIF數(shù)量
- 排序方式
實(shí)現(xiàn)類似這樣的功能也讓我們有機(jī)會(huì)去學(xué)習(xí)如何永久存儲(chǔ)數(shù)據(jù)這個(gè)應(yīng)用將在用戶返回的時(shí)候記得用戶設(shè)置喂柒。
制作一個(gè)Settings頁(yè)
我們將使用Modal模態(tài)頁(yè)來(lái)打開(kāi)設(shè)置頁(yè)不瓶。打開(kāi)模態(tài)頁(yè)和普通頁(yè)面有些許不同,普通頁(yè)面的打開(kāi)基本就是應(yīng)用的導(dǎo)航流的操作了灾杰。模態(tài)頁(yè)基本上是一個(gè)可以在頁(yè)面上顯示然后關(guān)閉的單獨(dú)頁(yè)面(你應(yīng)該對(duì)其他網(wǎng)頁(yè)模態(tài)頁(yè)很熟悉蚊丐,例如Facebook的照片預(yù)覽)。
任何頁(yè)面都可以作為模態(tài)頁(yè)來(lái)打開(kāi)艳吠,所以我們可以像創(chuàng)建其他頁(yè)面那樣來(lái)創(chuàng)建我們的Settings頁(yè)面麦备。我們先從定義Settings頁(yè)的模板開(kāi)始。
> 修改 src/pages/settings/settings.html 為如下:
<ion-header>
<ion-toolbar color="secondary">
<ion-title>Settings</ion-title>
<ion-buttons end>
<button ion-button icon-only (click)="close()"><ion-icon name="close"></ion-icon></button>
</ion-buttons>
</ion-toolbar>
</ion-header>
<ion-content padding>
<ion-card>
<ion-card-header>
About
</ion-card-header>
<ion-card-content>
<p><strong>Giflist</strong> is a client for <strong>reddit</strong>
that will endlessly <strong>stream GIFs</strong> from <strong>any
subreddit that predominantly contains gifs</strong>. By default
it uses the popular <strong>gifs</strong> subreddit, but you can
change this to whatever you like, e.g: perfectloops, me_irl,
chemicalreactiongifs.</p>
<br />
<p>To play a GIF, just tap it. To view the original submission for
any GIF, just tap the title section and it will open in reddit.
You can configure some settings for the application below.
Enjoy!</p>
</ion-card-content>
</ion-card>
<h3>Subreddit</h3>
<ion-input type="text" placeholder="enter subreddit name..." [(ngModel)]="subreddit"></ion-input>
<h3>Sort</h3>
<ion-segment color="secondary" [(ngModel)]="sort">
<ion-segment-button value="hot">
Hot
</ion-segment-button>
<ion-segment-button value="top">
Top
</ion-segment-button>
<ion-segment-button value="new">
New
</ion-segment-button>
</ion-segment>
<h3>Per Page</h3>
<ion-segment color="secondary" [(ngModel)]="perPage">
<ion-segment-button value="5">
5
</ion-segment-button>
<ion-segment-button value="10">
10
</ion-segment-button>
<ion-segment-button value="15">
15
</ion-segment-button>
</ion-segment>
<button ion-button full (click)="save()" color="secondary" style="margin:20px 0px;">Save Settings</button>
</ion-content>
這里沒(méi)做什么瘋狂的事情。我們像往常那樣定義了navbar凛篙,然后給他添加了一個(gè)按鈕用于調(diào)用close函數(shù)關(guān)閉窗口黍匾。
我們添加了一個(gè)<ion-card>用來(lái)向用戶展示應(yīng)用信息,然后我們定義了一些不同的輸入域呛梆。我們定義了一個(gè)文本輸入域來(lái)設(shè)置subreddit锐涯,我們使用了片段組件來(lái)控制sort和perPage值。所有這些數(shù)據(jù)都通過(guò)[(ngModel)] 進(jìn)行了雙向數(shù)據(jù)綁定填物,這樣在類定義里面就可以很容易訪問(wèn)到了纹腌。
> 修改 src/pages/settings/settings.ts 為如下:
import { Component } from '@angular/core';
import { ViewController, NavParams } from 'ionic-angular';
@Component({
selector: 'page-settings',
templateUrl: 'settings.html'
})
export class SettingsPage {
perPage: number;
sort: string;
subreddit: string;
constructor(public view: ViewController, public navParams: NavParams) {
this.perPage = this.navParams.get('perPage');
this.sort = this.navParams.get('sort');
this.subreddit = this.navParams.get('subreddit');
}
save(): void {
let settings = {
perPage: this.perPage,
sort: this.sort,
subreddit: this.subreddit
};
this.view.dismiss(settings);
}
close(): void {
this.view.dismiss();
}
}
可能你一眼就看到了我們?cè)谶@里用navParams來(lái)獲取一些值。早Home頁(yè)啟動(dòng)Settings頁(yè)的時(shí)候我們會(huì)傳過(guò)來(lái)一些值作為Settings頁(yè)的預(yù)設(shè)值滞磺。
另一個(gè)比較奇怪的是我們導(dǎo)入了ViewController -- 當(dāng)以Modal的方式來(lái)啟動(dòng)本頁(yè)的時(shí)候我們需要用到他在頁(yè)面里關(guān)閉本身升薯。在這里我們需要在用戶點(diǎn)擊關(guān)閉或者保存按鈕的時(shí)候關(guān)閉頁(yè)面。如果用戶點(diǎn)擊關(guān)閉按鈕的話雁刷,我們就不用保存設(shè)置覆劈。
在接下來(lái)的部分我們會(huì)處理設(shè)置的保存保礼,但是你可以會(huì)想要怎么才能做到呢 -- 這里的save函數(shù)不是用來(lái)保存一些數(shù)據(jù)的嗎沛励?由于Modal的工作方式的原因,我們可以從以模態(tài)框方式啟動(dòng)的頁(yè)面在關(guān)閉的時(shí)候返回?cái)?shù)據(jù)炮障,所以在這里我們調(diào)用視圖的dismiss函數(shù)的時(shí)候?qū)?huì)把新的設(shè)置值回傳到Home頁(yè)面目派,也就是Setting頁(yè)面的啟動(dòng)也 -- 我們會(huì)在其中操作數(shù)據(jù)的保存。
以模態(tài)頁(yè)的方式打開(kāi)Settings頁(yè)
現(xiàn)在胁赢,定義好了Settings頁(yè)面企蹭,我們需要已模態(tài)也的方式啟動(dòng)他。我們?cè)缇驮陧?yè)首設(shè)置了一個(gè)按鈕來(lái)打開(kāi)設(shè)置頁(yè)智末,所以我們只要完成openSettings函數(shù)就可以了谅摄。
> 修改 src/pages/home/home.ts 的 openSettings 函數(shù)為如下:
openSettings(): void {
let settingsModal = this.modalCtrl.create(SettingsPage, {
perPage: this.redditService.perPage,
sort: this.redditService.sort,
subreddit: this.redditService.subreddit
});
settingsModal.onDidDismiss(settings => {
if(settings){
this.redditService.perPage = settings.perPage;
this.redditService.sort = settings.sort;
this.redditService.subreddit = settings.subreddit;
//this.dataService.save(settings);
this.changeSubreddit();
}
});
settingsModal.present();
}
你也看到了,我們將Settings頁(yè)傳入了正在創(chuàng)建的Modal系馆,同時(shí)也傳入了Settings需要獲取的數(shù)據(jù)送漠。
我們?cè)O(shè)置了onDisDismiss監(jiān)聽(tīng)器用于偵測(cè)Moal關(guān)閉的時(shí)候回傳的數(shù)據(jù)。由于我們只在用戶點(diǎn)擊保存的時(shí)候才會(huì)穿數(shù)據(jù)由蘑,所以代碼也只會(huì)在此時(shí)機(jī)運(yùn)行闽寡。如果回傳了設(shè)置數(shù)據(jù),我們就要用新的值來(lái)更新當(dāng)前值尼酿,同時(shí)我們也要使用dataService來(lái)保存值到存儲(chǔ)(我們還是需要去定義這個(gè)服務(wù))爷狈。由于我們現(xiàn)在有了新的設(shè)置,所以我們需要調(diào)用changeSubreddit來(lái)重置所有事情和根據(jù)新設(shè)置加載新的GIF裳擎。
注意:由于我們目前沒(méi)有實(shí)現(xiàn)數(shù)據(jù)服務(wù)涎永,我們目前會(huì)注釋掉這個(gè)服務(wù)的調(diào)用。
最后,我們調(diào)用present方法來(lái)將模態(tài)框展示給用戶羡微。
保存數(shù)據(jù)
謎團(tuán)的最后一層是制作Data服務(wù)來(lái)保存設(shè)置到存儲(chǔ)以及從存儲(chǔ)獲取設(shè)置支救。
我們將使用Ionic提供的Storage服務(wù)來(lái)存儲(chǔ)數(shù)據(jù)。這也是我最喜歡的Ionic 2新增功能之一拷淘,因?yàn)樗審?fù)雜的存儲(chǔ)流程變得超級(jí)簡(jiǎn)單各墨。存儲(chǔ)數(shù)據(jù)中問(wèn)題有很多,例如操作系統(tǒng)隨機(jī)清理本地緩存數(shù)據(jù)启涯,但是這個(gè)存儲(chǔ)服務(wù)自動(dòng)使用最佳的存儲(chǔ)方式贬堵。
> 修改 src/providers/data.ts 為如下:
import { Injectable } from '@angular/core';
import { Storage } from '@ionic/storage';
@Injectable()
export class Data {
constructor(public storage: Storage) {
}
getData(): Promise<any> {
return this.storage.get('settings');
}
save(data): void {
let newData = JSON.stringify(data);
this.storage.set('settings', newData);
}
}
首先,我們?cè)跇?gòu)造器里注入了存儲(chǔ)服務(wù)结洼。然后我們有兩個(gè)函數(shù)黎做,一個(gè)用于獲取數(shù)據(jù),一個(gè)用于存儲(chǔ)數(shù)據(jù)松忍。getData()函數(shù)將返回所有存儲(chǔ)與存儲(chǔ)空間中的‘settings’上的數(shù)據(jù)蒸殿,save()將把新的數(shù)據(jù)存放到存儲(chǔ)空間的‘settings’字段上。我們以及在Settings模態(tài)框關(guān)閉的時(shí)候調(diào)用了save()鸣峭,現(xiàn)在我們只需要定義localSettings函數(shù)用于在應(yīng)用打開(kāi)的時(shí)候加載之前保存的設(shè)置宏所。
> 修改 src/pages/home/home.ts 的loadSettings函數(shù)為如下:
loadSettings(): void {
this.dataService.getData().then((settings) => {
if(settings && typeof(settings) != "undefined"){
let newSettings = JSON.parse(settings);
this.redditService.settings = newSettings;
if(newSettings.length != 0){
this.redditService.sort = newSettings.sort;
this.redditService.perPage = newSettings.perPage;
this.redditService.subreddit = newSettings.subreddit;
}
}
this.changeSubreddit();
});
}
此處我們簡(jiǎn)單的調(diào)用了data服務(wù)的getData函數(shù),當(dāng)數(shù)據(jù)返回的時(shí)候摊溶,我們將他JSON為一個(gè)對(duì)象爬骤,讀取數(shù)據(jù)到Reddit提供者的成員變量。然后我們調(diào)用了changeSubreddit函數(shù)來(lái)觸發(fā)使用新數(shù)據(jù)加載新帖子莫换。
現(xiàn)在我們有了數(shù)據(jù)服務(wù)的實(shí)現(xiàn)霞玄,我們可以拿掉拿掉之前數(shù)據(jù)解除之前的注釋。
> 修改 home.ts的 openSettings 函數(shù)為如下:
openSettings(): void {
let settingsModal = this.modalCtrl.create(SettingsPage, {
perPage: this.redditService.perPage,
sort: this.redditService.sort,
subreddit: this.redditService.subreddit
});
settingsModal.onDidDismiss(settings => {
if(settings){
this.redditService.perPage = settings.perPage;
this.redditService.sort = settings.sort;
this.redditService.subreddit = settings.subreddit;
this.dataService.save(settings);
this.changeSubreddit();
}
});
settingsModal.present();
}
總結(jié)
現(xiàn)在我們完成了設(shè)置頁(yè)和數(shù)據(jù)服務(wù)拉岁,應(yīng)用的功能就全部完成了坷剧!雖然現(xiàn)在看起來(lái)還是那么難看。
所以我們還有一節(jié)課的時(shí)間來(lái)添加一些自定義的樣式讓他好看些喊暖。