前回作成したテーブルビューは起動時にデータを取得し、
動的な更新
こういう動きを実装したい。でもまだコツがつかめない…。こんな時はキッチンシンクです。
キッチンシンクはiPhoneアプリやAndroidアプリの基本的な動作をTitaniumで実装したサンプル集です。実際に動作させた上でソースも確認できるのが非常にありがたいですね。
では今回の動作を実現するにはどのサンプルが必要でしょうか。example/
このサンプルの動作は、
- テーブルビューをスクロールさせる
- 画面上のリスト
(ROWデータ) が終わりそうになったら、 - テーブルビューに次のリストを追記する。
という動作です。
この動きによって画面をスクロールさせるだけで、
それでは該当ソースの部分を見てみましょう。
var updating = false;
var loadingRow = Ti.UI.createTableViewRow({title:"Loading..."});
//更新開始関数
function beginUpdate()
{
updating = true; //更新フラグをONにする(多重に動作しないように)
navActInd.show(); //ナビバーのスピナーを表示
tableView.appendRow(loadingRow); // “読み込み中”のローをテーブルビューに追記
// just mock out the reload
setTimeout(endUpdate,2000); // 2秒後にendUpdate()を起動。
}
// 更新終了関数
function endUpdate()
{
updating = false; // 更新フラグをOFF
// “読み込み中”のローを削除する。
tableView.deleteRow(lastRow,
{animationStyle:Titanium.UI.iPhone.RowAnimationStyle.NONE});
// simulate loading
for (var c=lastRow;c<lastRow+10;c++)
{
tableView.appendRow({title:"Row "+(c+1)},
{animationStyle:Titanium.UI.iPhone.RowAnimationStyle.NONE});
}
lastRow += 10;
navActInd.hide(); //スピナーを非表示に。
}
var lastDistance = 0; // 距離の初期値
// テーブルに対するスクロールイベントハンドラを追加。
tableView.addEventListener('scroll',function(e)
{
var offset = e.contentOffset.y; // テーブルの見えてる部分の位置(上)
var height = e.size.height; // テーブルの見えてる部分のサイズ(画面内の)固定
var total = offset + height; // テーブルの見えている部分の位置(下)
var theEnd = e.contentSize.height; // テーブルのサイズ
var distance = theEnd - total; // テーブル全体の底辺からの今見えてる部分の距離(最底辺だと0)
// 距離が前回の距離より短くなっている=テーブルが上に向かってスクロールしている。
if (distance < lastDistance)
{
var nearEnd = theEnd * .75;
// 更新中じゃなく、テーブルのサイズの75%以上までスクロールしたら。
if (!updating && (total >= nearEnd))
{
beginUpdate(); //更新を開始する!
}
}
lastDistance = distance; //現在の距離を保存する。
});
ここの動作のポイントとしては、
- テーブル全体の大きさと今現在見えている部分のサイズを比較
- テーブル下部へ近づいていることを検知
- 全体の75%の部分までスクロールしたらデータの更新を行う
という一連の動作によりスムーズな操作を実現しています。
ここの部分の動きは変更する必要がありません。強いて変更するなら75%で判別している部分がテーブルのサイズが動的に大きくなることを考えると適切ではないと思われます。ここは固定のピクセル値に直してもよいかもしれません。

紫の線で表現したのがテーブルビューの全体です。見えている部分と隠れている部分のサイズがどのように取得できるかがよくわかると思います。distance値がnピクセル以下になったら次のデータを取得する、
もうひとつのポイントはソース内の文字色を変えた部分です。こちらはサンプルですので模擬的に2秒後にendUpdate()が発火するように書いてありますが、
また、
ここではいろんな実装方法があるかと思いますが、
var MovieData = function(tableView)
{
this.rows=10; //1ページ毎の行数
this.page=1; //初期ページ数
this.lastRows = 0;
this.tableView = tableView;
}
MovieData.prototype = {
getNext: function()
{
//動画一覧を取得するAPI
var URL=”http://example.com/jikkyou/list.cgi?page=”+this.page+”&rows=”+ this.rows;
// Titaniumで用意されているHTTPClient関数
var c = Titanium.Network.createHTTPClient();
var json;
var row;
c.open("GET", URL); // GETで取得
c.send();
c.onreadystatechange = function() // HTTPClientのステータスが変わったら。。(コールバック関数)
{
if ( c.readyState == 4 )
{
if ( c.status == 200 )
{
this.tableView.deleteRow(this.lastRows, { animationStyle:Titanium.UI.iPhone.RowAnimationStyle.NONE });;
json = eval("("+c.responseText+")");
for( i = 0; i < json.data.length; i++ )
{
//JSONからデータを取得
var data = json.data;
// tableRowdデータの生成・・
…略…
this.tableView.appendRow(row);
this.lastRows++;
}
this.page++;
f(); //コールバック関数を起動(endUpdate) }
}
}
}
このクラスを外部ファイルに保存します。名前はMovieData.
titaniumで外部ソースを使う場合は次のようにします。
Titanium.include("MovieData.js”);
var md = new MovieData(tableView);
このようにソースの先頭の方でインクルードします。ファイルへのパスはカレントディレクトリからの相対パスで大丈夫です。
最初の文字色の違う部分を以下のように差し替えます。
md.getNext(endUpdate);
2つめの文字色の違う部分を削除します。
ちょっと付け焼き刃的なコーディングになってしまった気がしますが、
スクロールさせるたびに新たにデータが読み込まれるのはなかなか快感です。こういったUIをいち早く取り入れたiPhoneはさすがですね。
それでは次回はテーブルビューからの画面遷移についてご紹介します。