読者です 読者をやめる 読者になる 読者になる

TitaniumMobile勉強記

Web系エンジニア向けのキャリアアドバイザーやってましたが現在はフリーランスで開発含めて色々やってます。技術ネタとしてはRuby/RailsとJavaScript関連(Node.js、Titanium)あたり

Alloyで簡易のスライドメニューを実現する方法

前回書いたエントリ意外と注目を集めたので、続編というわけではないのですが、Alloyで簡易のスライドメニューを実現する方法についてまとめておこうと思います。


これから作るアプリのイメージ

起動時の画面には、Hello Worldの文字が表示されており、ナビバー上の左上、右上それぞれにボタンが配置されてます。

f:id:h5y1m141:20140409074128p:plain

左上のナビボタンをタッチすると、ウィンドウが右側にスライドするというよくあるユーザインタフェースのアプリをイメージしてます

f:id:h5y1m141:20140409074153p:plain

ソースコード

上記実現するソースコードを以下しめします

index.jade

Alloy
  TabGroup
    Tab#tabOne
      Window#mainWindow.container(title="main")
        RightNavButton#add(platform="ios")
          Button(title="Add")
        LeftNavButton#showBtn(platform="ios")
          Button(title="=" , onClick="slide")

        Label#label Hello, World!!!!!!!

index.coffee

$.index.open()
slide = (e) ->
  if $.mainWindow.slideState is false
    leftPosition = 100
    $.mainWindow.slideState = true
  else
    leftPosition = 0
    $.mainWindow.slideState = false
  
  transform = Titanium.UI.create2DMatrix()
  animation = Titanium.UI.createAnimation()
  animation.left = leftPosition
  animation.transform = transform
  animation.duration = 500
  
  $.mainWindow.animate(animation)

index.tss

".container": {
    backgroundColor:"#f9f9f9"
},

"#mainWindow":{
    statusBarStyle:0,
    tabBarHidden:true,
    slideState:false
}
"#label":{
    color:"#222",
    width:80,
    height:40,
    top:5,
    left:10,
    font:{
        fontSize: 16
    }
}

ソースコードの解説

キモは2点かと思います

  • Ti.UI.Windowにスライド状態かどうかを判定する独自のプロパティを設定するために、index.tss にslideStateを設定。デフォルト値をfalseで、スライドしてない状態を意図しています
  • Controllerのindex.coffeeのslide()は上記のslideStateの値をチェックしてfalseの場合には一定の箇所までスライドするアニメーションを実施します

地味にハマったこと

  • Alloy → TabGroup → Tab → Window → RightNavButton(もしくはLeftNavButton)という階層構造になってないといけないのが最初よくわからず地味にハマりました。

  • NabButtonのデフォルトの青色から変更したい場合のやり方。index.tssで設定したいTi.UI.WindowにnavTintColorというプロパティがあるのでそこで任意の色を指定すればOK

"#mainWindow":{
    navTintColor:'#99cc66',
    statusBarStyle:0,
    tabBarHidden:true,
    slideState:false
}

参考までににAlloyのTabGroupでの画面遷移方法

こういう↓感じでナビバーを配置しつつメイン画面から詳細画面へ画面遷移出来るユーザインタフェースのあるスマフォアプリを作るケースは、Titaniumに限らずよくあるかと思います。

f:id:h5y1m141:20140409084541p:plain

折角なので、TabにWindowを配置してあるようなアプリでのメイン画面→詳細画面への遷移の方法についてもまとめておきます

実装する上でのポイント

実装する上でのポイントはいくつかあると思うのですが、言葉にすると長くなるのでViewsとControllerとの対応関係を絵にしつつ説明します

f:id:h5y1m141:20140409084550p:plain

  1. 遷移先のControllerにて実装してるmoveNewWindow()を実行します。moveNewWindowでは、引数にTi.UI.Tabオブジェクトが渡されており、_tab.open(該当のWindow)にて遷移先のウィンドウが開きます。
  2. 画面遷移先の処理を渡すためにAlloy.createController()を実行してます。引数には遷移先のControllerのファイル名の拡張子をとったものを指定します
  3. Viewにあたるindex.jadeのTabに任意のID名を付与します。こうすることでController側のindex.coffeeから該当タブをこのようにして取得して、メソッドの引数に設定できます。

最終的なソースコード

index.jade

Alloy
  TabGroup
    Tab#tabOne
      Window#mainWindow.container(title="main")
        RightNavButton#add(platform="ios")
          Button(title="Add")
        LeftNavButton#showBtn(platform="ios")
          Button(title="=" , onClick="slide")

        Label#label Hello, World!!!!!!!

index.coffee

$.index.open()
slide = (e) ->
  if $.mainWindow.slideState is false
    leftPosition = 100
    $.mainWindow.slideState = true
  else
    leftPosition = 0
    $.mainWindow.slideState = false
  
  transform = Titanium.UI.create2DMatrix()
  animation = Titanium.UI.createAnimation()
  animation.left = leftPosition
  animation.transform = transform
  animation.duration = 500
  
  $.mainWindow.animate(animation)
$.label.addEventListener 'click', (e) ->
  newWindowController = Alloy.createController('newWindow')
  return newWindowController.moveNewWindow($.tabOne)

index.tss

".container": {
    backgroundColor:"#f9f9f9"
},

"#mainWindow":{
    statusBarStyle:0,
    tabBarHidden:true,
    slideState:false
}
"#label":{
    color:"#222",
    width:80,
    height:40,
    top:5,
    left:10,
    font:{
        fontSize: 16
    }
}

newWindow.jade

Alloy
  Window#newWindow.container(title="詳細画面")
    Label#label This is a new window

newWindow.coffee

exports.moveNewWindow = (_tab) ->
  Ti.API.info _tab
  Ti.API.info $.newWindow
  return _tab.open($.newWindow)

newWindow.tss

".container": {
    backgroundColor:"#f9f9f9"
},

"#newWindow":{
    statusBarStyle:0,
    tabBarHidden:true,
    slideState:false
}
"#title":{
    color:"#222",
    width:Ti.UI.FULL,
    height:40,
    top:"30%",
    left:"50%",
    font:{
        fontSize: 16
    }
}

最後に

今回作ったようなスライドメニューのAlloyWidgetはgitTioでも見つかるのですが、Widgetの実装見てるとそんなに大したことやってないように見えたので勉強がてら自分で作ってみました。

ブログに書くことで大分Alloyのことが理解できるようになってきた気がしてきたのでAlloyのメリットを活かすために

  • Widgetの作成方法
  • CommonJSな独自ライブラリの利用方法(app/lib/something.jsという感じにすれば利用できるのがわかってる)
  • 今のところ手付かずのModelの作成

あたりをこれから勉強していこうと思ってます