NativeScriptで大変に困るのが、ListViewのテンプレートを1つしか指定できない事です。
タイトルではテンプレートを動的に変更する、と書いたが、正確にはindex毎に異なるViewを表示したいのです。
例えば、1列目に画像、2列目にテキスト、3列目にボタンが入るようなレイアウトがあるとします。
海外のフォーラムを見ていると、皆さん同じ事でお困りのようなのですが、彗星のごとく現れた回答者が、
<StackLayout>
<Image visibility="{{showImage?'visible':'collapsed'}}"/>
<Label visibility="{{showLabel?'visible':'collapsed'}}"/>
<Button visibility="{{showButton?'visible':'collapsed'}}"/>
</StackLayout>
みたいに、全てのUIパーツをテンプレートに入れちゃって、indexによって表示/非表示させればいいじゃんとおっしゃり、賞賛の嵐を受けていたのです。
ケースバイケースだとは思いますが、いやいや、これはメモリの無駄だし、パフォーマンスも低下するだろう、と。
じゃあどうすれば良いかというと解決方法はいたって簡単で、テンプレートを使わなくても、ListViewのitemLoadingコールバック内で、引数(ItemEventData型)のviewプロパティに適当なViewを突っ込んでやれば良い。
listView.on(listViewModule.ListView.itemLoadingEvent, function (args: listViewModule.ItemEventData) {
var index = args.index;
var view;
// indexによってviewに好きなViewを入れる
switch(index){
case 0:
view = new Image();
・・・
break;
case 1:
<・・・中略・・・>
default:
view = null;
break;
}
args.view = view
});
これだけです。
JavaScriptは連想配列を含めオブジェクトは全て参照渡しなので、NativeScriptはこのコールバックを呼んだのち、args.viewを見てくれて、もしセットされていればそれを使ってくれるというナイスな実装になってたんですね。
でも、ええーここだけコードで書くの? せっかくNativeScriptはxmlでUIを記述できて便利なのに・・・と思った方もおられると思います。
確実にここに1人います。
これについては別記事で。