R&Dトレンドレポート

第24回マッシュアップ開発のススメその10:モバイル版アプリケーションを作ろう④]

今回は、リストから動画を選択した後の動画の詳細ページと、グラフ表示機能の実装を見てみましょう。

どんな画面?

動画のリストから動画の詳細ページに遷移しますが、以下のようなレイアウトで作成してみたいと思います。

図1 動画選択後のページのイメージ
図1 動画選択後のページのイメージ

画面レイアウトの構築

基本的にビューを定義し、そのビューに部品をアドしていくのがTitaniumの画面作成の方法です。それでは上記画面をどのように構築するかをご紹介します。

レイアウトは大きく3つの要素(ヘッダ部分、ボディ部分、グラフ部分)に分かれますが、ヘッダ部分は大きさは固定です。が、ボディ部分は不定の長さで番組によってはないものもあります。ボディ部分が長い場合はiphoneの画面長を超えて表示されるため、全体をスクロールさせる必要があります。ということで、ここでは全体をスクロールビューの上にアドしていくことにします。

リスト1 スクロールビューの作成
my scrv = Ti.UI.createScrollView({
  contentWidth:'auto',
  contentHeight:'auto',
  top:0,
  showVerticalScrollIndicator:true,
  showHorizontalScrollIndicator:false,
});

スクロールビューは縦横のビューサイズが画面を超えたときにスクロールが可能な状態にしてくれますが、今回は縦スクロールのイメージですので、showHorizontalScrollIndicatorはfalseに設定しておきます。

さて、ヘッダ部分、ボディ部分、グラフ部分もそれぞれをビューとして定義しておきましょう。ある程度の要素の集合として扱える要素についてはその固まりについてビューとして定義しておくのが便利です。

リスト2 ヘッダビューの作成
my v1 = Ti.UI.createView({
  backgroundcolor:"#e0ffff",
  top: 5,
  width:316,
  height:60,
  borderradius:5,
  bordercolor: "#d3d3d3",
})

ヘッダに表示する要素は、番組画面のアイコン、タイトル、日時などなど……。が想定されますが、ここではアイコン、タイトル、日時を表示してみます。

