OnEditorActionListener を使って EditText への Enter キー入力やアクション入力をハンドルする
EditText
への Enter キー入力を検知して何か処理をしたい、ということを調べてみると、TextView.OnEditorActionListener
を TextView#setOnEditorActionListener
メソッド で設定すればよいというようなブログ記事がいくつか見つかる。
editText.setOnEditorActionListener(new TextView.OnEditorActionListener() { @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { // ... 処理 ... return false; } });
- EditTextでソフトキーボードのイベントをハンドリングする
- EditTextでEnterが押されたらキーボードを閉じる
- EditTextで入力完了したら、ソフトキーボード閉じて処理を実行する
- EditTextでエンターキーを押した時にソフトウェアキーボードを閉じる
- OnEditorActionListenerでエンターキーの入力を感知する
- EditTextでEnterキー押下時のイベントを処理する
ただ、ここら辺の記事を読んでも (一番下の記事以外は) onEditorAction
メソッドの第 2 引数 actionId
が何であるかや、第 3 引数 event
が null
になりうることについての言及がなかったりして情報として不十分だったので、調べたことを書き残しておく。
TextView#setOnEditorActionListener
メソッドとは
Javadoc には次のように書かれている。
Set a special listener to be called when an action is performed on the text view. This will be called when the enter key is pressed, or when an action supplied to the IME is selected by the user.
TextView | Android Developers
すなわち、Enter キーが入力されたときや IME に提供されているアクションが選択されたときに呼ばれるコールバック処理を設定するものである。 アクションについては後述する。 コールバック処理は TextView.OnEditorActionListener#onEditorAction(TextView v, int actionId, KeyEvent event) メソッド として記述される。
引数の actionId
は、選択されたアクションを識別するための ID である。 Enter キー入力の場合は EditorInfo.IME_NULL
になる。
第 3 引数 event
には、Enter キー入力の場合にのみ null
でない値が渡される。
また、Enter キー入力の場合には、キーダウン時とキーアップ時の 2 回 onEditorAction
メソッドが呼ばれるようである。
アクションとは
IME に提供されるアクションについては、次のドキュメントに書かれている。
EditText
が複数行を受け付けない場合に、多くのソフトウェアキーボードでは Enter キーの代わりにアクションボタンが表示されるようである。 デフォルトでは 「Next」 や 「Done」 が表示される。 EditText
要素の android:imeOptions
属性を使って、「Next」 や 「Done」 ではなく 「Go」 や検索ボタンを表示させることもできる。
上で説明した TextView#setOnEditorActionListener
メソッドを使うことで、次のような感じでアクションをハンドルできる。
editText.setOnEditorActionListener(new TextView.OnEditorActionListener() { @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { boolean handled = false; if (actionId == EditorInfo.IME_ACTION_DONE) { // ... なんかの処理 ... handled = true; } return handled; // このメソッド中でアクションを消化したら true を返す。 } });
IME については詳しくないのでわからないのだけれど、『Most soft input methods provide a user action button in the bottom corner』 って書かれているので、おそらく IME の実装次第ではアクションボタンが提供されないこともある気がする。
あと、当然ながらハードウェアキーボードしかない場合はユーザーがアクションを実行することはできない。
OnEditorActionListener#onEditorAction
メソッドについてのプラクティス
- Enter キー入力以外では、第 3 引数
event
がnull
になるので、気を付ける必要がある。 - ソフトウェアキーボードの Enter キー入力では
OnEditorActionListener#onEditorAction
メソッドが呼ばれないことがある。- 参考: android - onEditorAction() is not called after Enter key has been pressed on Jelly Bean emulator - Stack Overflow
- これも IME の実装次第だと思われる *2。 バグか仕様かは不明。
- キーイベントについて 『You should never rely on receiving key events for any key on a soft input method』 (Handling Keyboard Actions | Android Developers) ということが書かれているので、
OnEditorActionListener#onEditorAction
メソッドについてもハードウェアキーボードの Enter しか受け取れないつもりでコードを書いた方が良さそう。
- 結論として、「
EditText
での Enter 入力時に (改行させずに) 何か処理をするようにしたい」 という場合、次のようにすべきだと思われる。 *3EditText
要素のandroid:inputType
属性を設定し、複数行入力をできないようにする。EditText
要素のandroid:imeOptions
属性にactionNone
以外の値を設定し、IME にアクションを提供する。 (あるいは独自のアクションを指定するとか。)onEditorAction
メソッドでは、アクションを受け取った場合の処理 (ソフトウェアキーボード用) と Enter キー入力を受け取った場合 (ハードウェアキーボード用) の両方の処理を書いておく。- このとき、Enter キー入力については
onEditorAction
メソッドが 2 回 (action=ACTION_DOWN と action=ACTION_UP) 呼ばれる可能性を考慮してコードを書いた方が良さそう。 (どういう条件でそうなるかはわかってないけど、1 回しか呼ばれないこともあれば 2 回呼ばれることもあるっぽい。)
- このとき、Enter キー入力については
- IME の実装次第ではアクションボタンが表示されず、Enter キー入力では
onEditorAction
メソッドが呼ばれないということもありうると思うので、onEditorAction
メソッドが呼ばれなくても次に進むための方法をユーザーに与えておくべき。 (「検索」 ボタンを配置しておく、とか。)
挙動については確証がない部分もあるけど、上のような感じで実装すれば問題はないはず。
Android Pattern Cookbook マーケットで埋もれないための差別化戦略
- 作者: あんざいゆき
- 出版社/メーカー: インプレスジャパン
- 発売日: 2014/03/20
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (3件) を見る
「うらがみが Java まわりの ORM を知りたい会」 に参加してきた
Java の O/R マッパーまわりの話を知りたかったので、6/14 に行われた勉強会 「うらがみが Java まわりの ORM を知りたい会」 に参加してきました。 会場は和室でした。
Java まわりの O/R マッパー、あんまり詳しくないのでいろいろ知れて良かったです。 メモを残しておきます。
発表内容
Java の ORM、Doma の話 +α (@backpaper0 さん)
いろんな O/R マッパーについての簡単な紹介と、Doma の紹介。
- 紹介された O/R マッパーのうち、使うとしたら JPA か Iciql か Doma かなーという気持ちになった。 (個人の感想です。)
- ちなみに紹介されてる O/R マッパーのうち私がちゃんと知ってるのは JPA だけ。
- Iciql と H2 Database を組み合わせて Android アプリで使うことができる (実際に製品開発に用いた) とのこと。
Doma について
- 公式サイト: Welcome to Doma — Doma 2.0 ドキュメント
- 2 系は Java 8 以降。 1 系は Java 7 までらしい。
- Doma、なんのライブラリにも依存してないらしい。
- Pluggable Annotation Processing API を使ってる。
- その仕組み上他の言語で使えない。
- 原則としてクエリは SQL ファイルに書かないといけない。 (クエリビルダもあるが使わない方が良いらしい。)
- コンパイル時にいろいろ検出。 (対応する SQL ファイルがなかったり中身が空だったり、アノテーションがなかったりすると)
- DAO の引数や戻り値、エンティティのプロパティ (?) などにドメインクラスを使用できる。 (良い!!!)
- 自動生成されるのはエンティティの補助クラスと DAO の実装クラスと、ドメインクラスの補助クラス。
F 社乙女チームの ORM (黒) 歴史 (@daiksy さん)
- Scala でサーバーサイドを書くにあたっての O/R マッパー選択の歴史。
- Play framework。
- 今は Slick か ScalikeJDBC が良さそうだけど、昔は悩ましかった。
- 最初: Squeryl。
- Implicit conversion を駆使するから IDE の補完が微妙だったりしてしっくりこなかったらしい。
- 2 個目: ScalaQuery (のちの Slick)。
- 使いやすいし、後々デファクトスタンダードになるのは理解できる。
- Scala 2.9 → 2.10 のバージョンアップ時に Slick と名を変えて 2.9 系は切り捨てられた。
- ScalaQuery を使っていた web アプリケーションはあえなくレガシー化...。
- Scala はバイナリ互換性がないのがつらいよね。
- 最後: MapperDao を採用。 (現在も。)
- Squeryl, Slick, Activate, Circumflex-ORM, MapperDao, SORM, Scala ActiveRecord などを検討して、結果的に MapperDao。
- DSL が結構良い。 普通の SQL っぽい感じで書ける。
- ドキュメントの量とかは少ないので、今からなら Slick とか ScalikeJDBC のが良さそうな気がする。
Scala 周りの文化は全然知らないので、そんな感じなのかーと思いながら聞いてた。 Scala 便利だけど互換性とか大変そう。
ORM 初心者が使おうとした (@KYON_MM さん)
3 つの O/R マッパー紹介
- JOOQ
- 機能的には使いやすい。 大体揃っているしユーザー数も多そう。
- QueryDSL を駆逐してやるという勢いを感じる。
- Iciql
- とても薄いラッパー。 手軽で良さそう。
- Slick
- Play Framework のデフォルトになる予定。
- 型型しすぎてる雰囲気。
- Scalaz と同じ雰囲気。
- ScalikeJDBC の方が好きな人が多いのでは?
MyBatis (@s_kozake さん)
GORM めっさゆるい (@kazuhito_m さん)
- リファレンス: 7 Object Relational Mapping (GORM) 2.4.0
- Grails 用の O/R マッパー。
- Grails とは独立させて使おうとすると大変っぽい?
- GORM、Groovy らしさがあふれてるなーと思った。
- ゆるい感じで使いたいならいいけど、まじめに大規模開発に使うと死にそう。
Unicode のサロゲートペアとは何か
こないだ同僚に Unicode のサロゲートペアについて説明する機会があって、それで Unicode の話をブログ記事に書きたくなったのでサロゲートペアについて書いておこうと思う。
この記事は Unicode Standard version 6.3.0 を見ながら書いた。
文字とコードポイント
抽象文字 (abstract character) を計算機上で扱うためには、符号化する必要がある。 Unicode では、文字の符号化のために使用できる整数の範囲を コード空間 (Codespace; 符号空間) と呼んでいる。 0 から 0x10FFFF がその範囲である。 そして、その空間に属する値を コードポイント (Code Point; 符号位置) と呼ぶ。
次の図は、抽象的な 「Å」 という文字と、対応する 符号化文字 (Encoded Character) を表現するコードポイントの関係を表すものである。 (Unicode Standard 6.2 より。) 下の図を見るとわかるように、1 つの抽象文字が複数の符号化文字に結び付けられることがある。 また、1 つの抽象文字が複数の符号化文字により構成されることもある。
Unicode コードポイントを参照する際は、「U+」 という接頭辞を付けて、16 進数表記の数字を続けて記述するのが Unicode Standard での表記法である。 また、符号化文字も単にコードポイントだけで参照することができる。
つまり、上の図における 00C5 という符号化文字を参照するために、「U+00C5」 という表記を使用できる。
なお、コードポイントは、必ずしも符号化文字に割り当てられているとは限らない。 (後で説明するが、サロゲートコードポイント (Surrogate Code Point) がその一例である。)
符号化文字と文字符号化形式
さて、上で述べたように Unicode 文字にはそれぞれコードポイントが与えられているわけであるが、そのコードポイントを計算機上でどのように表現するか、という意味でさらに符号化する必要がある。
Unicode Standard では、UTF-8、UTF-16、UTF-32 という 文字符号化形式 (Character Encoding Form) が提供されている。 それぞれ 8 ビット、16 ビット、32 ビットを 符号単位 (Code Unit) とする符号化方式である。
上の図は、いくつかのコードポイントが各文字符号化方式でどのように表現されるかを表した例である。 (Unicode Standard 6.2 より。)
任意のコードポイントは単一の 32 ビット符号単位で表現できるため、UTF-32 では常に 1 符号単位が 1 コードポイントを表す。 UTF-16 では、U+0000 から U+FFFF までのコードポイントは 1 符号単位で表現され、U+10000 以降のコードポイントは後述するサロゲートペアで表現される。 UTF-8 では、1 コードポイントを表現するために 1 個から 4 個の符号単位が使用される。
サロゲートペアについて
さて、いよいよ サロゲートペア (Surrogate Pair; 代用対) の説明を行う。 サロゲートペアとは、一言で言ってしまうと 16 ビット符号単位の組による単一の抽象文字の表現である。 UTF-16 でのみ用いられる。
UTF-16 は、16 ビットを符号単位とする文字符号化形式なので、任意のコードポイントを 1 符号単位で表現することができない。 16 ビットで表現可能な U+0000 から U+FFFF までのコードポイントについては、そのままコードポイントの数値を 16 ビットで表現するようになっている。 残りの U+10000 から U+10FFFF までのコードポイントは 16 ビットの符号単位の組で表現されるようになっていて、この組のことをサロゲートペアと呼ぶ。 例えば、先の図では U+10384 というコードポイントを表現するために、0xD800 と 0xDF84 の 2 つの符号単位の組が用いられていた。
上で 「U+0000 から U+FFFF までのコードポイントについては、コードポイントをそのまま 16 ビットで表現するようになっている」 と述べたが、それだとサロゲートペアのために使用できる符号単位がなくなってしまう。 そこで、Unicode では U+D800 から U+DFFF までのコードポイントをUnicode 文字に割り当てないようにし、0xD800 から 0xDFFF までの 16 ビット符号単位をサロゲートペアに使用できるようにしている。 これらのコードポイントはサロゲートコードポイントと呼ばれる。
つまり、より正確にいうと、UTF-16 では 「U+0000 から U+D7FF までと U+E000 から U+FFFF までのコードポイントについては 16 ビットの 1 符号単位であらわされ、U+10000 から U+10FFFF までのコードポイントは 2 つの符号単位の組で表現される」 ということになる。
文字符号化形式のためにコードポイントが使用されるのは奇妙な感じがするが、このような形になっているのは、もともと UTF-16 が固定長の文字符号化方式として設計されていたという歴史的な理由らしい。 (あんまり詳しくない。)
備考
U+0000 から U+FFFF までのコードポイント (文字符号化形式 UTF-16 において、単一の符号単位で表現できるコードポイント) は BMP コードポイント (BMP Code Point; BMP符号位置) と呼ばれる。 U+10000 から U+10FFFF までのコードポイントは 補助コードポイント (Supplementary Code Point; 補助符号位置) と呼ばれる。
ややこしいと思うこと
サロゲートペアはあくまで UTF-16 という文字符号化形式でのみ使用されるものであるが、UTF-16 でサロゲートペアが使用されるために U+D800 から U+DFFF のコードポイントがサロゲートコードポイントとして予約されていたりするあたりがややこしいと思う。 歴史的経緯...。
参考文献
- Unicode Terminology: English - Japanese : 日本語と英語の対応。 この記事はこの対応表に必ずしも従っていない。
- Glossary : 用語集。
- Unicode Standard Version 6.2, Chapter 2
ソフトウェア開発をするうえで最低限身につけておかなければならない文字エンコーディングに関する知識は次の書籍を読めば身につくと思う。 文字エンコーディング周りについて不安がある人は読むといい。
プログラマのための文字コード技術入門 (WEB+DB PRESS plus) (WEB+DB PRESS plusシリーズ)
- 作者: 矢野啓介
- 出版社/メーカー: 技術評論社
- 発売日: 2010/02/18
- メディア: 単行本(ソフトカバー)
- 購入: 34人 クリック: 578回
- この商品を含むブログ (130件) を見る
Android アプリの Action bar に独自 View を設定する
ActionBar#setCustomView
メソッド
Action bar に独自ビューを設定するには、ActionBar#setCustomView
メソッドを使用する。
ActionBar#setCustomView(int)
メソッドActionBar#setCustomView(View)
メソッドActionBar#setCustomView(View, LayoutParams)
メソッド
このメソッドを呼び出すだけでは独自ビューが表示されない。 独自ビューが表示されるようにするために、DISPLAY_SHOW_CUSTOM
オプションを有効にする必要がある。 また、独自ビューを設定しただけでは、通常表示されるタイトル部分 (?) も合わせて表示されるので、タイトル部分を表示しないように設定する必要もある。 (詳しくは下に書いている例を参考のこと。)
API ドキュメントを見ると次のように書かれているので、この独自ビューは、独自のナビゲーションを実現するためのもののようである。
Set the action bar into custom navigation mode, supplying a view for custom navigation.
Custom navigation views appear between the application icon and any action buttons and may use any space available there. Common use cases for custom navigation views might include an auto-suggesting address bar for a browser or other navigation mechanisms that do not translate well to provided navigation modes.
例
下の例では DISPLAY_SHOW_CUSTOM
オプションを有効にするために setDisplayOptions
メソッドを使っているが、他のオプションの値もまとめて設定したい、という場合でなければ setDisplayShowCustomEnabled(boolean)
メソッド を使った方が手軽で良さそう。
@nobuoka setDisplayOptionsの代わりにいつもsetDisplayShowCustomEnabledを使ってますが、違いがあったりするんでしょうか(ソースは今から追いかけるところ
— いちごたけさん (@ichigotake) 2014, 5月 24
素の Activity クラスの API を使用
API level 11 以降であれば、以下のような感じで素の Activity のメソッドを呼び出して Action Bar に独自 View を設定できる。
// 必要な import 文 import android.app.ActionBar; // android.app.Activity クラスを拡張した Activity の中で。 ActionBar actionBar = getActionBar(); // 通常表示されるタイトルを非表示にする。 actionBar.setDisplayShowTitleEnabled(false); // 独自のビューを表示するように設定。 actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM, ActionBar.DISPLAY_SHOW_CUSTOM); // 独自のビューを指定。 (ここではレイアウトリソースの ID を指定しているが、View オブジェクトを渡すこともできる。) actionBar.setCustomView(R.layout.custom_actionbar);
Support Library の v7 AppCompat ライブラリを使用する場合
v7 AppCompat ライブラリを使用する場合は次のような感じになる。 getActionBar()
メソッド呼び出しが getSupportActionBar()
メソッド呼び出しに変わったのと、ActionBar
のパッケージが異なる以外は、同じコードになる。
// 必要な import 文 import android.support.v7.app.ActionBar; // android.support.v7.app.ActionBarActivity クラスを拡張した Activity の中で。 ActionBar actionBar = getSupportActionBar(); // 通常表示されるタイトルを非表示にする。 actionBar.setDisplayShowTitleEnabled(false); // 独自のビューを表示するように設定。 actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM, ActionBar.DISPLAY_SHOW_CUSTOM); // 独自のビューを指定。 (ここではレイアウトリソースの ID を指定しているが、View オブジェクトを渡すこともできる。) actionBar.setCustomView(R.layout.custom_actionbar);
ActionBarSherlock を使用する場合
ActionBarSherlock を使用する場合は次のような感じになる。 ActionBar
のパッケージが異なる以外は、v7 AppCompat ライブラリのコードと同じ。
// 必要な import 文 import com.actionbarsherlock.app.ActionBar; // com.actionbarsherlock.app.SherlockActivity クラスを拡張した Activity の中で。 ActionBar actionBar = getSupportActionBar(); // 通常表示されるタイトルを非表示にする。 actionBar.setDisplayShowTitleEnabled(false); // 独自のビューを表示するように設定。 actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM, ActionBar.DISPLAY_SHOW_CUSTOM); // 独自のビューを指定。 (ここではレイアウトリソースの ID を指定しているが、View オブジェクトを渡すこともできる。) actionBar.setCustomView(R.layout.custom_actionbar);
読んだ: Effective Android
- 作者: TechBooster,小太刀御禄,出村成和,重田大助,西岡靖代,宮川大輔,柏本和俊,あんざいゆき,八木俊広,木村尭海,小林慎治,有山圭二,中西良明,わかめまさひろ,新井祐一,桝井草介,久郷達也,寺園聖文,shige0501,山下智樹,前田章博,秋葉ちひろ,末広尚義,中澤慧,日高正博,塚田翔也,井形圭介,中川幸哉,山崎誠,山下武志,なまそで,橋爪香織,さとうかずのり,l_b__,ゼロハチネット,長汐祐哉
- 出版社/メーカー: インプレスジャパン
- 発売日: 2014/01/17
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (7件) を見る
読みました。 タイトルからは 『Effective C++』 や 『Effective Java』 が連想されますね。 副題として 「アプリケーション開発を効率化する 39 のテクニック集」 と表紙に書かれています。
Effective Android - 達人出版会内容紹介
Androidの機能・端末バリエーションは年々巨大化しています。おぼろげな理解でも試行錯誤によってある程度のことが実現出来ますが、安定動作するアプリ、使っていて気持ちの良いアプリに仕上げる上では、依然きちんと理解する必要のあることが多く存在します。
本書は、Androidアプリ開発へ携わる著者総勢20名によるデザイン/開発上のポイント集です。
日々の開発中にぶつかった問題を掘り下げたもの、Androidのソースコードを読み解くことで得られたもの、多くの端末サイズ/解像度へと対応する中で得られたもの、Googleサービス群と連携する中で得られたものなど、日々のアプリ開発を一歩先へと進めるヒントに満ちていることでしょう。
上記内容紹介にかかれているように、本書は複数人によって書かれた書籍です。 もともと同人誌として発行されていたものなので、わりと各自が好きなことを書いてるようで、基本的には章ごとの体系だった流れのようなものはありません。 ある程度分野ごとに章はまとまっていますし、関連する章が前後に並んでいたりはしますが、基本的にはそれぞれの章を独立に読む、という感じの読み方になるでしょう。
カード UI の実現の仕方や、カード UI にアニメーションを付ける方法、といったすぐに使える UI 上のチップスもあれば、Eclipse の設定ファイルの話や Gradle の話といった開発環境周りの話、SQLite や NFC といったミドルウェア (?) 的な話、便利ライブラリの紹介、それから NDK などのプラットフォーム周りの話といった感じで、内容は多岐にわたっています。
以前、Maven Central Repository への AAR パッケージのアップロード方法を書きましたが、それと同様の内容も本書に収録されてました。
さらには、Git についての話や Java 7、Java 8 の話も書かれています。 Git については、write-tree
コマンドや rev-parse
コマンドといったマニアックなコマンドが紹介されていて、普段 Git を使っている人でも 「ほえー」 ってなるかもしれません *1。 Java 7 の話については、API level 19 以降では Java 7 の構文をフルで使えるようになった *2 といったことが書かれていて、そういうことを知らない人にはいろいろ得るところがあると思いますし、Java 8 についてもいろいろ書かれていて勉強になります *3。
感想
内容が多岐にわたっており、また、結構マニアックな話題も多いので、いろいろ視野が広がって良かったです。 たとえば、NFC タグの話や SQLiteDatabase の WAL の話、オーディオ周りの話などは 「へー」 という感じで読みました。 普段業務で Android アプリを開発していたり、個人で Android アプリを開発している人で、自分が普段関わらないようなところも含めてチップス集を読みたい、という気持ちがあれば本書はオススメです。 すぐさま業務に活かせるようなチップスもありますし (そうでないものもあります)、読み物としても興味深く読めるでしょう。
一方で、体系だった章立てになっていないという点や、全体的に誰しもにすぐ役立つ情報が多くないという点から、一通り Android アプリ開発できるようになった人に 「とりあえず読め!」 って感じで薦められる本ではないです。 あえてこういうことを書くのは、『Efefctive C++』 や 『Effective Java』 とタイトルが似てるからです *4。
読み物的な感じで Android アプリに関して視野を広げたい、って人にお勧めです。
EFFECTIVE JAVA 第2版 (The Java Series)
- 作者: Joshua Bloch,柴田芳樹
- 出版社/メーカー: 丸善出版
- 発売日: 2014/03/11
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (4件) を見る
『Effective Java』 もお薦めです。