レベル: 中級 Noel Rappin, Vice President of Rails Development, Pathfinder Development
2008年 7月 15日 iPhone と iPod touch は、Mobile Safari を米国で最も人気のあるモバイル・ブラウザーにしました。Mobile Safari は通常の Web ページのレンダリングにも十分対応できますが、それでも数多くの Web 開発者たちは iPhone を対象としたアプリケーションのバージョンを作成しています。連載「Ruby on Rails と Eclipse による iPhone アプリケーション開発」の第 3 回では、ユーザーがリスト構造の最後に達したときに、アプリケーションが実際にコンテンツを表示するために必要な処理について説明します。
連載のこれまでの 2 回の記事では、iPhone や iPod touch にある Mobile Safari ブラウザーのユーザーに専用のコンテンツを提供するように Ruby on Rails アプリケーションを構成する上で重要な 2 つの側面を取り上げました。第 1 回で説明したのは、Mobile Safari を検出して代替コンテンツを提供するようにサーバーをセットアップする方法です。そのために選択したメカニズムには (これが考えられる唯一の手段ではありません)、擬似 MIME タイプを作成し、ユーザー・エージェント文字列を突き合わせ、Rails の respond_to メカニズムを使用するという操作が伴います。
第 2 回では、iPhone や iPod touch 用に作成することができる実際のコンテンツの一例を検討しました。Web アプリケーションを Apple のルック・アンド・フィールのガイドラインに従わせるためのメカニズムとして使用したのは iUI ライブラリーです。その結果、アプリケーションはネイティブ iPhone アプリケーションによく似たものとなっています。この記事ではさらに踏み込んだ内容として、iPhone 固有の Mail アプリケーションに似たドリルダウン・ナビゲーション用のリスト構造を作成しました。このようなリスト構造は、ナビゲートが簡単で、しかもサイズが小さいために速度の遅い EDGE (Enhanced Data Rates for GSM Evolution) ネットワーク接続でも素早くダウンロードできるとして、Apple が推奨しています (訳注: EDGE は、第 2 世代携帯電話の通信方式である GSM (GSM は世界のほとんどで採用されている方式だが日本では採用されていない) をベースにした高速データ伝送方式 (第 2.5 世代、あるいは第 3 世代とも言われる) であるが、最大通信速度は 384 kbps にとどまる)。
この連載最後の今回の記事では、ユーザーがリスト構造の最後に達したときに、アプリケーションが実際にコンテンツを表示するために必要な処理について説明します。iUI にはコンテンツとフォームのレイアウトに役立つ機能が用意されているほかに、ユーザーが電話の持つ向きを回転するのを検出したり、iPhone のホーム画面に表示するアイコンを追加したりといった、アプリケーションを洗練したものにする機能も用意されています。
サンプル・コードを実行するには、いくつかのツールが必要になります。Ruby and Rails はもちろん欠かせません。さらに、Aptana Studio を備えた Eclipse など、Rails と連動するエディターあるいは統合開発環境 (IDE) があると役立ちます。iPhone ビュー画面のシミュレーターも同じく役立つはずです (第 1 回で、オプションをいくつか取り上げて、その利点を説明しています)。この記事ではサンプル・サイトとして Soups OnLine を使用します。このサイトは元々、私の著書『Professional Ruby on Rails』で作成したレシピ交換サイトですが、同サイトの詳細はこの記事では重要ではありません。また、iUI ツールキットが CSS (Cascading Style Sheets) と JavaScript によって iPhone のルック・アンド・フィールを実現します。rails_iui は、iUI の機能を Rails ヘルパーやその他のベスト・プラクティスの Rails イディオムにまとめるために作成されたプラグインです。
パネルを使用してリストの次画面を作成する
第 2 回は、iPhone または iPod-touch ユーザーにナビゲーション・オプションのリストを表示するナビゲーション構造を作成したところで終わりました。一部のオプションは、アルファベット順または最新のエントリー順に整理された第 2 のレシピ・リストを表示します。これらのリストでレシピをクリックすると、ユーザーにはそのレシピについて説明するページが表示されることになります。
iPhone のページに表示する個々の要素を設計する際に重要なのは、iPhone 画面の特異性を考慮することです。このアプリケーションに私が選んだビューポート設定では、ページの幅は、デバイスの現在の向きでの幅に設定されます。この Web アプリケーションはネイティブ iPhone アプリケーションのように見せたいため、ユーザーが使用するズームイン機能も使用不可に設定しました。したがって、設計を縦向きの iPhone の幅 320 ピクセル内に収めることが重要となっています (向きの変更については、この後すぐに説明します)。ページを 320 x 480 ピクセルの画面に収めることができれば理想的ですが、もしこの画面サイズに収まらず、ユーザーがスクロールしなければならない場合でも、一方向のスクロールであれば問題ありません。
iPhone ディスプレイのその他の特徴は、小さい画面サイズによる影響をもたらします。iPhone のピクセル配列は、通常のデスクトップ画面より遥かに密度が高くなっています。したがって、実際の電話でのフォントと画像は、シミュレートした画面で見るよりも小さく見えることになり、読みやすくするためにフォント・サイズを大きくしなければならないことも考えられます。その上、ユーザーの指による画面操作はマウスのクリックほど正確ではありません。Apple では、ユーザビリティーを最大限にするにはクリック可能なターゲットを 44 x 44 ピクセル以上にするよう推奨しています。
図 1 は、以上の要点を念頭に仕上げた最終的なレシピ表示ページです。多少単純にするために、スタイルは iUI が提供するものをそのまま使っています。
図 1. レシピ表示ページ
上記のページの Rails コードは、いくつかの rails_iui ヘルパーを利用して iUI 機能へのアクセスを単純化しています。このファイルは app/views/recipes/show.iphone.erb です。このコードを有効にするために必要なコントローラーの変更はただ 1 つ、該当するコントローラー動作の respond_to ブロックに format.iphone 行を追加することです。以降でこれを説明します。
リスト 1. レシピ表示コード
<% panel do %>
<% if @recipe.has_image? %>
<%= image_tag(@recipe.soup_image.public_filename, :align => :left,
:height => 80, :width => 80,
:style => "padding: 5px" ) %>
<% else %>
<% end %>
<div>Servings: <%= @recipe.servings %></div>
<br/>
<div>Description:</div>
<div><%= @recipe.description %></div><br/>
<div>Ingredients:</div>
<% fieldset do %>
<% for ingredient in @recipe.ingredients %>
<% row_label do %>
<%= h ingredient.display_string %>
<% end %>
<% end %>
<% end %>
<div>Directions:</div>
<% fieldset do %>
<%= row @recipe.directions %>
<% end %>
<div>Tags: <%= h @recipe.tag_list.to_s %></div>
<% end %>
|
この記事を書いている時点で、iUI の CSS 構造にはいくつか特異な点があります。これは主に、他のタグとの関係で特定のクラスがどこになければならないかに関する制約事項に関連します。いずれの場合も、このコードが使用しているいくつかの rails_iui ブロック・ヘルパーは、iUI が定義する特定の CSS クラスで div タグをラップします。
その 1 つは、コード・セグメントの先頭にある panel ハンドラーです。このハンドラーは、panel クラスで div タグをラップします。panel クラスは要素の枠をデバイス・ボックスのサイズに設定し、10 ピクセルのパディングを追加して、背景色とピンストライプの背景をページに設定します。このページは、いくつかあるページの中でも特に iPhone 設定ページを模倣しています。
その他の顕著な特徴としては、この画面が角丸四角 (Rounded-Rectangle) の画面になっていることが挙げられます。Mobile Safari 内部では、-webkit-border-radius というカスタム CSS プロパティーを使ってこの画面を容易に管理することができます。この例では、プロパティーを 10px に設定します。一方、iUI パネル内部では、fieldset タグを使用して角丸四角の境界線を指定します。枠の半径に加え、panel > fieldset セレクターは上部マージン、白い背景、枠、そして 16 ポイントの右揃えテキストも設定します (iPhone 設定ページの各要素に表示されているとおりです)。rails_iui により、fieldset ブロック・ヘルパーは fieldset タグのペアを配置するように定義されています。
ここで、fieldset 内のテキストは右揃えだと言いましたが、図 1 を見ると、テキストは明らかに左揃えになっています。その理由は、テキストの配置を変更する CSS クラスが他にもあるからです。材料 (ingredient) のリストのなかにある row クラスは、角丸四角画面内に表示される複数行の 1 行に適した高さ 42 ピクセルのブロックを設定します。row クラスに含まれる label タグは、テキストを太字に設定して行の終わりに戻します。このネイティブ・バージョンは、設定ページではラベルが左揃えで表示され、設定トグルは右側に配置されます。
rails_iui では行を対象とした 2 つのヘルパーを定義しています。このサンプルでは、説明のために両方とも使用しています。row バージョンが取るのは、1 つの引数 (文字列) とオプションのブロックです。文字列はラベルのテキストとして使用され、ブロックは行のコンテンツになります (すべての Rails ブロック・ヘルパーと同様に、非ブロック・バージョンは ERb テンプレートの出力ペア <%= で区切られる一方、ブロック・バージョンは %lt;% だけを使用します)。row_label ヘルパーはブロックを引数に取り、そのブロックのテキストを label タグに配置します。これ以外に、行のコンテンツはありません。
フォーム
ごく小さなタッチスクリーン上でフォームにデータを入力する際には、さまざまな制約が考えられますが、Mobile Safari にはその制約を克服するために設計された多数の機能が備わっています。なかでも最も代表的な機能 (テキスト入力用のソフトウェア・キーボード、そして選択リスト用の大きなスクロール) は、iPhone Web 開発者であれば当然有効にしますが、これらの機能を利用すると画面スペースが占有されてしまうため、フィールドと Mobile Safari の入力パネルによってページの大部分が隠されてしまうことに注意してください。
テキスト・フィールドに対しては、Mobile Safari ではソフトウェア・キーボードの振る舞いを制御する 2 つのカスタム属性、autocorrect と autocapitalize を定義しています。両属性ともデフォルトでオンに設定されますが、オフに設定して機能を解除することもできます。オートコレクト (autocorrect) は、一般的なスペルミスの修正案を入力フィールドの下に表示するかどうかを制御する機能で、オートキャピタライズ (autocapitalize) は新しいセンテンスの先頭文字を大文字にする機能です。いずれの機能も、Rails では text タグまたは password タグの HTML オプションにこの属性 (:autocorrect => "off" など) を含めて渡すことで制御することができます。ユーザーが、単語やセンテンスではないテキストを入力する可能性が高い場合 (例えばログイン・フィールドやパスワード・フィールド) には、機能をオフに設定してください。
Soups OnLine には、私が組み立てた検索フォームがあります。第 1 回で指定したように、ツールバーの Search ボタンは rails_iui の toolbar へルパー・メソッド <%= iui_toolbar "Soups OnLine", new_search_url %> によって描画されます。
ここでは、第 1 回で記載したヘルパー・メソッドに多少の変更を加えました。それは、ボタン・リンクのターゲットを self に変更したことです。これによって、リスト・ナビゲーションの振る舞いでは、スワイプ動作するのではなく画面全体が再描画されるようにしています。この変更は、検索はリスト・ナビゲーションの一部ではないため、多少異なった振る舞いになるべきだという理論に基づいて行いました。toolbar メソッドは現在、リスト 2 のようになっています。
リスト 2. iui_toolbar ヘルパー・メソッド
def iui_toolbar(initial_caption, search_url = nil)
back_button = button_link_to("", "#", :id => "backButton")
header = content_tag(:h1, initial_caption, :id => "header_text")
search_link = if search_url
then button_link_to("Search", search_url, :id => "searchButton",
:target => "_self")
else ""
end
content = [back_button, header, search_link].join("\n")
content_tag(:div, content, :class => "toolbar")
end
|
私が作成した検索画面は単純で、小さなサイズの画面で開始できるように最小限の機能セットを使っています。
図 2. 検索ディスプレイ
テキスト入力フィールド、選択プルダウン、トグル・スイッチからなるこのフォームは iUI で作成したもので、ネイティブ iPhone のトグル・コントロールを模倣しています。このフォームを機能させるために、まずはコントローラーから取り掛かかることにします。Soups OnLine アプリケーションには、デスクトップ検索フォームを作成する SearchController クラスがすでにあります。このコントローラーの動作を new で定義したコントローラーの動作に変更するのはわけありません。
リスト 3. SearchController の動作
def new
@search = Search.new
@tag_cloud = TagCloud.calculate(Recipe)
@tag_counts = TagCloud.tag_counts(Recipe)
@tags = @tag_cloud.keys.sort
respond_to do |format|
format.html
format.iphone
end
end
|
Search オブジェクトは、Rails モデル・オブジェクトにマッピングするためのフォームを必要とするフォーム・ビルダー・メソッドを、Rails ビューが使用できるようにすることを目的に設計された小さなモデル・オブジェクトです。この言葉通り、これは小さなクラスで、今のところ単なるアクセサーのリストでしかありません。
class Search
attr_accessor :keyword, :tags, :ingredients
end
|
後でこのクラスは、Recipe クラスに詰め込まれ過ぎないようにするために実際の検索ロジックを配置するための絶好の場所となります。
TagCloud の行は、プルダウン・リストに配置可能なタグのリストを作成するために使用されます。このコードでは acts_as_taggable_on_steroids プラグインを使いますが、その詳細はここでは重要でありません。この例で関連するのは、@tags には文字列のリストが含まれるという点です。
最後に、respond_to ブロックが iPhone リクエストを処理します。連載の第 2 回では、リスト作成の動作で :layout => false を指定することが重要でしたが、このコントローラーには該当しないことに注意してください。この違いは、動作の起動方法にあります。前回は、リスト作成の動作をデフォルトの iUI Ajax (Asynchronous JavaScript + XML) 動作によって起動しました。つまり、このデフォルト動作では既存の要素を置き換えているため、レイアウト全体を再描画する必要はありませんでした。一方、Search ボタンは前に説明したように target に _self を指定して起動されます。iUI はこのターゲットを通常の HTML リンクとして解釈し、画面全体を再描画することから、レイアウトを描画する必要があるのです。
レイアウトを描画するビュー画面の大部分は、典型的な Rails フォーマットです (以下を参照)。
リスト 4. 検索フォームのビュー・コード
<%= iui_toolbar "Soups OnLine", new_search_url %>
<div selected="true">
<% form_for @search do |f| %>
<table>
<tr>
<th>Keyword:</th>
<td><%= f.text_field :keyword %></td>
</tr>
<tr>
<th>Tag</th>
<td><%= f.select :tags, @tags,
:include_blank => true %></td>
</tr>
<tr>
<th>Ingredients?</th>
<td>
<%= f.toggle(:ingredients) %>
</td>
</tr>
</table>
<%= f.submit "Search" %>
<% end %>
</div>
|
上記のコードの最初の 4 分の 3 は、固定の標準的な Rails フォームです。このビューはまず、ツールバーを再描画します。これは、ビューがページ全体を処理しなければならないためです。続いて通常の form_for があります。テキスト・フィールドとプルダウン・タグも同じく標準的なものです。toggle の呼び出しは rails_iui ヘルパーになっており、iUI が提供するトグル・クラスを使用しています。このヘルパーによる最終的な HTML は、リスト 5 のようになります。
リスト 5. トグル・コントロールの HTML
<input id="search_ingredients" name="search[ingredients]"
type="hidden" value="OFF" />
<div class="row">
<div class="toggle" id="search_ingredients_toggle"
onclick="$('search_ingredients').value =
($('search_ingredients').value == 'OFF') ? 'ON' : 'OFF';"
toggled="OFF">
<span class="thumb"></span>
<span class="toggleOn">ON</span>
<span class="toggleOff">OFF</span>
</div>
</div>
|
iUI ツールキットにはトグル・コントロールを描画する toggle、thumb、toggleOn、toggleOff それぞれの CSS クラスがある他、コントロール・スイッチをクリック時に変更する JavaScript もあります。ただし iUI は、トグル・スイッチをフォーム・コントロールに結合することはしません。そこで rails_iui が登場しているわけです。まず、このヘルパーは隠しフィールドにトグルの初期値を入力します。この値が、フォームに送信されることになります。rails_iui ヘルパーはさらに、トグル div 用の JavaScript onclick イベント・ハンドラーを追加します。このイベント・ハンドラーは、隠しフィールドの値を現行の値と反対の値に切り替えます。toggle ヘルパーは、rails_iui がロードされていれば、すべての form_for ブロックで使用することができます。
Submit ボタン自体の見栄えを多少良くするため、iUI は whiteButton、blueButton、および grayButton という CSS クラスを提供しています。いずれも、ボタンを多少大きく、iPhone 風にします。
回転
Mobile Safari ブラウザーならではの独特の特徴の 1 つは、ユーザーがブラウザーを 90 度回転させて、横向きにでも、縦向きにでもブラウザーを使用できることです。ブラウザー自体がサイトを異なる幅に合わせて再描画するという優れた処理を行うわけですが、方向の変更に対するサイトの応答をより詳細に制御したい場合もあります。そのような場合には、iUI と rails_iui の組み合わせを使用して、2 通りの方法で向きによる振る舞いを指定することができます。
iUI ツールキットは向きの変更を追跡し、document.body.orient プロパティーの値を profile または landscape に切り替えます。この 2 つの値を使用すれば、リスト 6 の行に示すように、プロパティーの値に基づいて CSS の振る舞いを指定することができます。この行によって、デバイスが landscape モードの場合には h1 タグのマージンと幅が変更されることになります。
リスト 6. 向きに基づく CSS の変更例
body[orient="landscape"] > .toolbar > h1 {
margin-left: -125px;
width: 250px;
}
|
向きの変更による振る舞いをさらに巧妙に制御できるように、rails_iui プラグインでは、向きの変更が検出されると Ajax リクエストを Rails アプリケーションに送信するコールバックを定義できるようになっています。Mobile Safari で向きのイベントを処理するために定義しているのは、onorientationchange イベント・ハンドラーおよび window.orientation プロパティーです。Rails はこのイベントの Ajax オブザーバーを作成し、サーバーに対してリモート・コールバックを行うことができます。
このコールバックを使用するには、レイアウトをリスト 7 のように変更してください。
リスト 7. 向きの変更によるコールバックを設定したレイアウト
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
<title>Recipes: <%= controller.action_name %></title>
<meta name = "viewport"
content = "width = device-width, user-scalable=no">
<%= stylesheet_link_tag 'iphone' %>
<%= include_iui_files %>
<%= javascript_include_tag :defaults %>
<%= observe_orientation_change :controller => 'browsers',
:action => :orientation_change %>
</head>
<body <%= register_orientation_change %>>
<%= yield %>
</body>
</html>
|
このレイアウト・ファイルには、連載第 1 回で作成したレイアウト・ファイルに 3 つの変更を加えています。まず 1 つは、デフォルトの JavaScript ライブラリーが組み込まれています (Ajax コールバックにはプロトタイプが必要です)。他の 2 つの変更は、observe_orientation_change と register_orientation_change という rails_iui ヘルパー・メソッドです。この 2 つのうち、単純なのは register メソッドのほうで、このメソッドは文字列を body タグに出力してイベント・ハンドラーを設定するに過ぎません (以下を参照)。
リスト 8. register_orientation_change ヘルパー
def register_orientation_change
'onorientationchange="updateOrientation();"'
end
|
observe メソッドは、リモート・ヘルパーの :url オプションに渡すことが可能なものをすべて引数として取り、register ヘルパーが暗黙的に示す updateOrientation() メソッドを作成します。
リスト 9. observe_orientation_change ヘルパー
def observe_orientation_change(url_options = {})
remote = remote_function :url => url_options,
:with => "'position=' + String(window.orientation)"
func = "function() { #{remote}; };"
javascript_tag("function updateOrientation() { #{remote}; }")
end
|
このメソッドが使用するのは、Rails の標準 remote_function ヘルパーで、このヘルパーに渡された URL 情報を使用して JavaScript コールバックを作成し、script タグ内部にこの関数を出力します。サーバーに対するコールバックには、position というパラメーターが 1 つ含まれます。デバイスが通常の縦向きの状態になっている場合、この変数の値は「0」となります。電話が左方向に回転されると値は「90」になり、右方向に回転されると「-90」になります (デバイスは現在、逆さの状態を認識しませんが、今後も引き続き回転がサポートされれば、値は「180」となるはずです)。コールバックからは、画面上の DOM (Document Object Model) オブジェクトを変更するなど、Rails の RJS JavaScript テンプレートで対応可能なすべての操作を行うことができます。
以上の 2 つのメカニズムを使用すれば、ユーザーによるブラウザーの向きの変更に簡単に対応することができます。
iPhone の動作に関する追加の注意事項
iPhone 固有の Web アプリケーションを作成する上で、この連載は絶好の出発点になるはずです。以下に、念頭に置いておかなければならない点を追記します。
- iPhone は、電話番号のように見える番号を自動的に検知し、ユーザーがその番号をタップして電話を掛けられるようにしています (iPod の場合、このような自動検知は行いません)。ページ上でこの機能をオフにするには、
<meta name = "format-detection" content = "telephone=no"> というメタタグを使用します。この機能をオフにした場合、電話番号を <a href="tel:555-1234">555-1234</a> という形式の HTML リンクに変換することで、該当する電話番号を明示的に識別することができます。
- Google Maps のページにリンクすると、Mobile Safari が終了して Google Maps アプリケーションが起動されます。同様に、YouTube ページにリンクすると YouTube アプリケーションが起動されます。
- JavaScript 関数の
alert、confirm、prompt は iPhone で有効に機能しますが、showModalDialog は機能しません。iUIでは、dialog という CSS クラスがダイアログの振る舞いを模倣して、画面最前面のオーバーレイとして機能します。
- 現時点では、Flash、Java™ アプリケーション、WML (Wireless Markup Language)、SVG (Scalable Vector Graphics)、XSLT (Extensible Stylesheet Language Transformation) はいずれも Mobile Safari ブラウザーで機能しません。ファイルのアップロードとダウンロードはサポートされていませんが、iPhone ファームウェアの 2.0 バージョンでは違ってくる可能性があります。マウスオーバー・イベント、ツールチップ、およびホバー・スタイルも同じく機能しません。
- GIF (Graphics Interchange Format)、PNG (Portable Network Graphics)、TIFF (Tagged Image File Format) の画像は、デコードしたときに 2 メガピクセル以下でなければなりません。2 メガピクセルを超える JPEG 画像はサブサンプリングされて小さくなるので、最大 32 メガピクセルが限度です。個々のテキスト・ファイルやメディア・ファイルは、10 MB 未満でなければなりません。
- iPhone と iPod touch ではどちらも、ユーザーが特定の Web アプリケーションを表すアイコンをホーム画面に配置することができます。アプリケーションにカスタム・アイコンを指定するには、PNG ファイルを /apple-touch-icon.png に配置します。アイコンは、角が直角の 57 x 57 ピクセルにする必要があります。ネイティブ・アイコンが使用する光沢は含めないようにしてください。iPhone または iPod-touch のオペレーティング・システムが、自動的に角を丸くして光沢エフェクトを追加します。

 |
近い将来
iPhone と iPod touch にとって、今年は楽しみな年になっています。2.0 バージョンがサード・パーティーのネイティブ・アプリケーションを追加したとしても、iPhone 対応の Web アプリケーションの需要は増すばかりでしょう。これからも iUI ツールキットと rails_iui プラグインは、開発者が容易に Mobile Safari アプリケーションを見事な仕上がりにするための手段として活躍するはずです。
参考文献 学ぶために
製品や技術を入手するために
議論するために
著者について  | |  | Noel Rappin は、Pathfinder Development (http://www.pathf.com) で Rails 業務の責任者を務めています。Web アプリケーション開発では 10 年の経験を積んでいます。彼が博士号を取得した Georgia Institute of Technology では、オブジェクト指向の設計概念の教授法を学びました。彼の著書には『Professional Ruby on Rails』、共著書には『wxPython in Action and Jython Essentials』があります。詳しくは、http://www.pathf.com/blogs、http://10printhello.blogspot.com を読んでください。 |
記事の評価
|