◆PROCESSING 逆引きリファレンス
カテゴリー:スマホ(AndroidMode)
キー入力を検知するには(AndroidMode編)
【概要】
PROCESSINGにAndroidMode を導入する事で、PROCESSINGで開発したプログラムをAndroid端末上で動かす事ができるようになります。
AndroidModeの導入については「PROCESSINGをAndroid端末で動かすには(4.0版)」記事を参照してください。
PCではマウスとキーボードで入力操作を行うのが一般的です。
JavaモードのPROCESSINGでは keyPressed イベント関数や keyPressed システム変数でキー入力を検知する事が可能でした。
AndroidModeでも これらを使うことが可能ですが、その動作はJavaモードの時とはかなり異なります。
なお、以下の記載はすべてソフトウェアキーボードしか搭載していない(つまり国内で良く出回っている)スマホ操作時の説明となります。
ハードウェアキーボードを搭載しているスマホや、普通のスマホにハードウェアキーボードを接続した場合、どのような動作になるかは確認できていません。あしからずご了承下さい。
まずキーが押された事を検知するkeyPressedイベント関数と、キーが離された事を検知するkeyReleased イベント関数ですが、共に「英語」キーボードでの操作のみキャッチします。
キーボードが「日本語」の場合で、かつ変換入力を伴う場合は、キー操作を行ってもイベントをキャッチする事ができません。つまりこれらのイベント関数では日本語入力を扱うことができないという事です。
・・・ちょっと残念ですね(泣)。
なおエミュレータで実行した場合は、PCに接続されているキーボードの操作をキャッチする事が可能です。
またJavaモードで、キーが押されている間 True となった keyPressed システム変数ですが、ソフトウェアキーボードを操作しても値が変化しません(正確には、反応したり、しなかったりと不安定です:汗)。
keyPressed システム変数は、スマホ本体に搭載されている一部のボタン(具体的には音量の上下キーと戻るボタン)を押している時にTrueとなります。
またエミュレータ実行時は、PCのキーボードの一部ボタン(矢印キーや、リターンキーなど)押下時にのみ True となります。
Javaモードの時のように、keyPressed システム変数でキーの押下状態を判定するようなロジックは、期待通り動作しない事になりそうですので注意してください。
key システム変数と keyCode システム変数も利用可能ですが、keyPressed、keyReleased イベント関数が動作するタイミングでしか意味を持ちません。
AndroidModeで押された(あるいは離された)キーを知りたいなら、これらのシステム変数を使うのではなく、keyPressed、keyReleased イベント関数に渡されてくる KeyEvent クラスを使って、押されたキーを判定するのが良いでしょう。
【詳細】
キー操作イベント関数
キー操作イベントvoid keyPressed ( KeyEvent keyEvent ) ;
void keyReleased ( KeyEvent keyEvent ) ;
keyEvent : キーイベントクラス
keyPressed はキーボードが押されたイベントをキャッチします。keyReleased は、キーボードのボタンから指が離されたイベントをキャッチします。
共に、keyEvent には操作されたキー情報が渡されてきます。
ちょっと紛らわしいのですが、KeyEvent は PROCESSING独自のイベントクラスです。Android SDK のネィティヴクラスではないので注意して下さい。
キーを判定する
コードを判定するint code = keyEvent . getKeyCode() ;
code : 操作されたキーコード
keyEvent : キーイベントクラス
getKeyCode() メソッドを利用する事で、イベントが発生したキーを知る事が可能です。
得られるキーコードは、Android SDK のものと互換があります。
以下のサイト様などにSDKのキーコードが綺麗にまとめられています。キーコードについて詳しく知りたい方は、参考として下さい。
なお、アルファベットの大文字や一部の文字(@や$など)は、シフトキー(KEYCODE_SHIFT_LEFT)のコードと、その文字が割り当てられたキーコードの両方が通知されてきます。
例えば大文字のAを押して離したイベントは、以下のようになります。
02-09 14:35:45.434 3318-3340/com.example D/AMTEST: keyPressed CODE=59
02-09 14:35:45.434 3318-3340/com.example D/AMTEST: keyPressed CODE=29
02-09 14:35:45.434 3318-3340/com.example D/AMTEST: keyReleased CODE=29
02-09 14:35:45.434 3318-3340/com.example D/AMTEST: keyReleased CODE=59
Aキーを1回だけ押して離した操作であっても、押されたイベントが2回、離されたイベントが2回、合計4回のイベントが連続で発生します。
59番はシフトキー(KEYCODE_SHIFT_LEFT)、29番はアルファベットのa(KEYCODE_A)です。
つまり大文字のAは、「シフトキーとaを、同時に押して離した」操作として通知されてくるというわけです。
大文字のAを表すコードが1回だけ通知されてくるわけではないので、注意して下さい。※
※PCのキーボードから入力した場合、一部のキーコードが期待通り通知されない事があるようです。例えば大文字のBはCODE137(KEYCODE_F7)として通知されてきます。本来は 59 + 30 の筈なのですが・・・何かの不具合っぽいですね(汗)。ソフトウェアキーボード経由で入力すると問題ありません。私の環境の問題??
文字を判定するchar moji = keyEvent . getKey() ;
moji: 操作されたキー文字
keyEvent : キーイベントクラス
コード(番号)ではなく、操作されたキーの文字を得ます。
ただし文字に変換できないような特殊キー(KEYCODE_DELやKEYCODE_SHIFT_LEFTなど)を操作した場合は、moji は -1(0xFFFF)になるので注意して下さい。
【関連記事】
サンプルプログラム
文字の入力をキャッチする例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
import android.util.Log; import processing.core.PApplet; import processing.event.KeyEvent; /** * PROCESSING AndroidMode Key Event Sample * @author MSLABO * @version 1.0 */ public class Sketch extends PApplet { @Override public void settings() { fullScreen(); } @Override public void setup() { } @Override public void draw() { background(255); if( keyPressed ){ //一部のHWボタンが押された時 Log.d("AMTEST", "KEYPRESSED CODE=" + keyCode + " KEY=" + hex(key) ); } } /** * キー押下イベント関数 * @param keyEvent イベント情報 */ @Override public void keyPressed(KeyEvent keyEvent) { super.keyPressed(keyEvent); Log.d("AMTEST", "keyPressed CODE=" + keyEvent.getKeyCode() + " KEY=" + hex(keyEvent.getKey()) ); } /** * キーリリースイベント関数 * @param keyEvent イベント情報 */ @Override public void keyReleased(KeyEvent keyEvent) { super.keyReleased(keyEvent); Log.d("AMTEST", "keyReleased CODE=" + keyEvent.getKeyCode() + " KEY=" + hex(keyEvent.getKey()) ); } } |
キー押下、キーリリースのタイミングでログを出力します。
以下のサンプルは、キーボードから 「qaZ」と押下した際のログです。上から順番に CODE 45(q)、CODE 29(a)、CODE 59(SHIFT) + CODE 54(z) になっています。
簡易タイプライターモドキ例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
import processing.core.PApplet; import processing.event.KeyEvent; import static android.view.KeyEvent.KEYCODE_DEL; import static android.view.KeyEvent.KEYCODE_F7; /** * PROCESSING AndroidMode Key Event Sample * @author MSLABO * @version 1.1 */ public class Sketch extends PApplet { String pushString = ""; //入力文字 float lineLength = 0; //1行あたりの文字長 @Override public void settings() { fullScreen(); } @Override public void setup() { //フォント設定 textSize(24 * displayDensity); textAlign(LEFT, TOP); fill(0); } @Override public void draw() { //画面に入力された文字を表示する background(255); text(pushString,10,10); } /** * キー押下イベント関数 * @param keyEvent イベント情報 */ @Override public void keyPressed(KeyEvent keyEvent) { super.keyPressed(keyEvent); if( !hex(keyEvent.getKey()).equals("FFFF") ){ //制御文字以外なら、入力文字として扱う //表示文字が画面の横幅を超えるなら、自動改行する lineLength = lineLength + textWidth(keyEvent.getKey()); if( lineLength > width ){ //横幅を超えるので自動改行 pushString = pushString +"\n"; lineLength = 0; } //表示用文字列を作成する pushString = pushString + keyEvent.getKey(); } else { //制御文字 if( keyEvent.getKeyCode() == KEYCODE_F7 ){ //大文字Bは BUG?で CODE137 になるので回避 pushString = pushString + "B"; } else if( keyEvent.getKeyCode() == KEYCODE_DEL ){ //DELキー(BackSpace)なら1文字削除 int len = pushString.length() - 1; if( len > 0 ){ pushString = pushString.substring(0, len); } else { pushString = ""; } } } } } |
本例はPCのエミュレータ上で実行してください。
keyPressed イベントでキー入力をキャッチし、入力された文字が制御文字以外なら、画面に表示します。
真っ白なスマホ画面上にPCのキーボードから文字を入力すると、入力した文字がどんどん表示されていきます。
大文字Bの入力だけBUGがあるようなので、無理やり回避しています(汗)。
エミュレータではなく実機で動作させたい場合は、文字入力のためにソフトウェアキーボードを表示させる必要があります。
本ページで利用しているアイコン画像は、下記サイト様より拝借しております。各画像の著作権は、それぞれのサイト様および作者にあります。