039-insertRowAfter使った処理がうまくいかずにはまってます
CreateTableViewのreceive()は、エントリ一覧のオブジェクトに加えて、iPhone上で何ページ目が表示されているのかそのページ数を受取、2ページ目以降ならば、TableViewのinsertRowAfterメソッドを使って、rowを動的に追加しようと考えました。
結構簡単にできると思ってやってみたものの、全然できない。。。
現時点で、rowを静的に組み立てて、insertRowAfterに適用しようと思って、こんな感じのコードをCreateTableViewのreceive()内に書きました
// テストのためにrowを準備して var row = Ti.UI.createTableViewRow({ hasChild:true, data:entryList, height:80 }); var title = Ti.UI.createLabel(styles["titleLabel"]); title.text = entryList[0].title, row.add(title); var content = Ti.UI.createLabel(styles["contentLabel"]); content.text = entryList[0].html_body.replace(/<\/?[^>]+>/gi, ""); row.add(content); this.tableView.insertRowAfter(4,row,{});
これで実行すると
[ERROR] invalid number of rows. in -[TiUITableViewProxy insertRowAfter:] (TiUITableViewProxy.m:368)
という感じで怒られます。
もうちょっとでうまくいきそうな予感がしているのですが、その”ちょっと”というのが届きそうで届かないので、めげそうになります
前回のエントリからViewとなるCreateTableViewクラスとModelとなるBloggerクラスを分けはじめまて、今のところ上記のinsertRowAfterの部分がうまくいってないですが、とりあえずソースコード晒します。
//CreateTableView CreateTableView = function(){ this.entry_list_length = 5; this.list = []; this.pagenumber = 1; this.win = Ti.UI.currentWindow; this.tableView = Ti.UI.createTableView(); this.pulling = false; this.reloading = false; this.init(); }; CreateTableView.prototype = { init:function(){ /* TableViewのヘッダー部分や、その中のEventListenerは 初回だけ生成すればOK。 */ this.makeTableHeader(); }, run:function(entryList){ var data = []; for(var i=0;i<this.entry_list_length;i++){ var entry = entryList[i]; data.push(this.makeView(entry)); } return data; }, receive:function(entryList,current_page){ /* * 最初に読み込まれるページでなければ * beginReloadingに結果のエントリ一覧を渡すことで * 2ページ目以降のエントリ一覧を生成する * */ Titanium.API.info('CURRENT PAGE' + current_page); var entries = this.run(entryList); if(current_page===1){ this.pagenumber = current_page; this.setData(entries); } else { this.pagenumber = current_page; var row = Ti.UI.createTableViewRow({ hasChild:true, data:entryList, height:80 }); var title = Ti.UI.createLabel(styles["titleLabel"]); title.text = entryList[0].title, row.add(title); var content = Ti.UI.createLabel(styles["contentLabel"]); content.text = entryList[0].html_body.replace(/<\/?[^>]+>/gi, ""); row.add(content); Titanium.API.info(title + ":" + content); Titanium.API.info(entryList[1].title); this.tableView.insertRowAfter(4,row,{}); } }, getRow:function(){ return this.row; }, makeView:function(entry){ var self = this; var row = Ti.UI.createTableViewRow({ hasChild:true, data:entry, height:80 }); // 記事の詳細情報を表示 row.addEventListener('click', function(e){ var title = e.rowData.data.title; var html_body = e.rowData.data.html_body; var permalink = e.rowData.data.permalink; var webView = Ti.UI.createWebView(); webView.html = '<html><body>' + html_body + '</body></html>'; self.win.add(webView); Titanium.UI.currentTab.open(self.win,{animated:true}); }); var title = Ti.UI.createLabel(styles["titleLabel"]); title.text = entry.title, row.add(title); var content = Ti.UI.createLabel(styles["contentLabel"]); content.text = entry.html_body.replace(/<\/?[^>]+>/gi, ""); row.add(content); return row; }, makeTableHeader:function(){ var self = this; var border = Ti.UI.createView(styles["border"]); var tableHeader = Ti.UI.createView(styles["tableHeader"]); var arrow = Ti.UI.createView(styles["arrow"]); var statusLabel = Ti.UI.createLabel(styles["statusLabel"]); var lastUpdatedLabel = Ti.UI.createLabel(styles["lastUpdatedLabel"]); tableHeader.add(border); tableHeader.add(arrow); tableHeader.add(statusLabel); tableHeader.add(lastUpdatedLabel); self.tableView.addEventListener('scroll',function(e){ var offset = e.contentOffset.y; if (offset <= -65.0 && !self.pulling) { var t = Titanium.UI.create2DMatrix(); t = t.rotate(-180); self.pulling = true; arrow.animate({transform:t,duration:180}); statusLabel.text = "手を離すと更新"; } else if (self.pulling && offset > -65.0 && offset < 0) { self.pulling = false; var t = Titanium.UI.create2DMatrix(); arrow.animate({transform:t,duration:180}); statusLabel.text = "Pull down to refresh..."; } }); self.tableView.addEventListener('scrollEnd',function(e){ if (self.pulling && !self.reloading && e.contentOffset.y <= -65.0) { self.reloading = true; self.pulling = false; arrow.hide(); statusLabel.text = "更新しています..."; self.tableView.setContentInsets({top:60},{animated:true}); arrow.transform = Titanium.UI.create2DMatrix(); self.beginReloading(); } }); self.tableView.headerPullView = tableHeader; return; }, setData:function(data){ this.tableView.setData(data); return this.win.add(this.tableView); }, nextPage:function(){ this.pagenumber++; return this.pagenumber; }, beginReloading:function(){ /* エントリ情報更新する際に、コントローラーに現在のページ数を 引き渡すことで、コントローラー側で次に何ページを取得すればいいのか 判定できる */ var self = this; var next_page = self.nextPage(); Titanium.API.info('NEXT PAGE IS ' + next_page); setTimeout(function(){ self.tableView.scrollToTop(); self.reloading = false; },2000); var blogger = new Blogger('hibi'); blogger.getEntry(next_page); return; } };
//Blogger var Blogger = function(blogger){ this.blogger = blogger; this.xhr = Titanium.Network.createHTTPClient(); this.list = []; this.entry_list_length = 5; this.objTable = new CreateTableView(); }; Blogger.prototype = { getEntry:function(current_page){ var _url =''; var self = this; _url = "http://localhost:4567/api/" + this.blogger + "/" + current_page; self.xhr.open('GET',_url); self.xhr.onload = function(){ var entries = JSON.parse(this.responseText); //ここでレイアウト情報を生成するようなメソッドを呼び出せばOK? self.makeEntryList(entries,current_page); }; self.xhr.send(); }, makeEntryList:function(obj,current_page){ /*エントリ一覧情報となるオブジェクトを生成して CreataTableViewのreceiveメソッドを呼び出して そちらのクラスでTableViewの生成をする */ for(var i=0;i<this.entry_list_length + 1;i++){ var entry = obj[i]; this.list.push(obj[i]); } return this.objTable.receive(this.list,current_page); }, close:function(){ this.xhr.onload = null; this.xhr = null; }, update:function(){ var next_url = "http://localhost:4567/api/" + this.blogger + "/" + this.objTable.nextPage(); Titanium.API.info(next_url); return this.get(next_url); } };