Androidアプリ タップイベント [Androidアプリ開発]
ビューを作り、「好きな文字列」を表示することができた。センサーの値も取れた。次に何をやろうかと悩んだが、やっぱりタップしてみたいでしょう。ということでタップのイベント処理に挑戦してみることにした。
正確な用語は、「タップ」じゃなくて、「タッチ」みたいだが、「タッチ」だと微妙にエッチなのでタップで行くことにする。
でもって、タップされたかどうか、またその位置は、onTouchEventメソッドをオーバーライドすることで取得できる。
このメソッドは、Activity、Viewの両方にある。自前のビューを作成している場合は、Viewの方にonTouchEventを作成する。
これで、タップするとイベントが発生し、onTouchEventが呼び出される。
onTouchEventに渡ってくるMotionEventオブジェクトに、タップされた位置などの情報が含まれている。位置をメンバ変数で記憶しておき、onDrawでその位置に丸を表示させてみることにしよう。
まずは、メンバ変数を追加。
次に、eventから位置を取得して、メンバ変数に代入して記憶。
さらに、onDrawで丸を表示する。
これで、いけるはず。
エミュレーター起動、適当な位置でクリック。おや、クリック、クリック...
移動しない。画面の左上に丸が表示されている。これは多分、x=0,y=0の位置に表示されているな。イベントは確かに拾っているはずではあるが...
しょうがない。こういうときは、ひとつひとつ確認していくしかない。まずは、イベントが発生しているかどうか。onTouchEventが呼び出されているかどうかをまず確認する。
しかし、どうやって確認するか...
Log
普通のJavaアプリとか、アプレットなら、System.out.printlnで標準出力にデバッグ用の出力をしてしまうのが手っ取り早い。しかし、Androidには標準出力なんてあるのか?
出力できたとしても、エミュレーターから取ってこれるものなのか...
実は、Androidアプリでは、android.util.Logでログ出力することができる。
Logクラスには、ログレベルごとに出力メソッドが用意されている。Log.dならデバッグレベルのログを出力することができる。Log.eならエラーレベルのログ。詳細は、Logのドキュメントを参照して欲しい。
出力したログは、エミュレーター実行時なら、eclipseのLogCatビューに表示される(実機でもUSBで接続していればLogCatビューに表示される)。
まぁ、とりあえずやってみるべし。
Logという名前のクラスは結構いろんなパッケージに含まれていそうなので、パッケージ名まで書いている。こうしている例が多かったので。android.utilのLogしか使わない。というのであれば、import android.util.Logとしてインポートして、Log.dとだけ書いてもOKだと思う。
Log.dに渡している引数はふたつ。最初の文字列はタグ。次の文字列が出力内容。ここでは、位置情報を出力してみた。
では、実行してみよう。
デフォルトでLogCatビューが表示されていると思うが、表示されていなかったらLogCatビューを表示する。「ウインドウ」メニュー、「ビューの表示」、「LogCat」を選択すれば表示できる。
LogCatビューの表示レベルをdebug以上に変更しておく(verboseはdebug以上なのでそのままでOK)。debugレベルのログを出力しているのだから、下の設定になっていると表示されない。
ビューをタップ(エミュレーターだからマウスでクリック)するとLogCatに座標値が表示された。ということは、イベントはちゃんと取れている。
となると、問題は、描画の方か。
しかし、丸は表示されているが...
しょうがないので、onDrawにもログ出力を追加。
これで、再度実行してみると...
どうもonDrawが呼び出されていないことがわかった。
invalidate
まぁ、種を明かすと、invalidateをしていなかったから。多くのGUIシステムがそうであるように、AndroidのViewも書き換えが必要なときだけ、onDrawが呼び出される。丸の表示位置を変更したかったら、onDrawを呼び出してもらわないといけないのだが、Viewの方は更新が必要なことを知らないので、onDrawが呼び出されず表示が変わらない。
Viewに再描画が必要であることを通知するのが、invalidate。onTouchEventで表示位置を変更したら、invalidateメソッドを呼び出して、再描画を依頼すればOK。
これで、タップ中は丸がついてくるようになる。
関連記事
サイト内を検索
正確な用語は、「タップ」じゃなくて、「タッチ」みたいだが、「タッチ」だと微妙にエッチなのでタップで行くことにする。
でもって、タップされたかどうか、またその位置は、onTouchEventメソッドをオーバーライドすることで取得できる。
このメソッドは、Activity、Viewの両方にある。自前のビューを作成している場合は、Viewの方にonTouchEventを作成する。
public class HelloAndroidView extends View { @Override public boolean onTouchEvent(MotionEvent event) { return true; } }
これで、タップするとイベントが発生し、onTouchEventが呼び出される。
onTouchEventに渡ってくるMotionEventオブジェクトに、タップされた位置などの情報が含まれている。位置をメンバ変数で記憶しておき、onDrawでその位置に丸を表示させてみることにしよう。
まずは、メンバ変数を追加。
public class HelloAndroidView extends View { private float x, y; // タップされた位置を記憶 @Override public boolean onTouchEvent(MotionEvent event) { return true; } }
次に、eventから位置を取得して、メンバ変数に代入して記憶。
public class HelloAndroidView extends View { private float x, y; // タップされた位置を記憶 @Override public boolean onTouchEvent(MotionEvent event) { x = event.getX(); y = event.getY(); return true; } }
さらに、onDrawで丸を表示する。
public class HelloAndroidView extends View { private float x, y; // タップされた位置を記憶 protected void onDraw(Canvas canvas){ Paint paint = new Paint(); paint.setColor(Color.WHITE); canvas.drawText("好きな文字書いてね", 20, 30, paint); // 丸を表示 canvas.drawCircle(x, y, 10, paint); } @Override public boolean onTouchEvent(MotionEvent event) { x = event.getX(); y = event.getY(); return true; } }
これで、いけるはず。
エミュレーター起動、適当な位置でクリック。おや、クリック、クリック...
移動しない。画面の左上に丸が表示されている。これは多分、x=0,y=0の位置に表示されているな。イベントは確かに拾っているはずではあるが...
しょうがない。こういうときは、ひとつひとつ確認していくしかない。まずは、イベントが発生しているかどうか。onTouchEventが呼び出されているかどうかをまず確認する。
しかし、どうやって確認するか...
Log
普通のJavaアプリとか、アプレットなら、System.out.printlnで標準出力にデバッグ用の出力をしてしまうのが手っ取り早い。しかし、Androidには標準出力なんてあるのか?
出力できたとしても、エミュレーターから取ってこれるものなのか...
実は、Androidアプリでは、android.util.Logでログ出力することができる。
Logクラスには、ログレベルごとに出力メソッドが用意されている。Log.dならデバッグレベルのログを出力することができる。Log.eならエラーレベルのログ。詳細は、Logのドキュメントを参照して欲しい。
出力したログは、エミュレーター実行時なら、eclipseのLogCatビューに表示される(実機でもUSBで接続していればLogCatビューに表示される)。
まぁ、とりあえずやってみるべし。
public class HelloAndroidView extends View { @Override public boolean onTouchEvent(MotionEvent event) { x = event.getX(); y = event.getY(); // debugレベルでログ出力 android.util.Log.d("onTouchEvent", "x=" + x + " y=" + y); return true; } }
Logという名前のクラスは結構いろんなパッケージに含まれていそうなので、パッケージ名まで書いている。こうしている例が多かったので。android.utilのLogしか使わない。というのであれば、import android.util.Logとしてインポートして、Log.dとだけ書いてもOKだと思う。
Log.dに渡している引数はふたつ。最初の文字列はタグ。次の文字列が出力内容。ここでは、位置情報を出力してみた。
では、実行してみよう。
デフォルトでLogCatビューが表示されていると思うが、表示されていなかったらLogCatビューを表示する。「ウインドウ」メニュー、「ビューの表示」、「LogCat」を選択すれば表示できる。
LogCatビューの表示レベルをdebug以上に変更しておく(verboseはdebug以上なのでそのままでOK)。debugレベルのログを出力しているのだから、下の設定になっていると表示されない。
ビューをタップ(エミュレーターだからマウスでクリック)するとLogCatに座標値が表示された。ということは、イベントはちゃんと取れている。
となると、問題は、描画の方か。
しかし、丸は表示されているが...
しょうがないので、onDrawにもログ出力を追加。
protected void onDraw(Canvas canvas){ Paint paint = new Paint(); paint.setColor(Color.WHITE); canvas.drawText("好きな文字書いてね", 20, 30, paint); // ここにもログ出力を追加 android.util.Log.d("onDraw", "x=" + x + " y=" + y); canvas.drawCircle(x, y, 10, paint); } }
これで、再度実行してみると...
どうもonDrawが呼び出されていないことがわかった。
invalidate
まぁ、種を明かすと、invalidateをしていなかったから。多くのGUIシステムがそうであるように、AndroidのViewも書き換えが必要なときだけ、onDrawが呼び出される。丸の表示位置を変更したかったら、onDrawを呼び出してもらわないといけないのだが、Viewの方は更新が必要なことを知らないので、onDrawが呼び出されず表示が変わらない。
Viewに再描画が必要であることを通知するのが、invalidate。onTouchEventで表示位置を変更したら、invalidateメソッドを呼び出して、再描画を依頼すればOK。
public class HelloAndroidView extends View { @Override public boolean onTouchEvent(MotionEvent event) { x = event.getX(); y = event.getY(); android.util.Log.d("onTouchEvent", "x=" + x + " y=" + y); invalidate(); // 再表示が必要と通知する return true; } }
これで、タップ中は丸がついてくるようになる。
関連記事
サイト内を検索
2012-01-23 11:12
nice!(0)
コメント(0)
Copyright Atsushi Asai Google+朝井淳
[データベースの気持ちがわかる]SQLはじめの一歩 (WEB+DB PRESS plus)
- 作者: 朝井 淳
- 出版社/メーカー: 技術評論社
- 発売日: 2015/03/03
- メディア: 単行本(ソフトカバー)
Access クエリ 徹底活用ガイド ~仕事の現場で即使える
- 作者: 朝井 淳
- 出版社/メーカー: 技術評論社
- 発売日: 2018/05/25
- メディア: 大型本
コメント 0