2014年10月21日火曜日

Life/Biorhythm Logger (LB Logger) の v1.4 をリリース

今回のバージョンアップで
  • ログ一覧をインクリメンタルサーチする機能を追加
  • バグ修正
という修正を行いました。

1点目について、このブログでより詳細を書きます。

次の画像のように、ログ一覧の上に検索文字列を指定する領域が追加され、そこに入力した文字列でログの絞り込みを出来るようになりました。



入力する文字列は任意の文字列で、日付・種類・メモ部分のどこでも良いので文字列が一致したもので絞り込むことが出来ます。
メモ部分に特定のキーワードを(タグ的に)入れるなどしておけば、後で一気に抽出することなども可能です。

このように新しい振り返り方ができるようになりましたので、ぜひ活用してみて下さい。

2014年10月15日水曜日

Life/Biorhythm Logger (LB Logger) の v1.3 をリリース

今回のバージョンアップで
  • メニュー → エクスポート(メール)、メニュー → 一括エクスポート (SD) コマンドの追加
    ログデータを CSV 形式でエクスポートできます。
    SD への出力のため、権限でストレージ書き込みが必要となりました。
  • グラフ描画の処理を最適化
という修正を行いました。

1点目について、このブログでより詳細を書きます。

次の画像のようにメニューに「エクスポート(メール)」「一括エクスポート (SD)」というコマンドを追加しました。

どちらのコマンドもログを CSV 形式でエクスポートすることが出来ます。

メールへの出力の場合、次の画像のように連携したメール送信画面からログを送信することができます。
この際、エクスポートされるのは現在開いているログ画面(生活/バイオリズムのどちらか)のものとなります。


SD への出力の場合、次の画像のようにファイルを出力したフォルダが表示されます。
このフォルダ配下に、生活・バイオリズムそれぞれの単位で一括してファイルに出力されます。


他のアプリ・パソコンなどでデータを参照する際などに利用して下さい。

2014年10月10日金曜日

Life/Biorhythm Logger (LB Logger) の v1.2 をリリース

今回のバージョンアップで
  • "メニュー → 過去ログ削除(指定日以前)" コマンドを追加 : 指定した日以前のログを一括削除する機能
  • 画面デザインや語句の見直し
という修正を行いました。

1点目について、このブログでより詳細を書きます。

次の画像のようにメニューに「過去ログ削除(指定日以前)」というコマンドを追加しました。


このコマンドを実行すると次の画像のように


日付を指定する画面が出てきます。
  • 「削除」ボタンを押すと、この画面で指定した日付以前のログを一気に削除することが出来ます
  • 削除対象となるログは現在開いているログ(生活 or バイオリズム)だけとなります。
    もう一方の方は削除されません
ログの量が増えてきて、以前のものが必要なくなった際などに利用して下さい。

2014年10月4日土曜日

Titanium Tips: Titanium で図形描画、WebView の利用

Titanium の開発で図形描画の解決方法として、デザインの統一性さえゆるせば WebView +Javascript の描画ライブラリを使うという方法があります。
実際、私のアプリケーションではグラフを描くのに、WebView と Flot: Attractive JavaScript plotting for jQuery を組み合わせて実現しました。

公式の Using Local Web Content with WebView にあるように WebView は local な HTML/javascript などを読み込み可能です。
例えば、Alloy の View 側で app/assets/etc/local.html を読み込むには次のように
<Window title="hogehoge">
        <WebView id="webview" url="/etc/local.html"></WebView>
</Window>
という指定になります。
local.html 側では
<head>
<title>Local HTML</title>
<link rel="stylesheet" type="text/css" href="local.css"/>
<script src="local.js"></script>
</head>
と書くと local.html と同階層=app/assets/etc 配下の local.css, local.js を読み込み、利用することが出来ます。
(もちろん、local.html 内でも Javascript を記述可能)

