さきほどはスクロールしたら追加の情報を読み込む実現方法についていくつかご紹介をしたので、この章では実装方法について解説します。
TableViewSectionで投稿情報別に区切る方法を実装していきます。実装自体はシンプルそうに見えるのですが、いくつかポイントになる箇所があるのでまずはその点について解説します。
QiitaのWebAPIにリクエストを投げる時に、何ページ目の情報を何件取得するのかオプションで指定することが出来るページネーションの機能が備わってます。
特にオプションの指定をせずに
https://qiita.com/api/v1/items
にアクセスすると、1ページ目の情報を20件取得する仕様になってます。(詳しくはQiitaのWeb APIのドキュメントを参照してください)
例えば、2ページ目の情報を取得したい場合にはURLの末尾に?page=ページ名を付け加えます。具体的には以下のようにします。
https://qiita.com/api/v1/items?page=2
また、リクエスト辺りの取得件数を5件に制限したい場合には?per_page=件数とすることで処理ができます。具体的には以下のようにします。
https://qiita.com/api/v1/items?per_page=5
上記2つを組み合わせて利用することも出来ます。パラメータを組み合わせる場合には、& で連結させます。以下は、2ページ目の情報を5件取得するという意味になります
https://qiita.com/api/v1/items?page=2&per_page=5
1つのタイムラインのようなユーザインタフェースに見せるため、TableViewSection作成時にheaderViewやheaderTitleの設定は行わないようにします
画面下部までスクロールした状態を検知するのにscrollEnd イベントを利用します。その際に
という処理を行うのですが、上記処理途中にスクロール出来る状態のままにしておくとscrollEndイベントが頻発してしまう可能性があります。
それを防ぐためにTalbeViewのスクロールを一時的に利用不可にしつつ、処理途中であることを明示したほうが使い勝手の良いアプリケーションにつながると思います。
これまで作ってきたアプリケーションをベースに開発をしていきます。
app.jsはそのまま流用します。念のためソースコードを以下記載しておきます
var mainWindow,win;
mainWindow = require("mainWindow");
win = mainWindow.createWindow();
win.open();
引っ張って更新処理を実装するで利用したソースコードをそのまま流用します。念のためソースコードを以下記載しておきます
exports.mainTable = {
"width": Ti.UI.FULL,
"height": Ti.UI.FULL,
"backgroundColor": "#fff",
"separatorColor": "#ccc",
"left": 0,
"top": 0
};
exports.row = {
"width": Ti.UI.FULL,
"height":60,
"borderWidth": 0,
"className":"entry"
};
exports.iconImage = {
top:5,
left:5,
width:40,
height:40
};
exports.textLabel = {
"width":250,
"height":50,
"top":5,
"left":60,
"color":"#222",
"font":{
"fontSize":16,
"fontWeight":"bold"
}
};
// 引っ張って更新処理中の色を指定
exports.refreshControl = {
tintColor:'red'
};
// QiitaのWebAPIから情報を読み込んでいる状態を示すために ActivityIndicatorを配置しためので
// その設定値
exports.actInd = {
top:"20%",
left:"30%",
height:Ti.UI.SIZE,
width:Ti.UI.SIZE,
zIndex:0,
color: "#f9f9f9",
backgroundColor:"#444",
font: {
fontFamily:'Helvetica Neue',
fontSize:16,
fontWeight:'bold'
},
message: 'Loading...',
style:Ti.UI.iPhone.ActivityIndicatorStyle.DARK
};
QiitaのWebAPIにアクセスする際に何ページ目を取得するのか指定する必要があります。関数の引数にページ番号を設定し、かつ、QiitaのWebAPIへのアクセス時にページ番号のオプションを指定します
exports.getItems = function(callback){
var xhr,qiitaURL,method;
qiitaURL = "https://qiita.com/api/v1/items";
exports.getItems = function(page,callback){
var xhr,qiitaURL,method;
qiitaURL = "https://qiita.com/api/v1/items?page=" + page;
最終的には以下のようになります
exports.getLocalJSON = function(){
var sample,file,body;
sample = Ti.Filesystem.getFile(Ti.Filesystem.resourcesDirectory, "sample.json");
file = sample.read().toString();
body = JSON.parse(file);
return body;
};
// 今回拡張する機能
exports.getItems = function(page,callback){
var xhr,qiitaURL,method;
qiitaURL = "https://qiita.com/api/v1/items?page=" + page;
Ti.API.info("qiitaURL is" + qiitaURL);
method = "GET";
xhr = Ti.Network.createHTTPClient();
xhr.open(method,qiitaURL);
xhr.onload = function(){
var body;
if (this.status === 200) {
body = JSON.parse(this.responseText);
Ti.API.info("number is :" + body.length);
callback('ok',body);
} else {
Ti.API.info("error:status code is " + this.status);
}
};
xhr.onerror = function(e) {
var error;
error = JSON.parse(this.responseText);
Ti.API.info(error.error);
};
xhr.timeout = 5000;
xhr.send();
};
ユーザインタフェース側の処理が多くなるため、上記3つと比較すると少し長くなりますが、先にソースコード全体を以下に記載します。
var style = require("style"),
mainTable = Ti.UI.createTableView(style.mainTable),
actInd = Ti.UI.createActivityIndicator(style.actInd),
qiita = require("qiita"),
pageNumber = 1, // (1)
pageSection = 0; // (2)
exports.createWindow = function(){
var win = Ti.UI.createWindow({
title:"QiitaViewer"
});
getQiitaItems(pageNumber,function(items){ // (3)
var section = Ti.UI.createTableViewSection();
Ti.API.info("起動時にWebAPIからデータを取得しました");
mainTable.setData([createSection(items,section)]); // (4)
pageNumber++;
});
win.add(mainTable);
win.add(actInd);
return win;
};
mainTable.addEventListener('scrollEnd',function(e){
// (5)
mainTable.scrollable = false;
mainTable.opacity = 0.3;
getQiitaItems(pageNumber,function(items){ // (6)
var section = Ti.UI.createTableViewSection(),
insertSection = createSection(items,section); // (7)
mainTable.insertSectionAfter(pageSection,insertSection); // (8)
// (9)
mainTable.scrollable = true;
mainTable.opacity = 1.0;
pageNumber++;
pageSection++;
});
});
// (10)
function getQiitaItems(page,callback){
if (Ti.Network.online === false){
alert("利用されてるスマートフォンからインターネットに接続できないため情報が取得できません");
} else {
actInd.show();
qiita.getItems(page,function(status,items){
actInd.hide();
return callback(items);
});
}
};
// (11)
function createSection(items,section){
var _i,_len,style = require("style");
for (_i = 0, _len = items.length; _i < _len; _i++) {
row = Ti.UI.createTableViewRow(style.row);
textLabel = Ti.UI.createLabel(style.textLabel);
iconImage = Ti.UI.createImageView(style.iconImage);
iconImage.image = items[_i].user.profile_image_url;
textLabel.text = items[_i].title;
row.add(textLabel);
row.add(iconImage);
section.add(row);
}
return section;
};
スクロール中の状態を画面キャプチャー取れないので見た目にはわかりづらいのですが以下のようになります。