リスト3 アイコン(+再生ボタン画像⁠⁠、タイトル、日付の作成
var iconImage =  Titanium.UI.createImageView({
  image:myData.iconurl,
  width:96,
  height:50,
  left:0,
  top:5
});

var saiseiImage = Ti.UI.createImageView({
  image: "avsdvdicon.png",
  width: 26,
  height: 26,
  top: 20,
  left: 35,
});

var titleLabel = Titanium.UI.createLabel({
  text:myData.title,
  font: {
      fontSize: (myData.title.length > 48)? 10: 12,
      fontWeight:'bold'
    },
  color: "#000080",
  width:'auto',
  textAlign:'left',
  top:1,
  left:98,
  height:34
});

var ymd = myData.note.startdate.split(" ")[0];
var dateLabel =  Titanium.UI.createLabel({
  text: ymd,
  font:
    {
      fontSize:10,
    },
  width:'auto',
  textAlign:'right',
  bottom:5,
  right:8,
  height:16
});

v1.add(iconImage);
v1.add(saiseiImage);
v1.add(titleLabel);
v1.add(dateLabel);

以上のようにそれぞれの部品を構築し、アドしたいビューに対する座標値を設定します。topやleft, rightはv1上の座標値となります。

※:ここでは固定値をプログラム内に書き込んでいますが、たとえばアイコンの画像サイズを変更したらすべての部品サイズが動的に変更されるように書いておくべきでしょう。

同様にボディ部分のビューの構築です。

リスト4 ボディビューの作成
var v2 = Ti.UI.createView({
  top: 70,
  width:300,
  height:"auto",
  borderRadius:5,
});

if ( myData.note.desc != null && myData.note.desc.length > 0 )
{
  var desc = Ti.UI.createLabel({
    text:myData.note.desc,
    top:3,
    height:"auto",
    color:"#576c89",
    font:{fontSize:12},
    shadowColor:"#999",
    shadowOffset:{x:0,y:1}
  });

  v2.add(desc);
}

ここでのdesc(説明)は存在しないことがあるため、上記のように無い場合はビューにテキストラベルを追加していません。ヘッダ部分では存在することが明らかな部品に対しての構築であったためこのような処理は不要でしたが、ないかもしれない部品を扱うには必要な処理となります。

それでは最後にグラフビューの構築ですが、Titaniumにはグラフ描画用のライブラリは用意されていませんでした。グラフィックライブラリを駆使すればできなくもないですが、ここではもっと簡単な方法で実現したいと思います。

グラフ機能の実装

iPhoneではwebviewというウェブコンポーネント(ウェブキット)を使用することで、HTMLを用いた表現が可能となっています。要するにブラウザと同等の機能を有するわけです。

ということはPC版クライアントの時に使用したhighchartsがそのまま利用できるということです。これは便利ですね。

グラフ描画処理の流れとしては以下のようになります。

図2 グラフ描画のシーケンス
図2 グラフ描画のシーケンス

また、グラフをタッチしたときにTitanium側にフィードバックする機能は以下のようになります。

図3 グラフタッチのシーケンス
図3 グラフタッチのシーケンス

グラフ描画

それではグラフの実装について見てみましょう。まずはウェブビューの定義です。これはTitanium側で行います。

リスト5 ウェブビューの実装
var w = Ti.UI.createWebView({
  top: v2.top + v2.height,
  width:316,
  height: “auto”,
  url: "html/chart.html"
});

ここではウェブビューの部品を作っていますが、実体はhtml/chart.htmlにあります。ウェブビューではリモートのウェブページ以外にもローカルのhtmlファイルも表示することが可能です。

ウェブビューはブラウザそのものですので、Titaniumでは使用できなかったjqueryも使用できます。ディレクトリはResources/htmlを作成し、その直下にjqueryとhighchartsのjsファイルをコピーします。また、chart.htmlも同じところにおきます。

それではウェブビューの中身を見ていきましょう。

リスト6 ウェブビューのHTML部分
<html >
<head >
<script type = "text/javascript"src = "jquery-1.3.2.min.js" > </script>
<script type = "text/javascript"src = "highcharts.src.js" > </script>
    <script type="text/javascript ">

function graphinit( data, asec ){
  var options = {
    credits: {
        enabled: false,
    },
   ~省略~
    plotOptions: 
    {
      series: 
      {
        point: 
        {
          events: 
          {
            click: function(e) {
              t = this.x * asec;
              Ti.App.fireEvent("click_chart",{x:t, y:this.y, pxx:e.x});
            },
          }
        },
        marker:
        {
          enabled: false,
        }
      },
    }
}
    </script>
  </head>

  <body>
    <!--Div that will hold the chart-->
    <div id="myChart" style="width:305; height:140;"></div>
  </body>
</html>

このように普通のhtmlを記述できます。青字のメソッド定義がTitaniumから呼び出されるメソッドとなります。

次に、Titaniumでサーバからグラフデータのダウンロードを行い、ウェブビューのメソッドを呼び出す部分です。

リスト7 メソッド呼び出し
var baseURL = "http://example.com/xxx/";

var url = baseURL + "thumb.cgi?id=" + myData.id;
var linevalue;

var xhr = Titanium.Network.createHTTPClient();
xhr.open("GET", url);
xhr.send();
xhr.onreadystatechange = function(){
  if ( xhr.readyState == 4 && xhr.status == 200 )
  {
    json = JSON.parse(xhr.responseText);
    linevalue = JSON.stringify(json.data.graph);
    asec = json.data.asec;
    Ti.API.info(linevalue);
    Ti.API.info(w);
    w.evalJS('graphinit('+  linevalue + ', ' + asec + ')');
  }
};

上記ソースの青字の部分がウェブビュー側の関数を呼び出している部分です。evalJSというメソッドを使用することで、ウェブビュー側で定義しているgraphinit()というメソッドが呼び出されます。

これでTitanium側からデータを渡し、グラフを描画させることができました。

グラフからのフィードバック

再度、⁠ウェブビューのHTML部分⁠のソース(リスト6)を参照ください。ここでのポイントは赤字の部分、ネイティブアプリ側の関数を呼び出している部分です。fireEvent関数を使用することで、ウェブビュー内から今度は逆にTitanium側の関数を呼び出すことが可能となっています。

以下は呼び出されるメソッドの定義です。

Ti.App.addEventListener("click_chart", function(e){

~アイコン作ったりとか処理~

});

ここで注意しておきたいのが、fireEventで呼び出すメソッドは一意に識別できる名称にしておかないといろんなところで呼ばれる可能性があります(試してみたところ、現在アクティブなウインドウの定義とapp.jsでの定義は同列に扱われるようです⁠⁠。

このように実装することで、ネイティブ部分とウェブビュー部分で互いにデータのやりとりやイベントのハンドリングが可能となります。非常に便利ですが、ひとつ難点を言うとすると、動作が緩慢になる可能性があります。描画やタッチからの動作が比較的遅い感じがしました。ただ、表現力が高いためそこら辺のトレードオフは十分にあると思います。用途に合わせて使い分けたいですね。

こんな感じになりました。

図4
図4

次回は動画再生部分になります。よろしくお願いします。

おすすめ記事

記事・ニュース一覧