また、local な Javascript の利点として次の2点があります。
特に、Ti.App.fireEvent() と Ti.App.addEventListener() を使うことで、Titanium 側の通常の Javascript のコードと WebView内の Javascript とで相互に通信が出来るのは、必須とも言える機能です。詳しい説明やサンプルは公式の Communication Between WebViews and Titanium を参照してみて下さい。

注意点としては、javascript を script タグなどで静的に読み込みしてしていなくて、生成した HTML で読み込むようなケース。
そのような場合には
For local JavaScript files not referenced in static local HTML files, for example, a dynamically-genereated HTML file referencing a local JavaScript file, rename the file extension of the local JavaScript files to '.jslocal' instead of '.js'.
とあるように拡張子を .js → .jslocal に変える必要があるようです。

2014年10月3日金曜日

Titanium Tips: Alloy のモジュール間での汎用的なデータのやりとり方法

前回のTitanium Tips: Alloy での部品化でソースを分割する方法をまとめましたが、今回はそれぞれに依存しないようなパーツ間でのデータのやり取り方法の(自分用)まとめ。

選択方法としては
  1. Alloy.Globalsなど
  2. Ti.App によるユーザ定義のイベント通信
から選べそうです。
(他にもありそうですが、私自身は見つけられていない…)

ただ、どちらもグローバルにリソースを食うことになるので、使いすぎやメモリリークには注意しましょう。

1.  Alloy.Globalsなど

公式の Alloy クラスをみれば分かりますが、次のような全 controller からアクセス可能なデータ格納用オブジェクトが用意されています。
(一部は controller 以外からのアクセス方法もあり)
  • Globals: 任意の変数・関数をプロパティとして格納可能
  • CFG:  app/config.json で定義した Key/Value 値
  • Collections: Collection用
  • Models: Model用
Globals, CFG は特に使いやすいと思われます。

2. Ti.App によるユーザ定義のイベント通信

公式の Application-Level Events に
App-level events are global to your app. They are accessible in all contexts, functional scopes, CommonJS modules, and so forth.
とあるように Ti.App.addEventListener() で定義したカスタムイベントは Ti.App.fireEvent() でコンテキストを超えて呼び出し可能です。
WebView を扱う際には必須ともいえる方法です → Communication Between WebViews and Titanium

removeEventListener() で登録解除できますが、引数に add した際の関数を渡す必要があるので、無名関数の場合には関数の参照を保存しておく必要があるので注意して下さい。
登録時
var listener = function() { Ti.API.info("Event listener called."); }
window.addEventListener('click', listener);

解除時
window.removeEventListener('click', listener);
 また、上記の WebView での例ではイベント名に "app:fromTitanium" のように "app:" という prefix をつけて、名前衝突が起こるのを推奨しています(もちろん必須ではありません)。

2014年9月29日月曜日

Titanium Tips: Alloy での部品化

Titanium の開発の中で部品化のために出てくる
  1. View 内から require で別の View を読み込む 
  2. Controller 内から createController で 別 View/Controler を動的生成
  3. controller 内で require による CommonJS モジュールの読み込み
辺りについて簡単なメモ。
(半分自分向けのポイントのみのまとめです。
 実例を交えた詳しい説明はすでに色々なサイトでされているので・・・
 後、widget という手もありますが、手を出してないので省略)

1. View 内から require で別の View を読み込む

公式ドキュメントとしては Alloy XML Markup内の Require Element

