[iOS・Android]Alloyでタイトルバーをテンプレート化して作業量を減らす


タイトルバーのコードを各画面のコードに記述した場合,
画面数が3画面とかならいいのですが,5画面や10画面など画面数が増えた場合に,
タイトルバーの仕様を変更した時にすべての画面のコードを変更するのがとても辛いです.
そして絶対に直し忘れがあったりしてモチベーションだだ下がりです.

そうならないように,タイトルバーを各画面のコードから分離して気持よくなりましょう.

タイトルバーのビューを以下のように作成します.予めバックボタンの画像をassetsフォルダ以下に置いてます.

app/views/titlebar.xml
<Alloy>
  <View id="titlebar">
    <ImageView id="backBtn" image="/backbtn_arrow.png" onClick="doWinBack" />
    <Label id="title" text="notTitle" />
  </View>
</Alloy>

次にタイトルバーのスタイルを定義します.iOSの場合ナビゲーションバーに被らないようにtopの位置を指定してます.

app/styles/titlebar.tss
"#backBtn":{
  height:"50dp",
  width:"50dp",
  left:0
}

"#titlebar": {
  top:"0dp",
  height: "50dp",
  width: Ti.UI.FILL,
  backgroundColor: "red"
}

"#titlebar[platform=ios]": {
  top: "20dp",
}

最後にタイトル名を親から受け取った場合,タイトル名を付与する処理と,バックボタンの関数を作成します.

app/controllers/titlebar.js
var titleName = arguments[0].title || {};

if (titleName) {
  $.title.setText(titleName); //タイトル名を追加
}

function doWinBack(e) {
  e.source.getParent().getParent().close(); //親ウィンドウを閉じる
}

今回はどうしてもtitlebar.jsに書きたかったので,親ウィンドウを取得するのにgetParentを使っていますが,公式ドキュメントが無いので動作が不安です.
それに,viewの階層が変わった場合正しく動作しない可能性もあります.
その場合,alloy.jsにカレントウィンドウを保持させて,alloy.js側にバックボタンの処理を書くのも手だと思います.

これで,タイトルバーをテンプレ化できたので,タイトルバーを使う画面のviewでこのタイトルバーを呼び出して使えます.Requireタグにtitleプロパティを付与し,タイトル名を渡しています.

app/views/index.xml
<Alloy>
  <Window class="container">
    <Require src="titlebar" title="win1" type="view" />
    <Label id="label" onClick="doClick">Window1</Label>
  </Window>
</Alloy>

本音を言えば,ちゃんとiOS,Androidでちゃんとしたタイトルバー使うべきなんだろうけど・・・