この方法で View 内で別の View を読み込むことが出来ます。
<Require type="view" src="about" id="aboutTab"/> ← about.xml に定義した View
View に対応した Controller(~.js)はあっても無くてもOK。
("Views can be created without controllers with an optional style sheet"@ Views without Controllers

また、クラスのインスタンス化的に同じ View を複数回 require しても可。

<Alloy>
 <Window layout="vertical">
    <Require id="button1" src="foo" type="view"/>
    <Require id="button2" src="foo" type="view"/>
    <Require id="button3" src="foo" type="view"/>
  </Window>
</Alloy>

単純にソースの見やすさ・管理のしやすさ、ということだけではなく、一つの View 定義の使い回しが可能です。

では、その分かれた View に対して、require する側からアクセスするには、 xml で指定した id ベースになります。
汎用例:var object = $.requireId.getView('objectId');
例えば、require で指定した id が aboutTab、読み込む src 内にある view の id が aboutView の場合、それを取得するには、
var aboutView = $.aboutTab.getView('aboutView'); 
となります。
ちなみに、 undocumented なやり方ですが id をつなげるだけでもアクセスできるようです。
例えば、上の例ならば次のような形になります。
$.aboutTab.aboutView

2. Controller 内から createController で 別 View/Controler を動的生成

公式ドキュメントとしては Alloy Controllers 辺りでしょうか。

Controller 内から独立した View, Controller を動的生成する場合には Alloy.createController() を使い、getView() で View を取得します。
var about = Alloy.createController('about', args).getView();
about.open();
これで about.xml, about.tss, about.js で定義された1セットをインスタンス化できるわけです。
またこの際に、引数を渡すことができるので(上記の args)、そこで様々な情報を引き渡すこともできます。

3. controller 内で require による CommonJS モジュールの読み込み


公式ドキュメントとしては CommonJS Modules in Titanium
複数の Controller で使うコードを、独立・共通化して記述することが可能です。

app/lib/ 配下に .js ファイルを配置して、require で読み込めば利用できます。

モジュール側は CommonJS に則った書き方になりますが、
  • exports - a free variable within a module, to which multiple properties may be added to create a public interface
  • module.exports - an object within a module, which may be REPLACED by an object representing the public interface to the module
とモジュール側からの公開方法は2通りの方法があります。

exports は require で読み込んだ側のオブジェクトでプロパティを参照する方式。

module.exports の場合には、require で読み込んだオブジェクトがそのままモジュール側で指定したものに置き変わる形。
module.exports はクラスを定義してそれを丸ごと公開するようなものに向いています。
(公式ドキュメントの Person の例などが分かりやすい)

2014年9月24日水曜日

Titanium Tips: TableView + dataFilter で上位~個だけ表示

今回アプリを作るにあたって、実装で少し苦労・工夫したところの一つは、Alloy の TableView  の dataFilter と Model を組み合わせて、表示内容を上位~個だけ表示させる実装でした。

私がやりたかったことは、TabbleView に binding して自動的にリスト表示されている SQLite のデータから、そのままでは全データが表示されてしまうものを、表示する個数を制限する、ということでした。

それを、TableView の dataFilter を使う方法で実現をしました。

TableView の dataFilter は、Alloy Data Binding - Titanium 3.X - Appcelerator Docs の説明を引用すると
dataFilter: specifies an optional callback to use to filter data in the collection. The passed argument is a collection and the return value is an array of models.
とあるように、 binding されたデータをフィルタリングする機能です。
サンプルなどでは、書籍データの中から著者(author)で絞り込みをするような、SQL でいうところの where 句での絞り込みのようなものをしていることが多いです。
例えば、上記の「Alloy Data Binding」でも dataFilter用の関数では
// Show only book models by Mark Twain
function filterFunction(collection) {
    return collection.where({author:'Mark Twain'});
}
ただ、結果として「the return value is an array of models.」とモデルの配列を返せば良いので、Filter の仕方に特定の制限はなさそうでした。
そこで
function filterFunction(collection) {
var i=0;
    collectionTopMost = new Array();
    // Collection 中、上位~だけを配列として取りだし(この例では 10個固定)
    for(i=0; i<10 && i<collection.length; i++){
  collectionTopMost.push(collection.at(i));
    }
return collectionTopMost;
}
といった形で必要な個数の配列を返すように実装しました。

この方法でリスト表示数に制限をかけられるようになりました。



Android アプリを Titanium Studio/Alloy を使って作ったので、その際にひっかかったことを、Tips で書いていってます。
実際に同じところで躓いた人がいて、それの解決のお役に立てば、と思っています。
ちなみに環境は Windows + Titanium Studio 3.3 + Android用開発となっています。

ただ、まったくのピンポイントでの Tips なので、まとまっての記述を期待している人にはすいません。