2015年3月22日日曜日

Canvasクラスを制すものは描画を制す

AndroidはViewを描写をするときonDraw(Canvas canvas)メソッドで行っている
この引数のCanvasクラスは描画するための最小単位のクラスで、こいつでテキストだしたり、画像出したりしてる。android1.0から存在する大先輩クラス
今ではほとんどCanvasを意識せずViewの組み合わせによりUI構築を行うが、結局は各ViewのonDraw()で描写してるだけに過ぎない。ゆえにImageView、TextView、ListViewなどのViewを継承してるクラスのonDraw()をオーバーライドさせてやれば何でも描画できる!
てことでonDraw時のCanvasを制御する方法をまとめる
 文字の逆さ表示(TextViewのOverride)
やり方はCanvasを回転させて逆さにする。
Canvas# rotate()メソッドに回転方向、回転軸x、yを引数にして回転させる
回転軸は設定しないと、Viewの左上が回転軸になる。Viewの中心で回転させるので、横幅、縦幅の半分が回転軸
  1. /** 逆向き表示TextView */
  2. TextView textView1 = new TextView(this) {
  3. @Override
  4. public void onDraw(Canvas canvas) {
  5. canvas.save();
  6. canvas.rotate(180, getWidth() / 2, getHeight() / 2);
  7. super.onDraw(canvas);
  8. canvas.restore();
  9. }
  10. };
 文字の反転(TextViewのOverride)
やり方はCanvasの倍率を変更するメソッドで倍率をx軸を-1倍にする。
そうすると、X軸に対し、線対称に表示される
  1. /** 反転表示TextView */
  2. TextView textView4 = new TextView(this) {
  3. @Override
  4. public void onDraw(Canvas canvas) {
  5. canvas.save();
  6. canvas.scale(-1, 1);
  7. canvas.translate(-getWidth(), 0);
  8. super.onDraw(canvas);
  9. canvas.restore();
  10. }
  11. };
 影付き文字(TextViewのOverride)
影付けるにはCanvasの文字を描写するメソッドを使い、少しずれた位置に表示文字色より、薄い色で文字を描く
  1. /** 影付きTextView */
  2. TextView textView2 = new TextView(this) {
  3. Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
  4. @Override
  5. public void onDraw(Canvas canvas) {
  6. canvas.save();
  7. // 影の部分を先に描いてその上にほんとの文字を描く
  8. // 色の設定。本物の色を取ってきて、RGBに加算して色を足す
  9. p.setColor(getTextColors().getDefaultColor() | 0x00AFAFAF);
  10. // 文字のサイズを合わせる
  11. p.setTextSize(getTextSize());
  12. // 表示文字を合わせる
  13. String text = getText().toString();
  14. // 文字の表示位置調整。文字の高さ、マージンとか計算
  15. FontMetrics fm = p.getFontMetrics();
  16. float size = (fm.descent - fm.ascent);
  17. float margin = (getHeight() - size) / 2;
  18. canvas.drawText(text, 0, margin + getTextSize(), p);
  19. // 表示位置のずれ具合調整。だいたい5とか10くらい
  20. int dx = 5;
  21. canvas.drawText(text, 0 + dx, margin + getTextSize() + dx, p);
  22. canvas.restore();
  23. // 通常描写
  24. super.onDraw(canvas);
  25. }
  26. };
 スクロールアニメーション(TextViewのOverride)
Handler使って描画時間を調整しつつ、Canvasを平行移動させていくことで文字をずらしていく。
Handlerでスレッド止めたりするのキューたまりすぎないか心配なので、Threadとかで時間管理した方がいい気がする
  1. /** スクロールアニメーションTextView. */
  2. TextView textView3 = new TextView(this) {
  3. Point point = new Point();
  4. Handler handler = new Handler();
  5. Runnable runnable = new Runnable() { public void run() {
  6. // 10m秒このスレッドの時間を止める。その後強制描写メソッドで、onDraw()を呼ぶ
  7. try {Thread.sleep(10);} catch (InterruptedException e) {}
  8. invalidate();}
  9. };
  10. @Override
  11. public void onDraw(Canvas canvas) {
  12. canvas.save();
  13. // 結構ややこしい計算だけど、幅の2倍移動するので、移動式がこんな感じ
  14. canvas.translate(point.x + getWidth(), 0);
  15. super.onDraw(canvas);
  16. canvas.restore();
  17. // 座標を3ずらして表示。表示幅の2倍より大きくなったらリセット
  18. point.x = (point.x -3) % (getWidth() * 2);
  19. handler.post(runnable);
  20. }
  21. };
 角度を変えた画像の重ね合わせ(ImageViewのOverride)
この画像を回転させながら重ね合わせて、扇風機の羽を作る
文字反転と同じようにCanvasをView中心で回転させて、onDraw()を何度も呼ぶ。
  1. /** 重ね合わせImageView. */
  2. ImageView imageView = new ImageView(this) {
  3. @Override
  4. public void onDraw(Canvas canvas) {
  5. canvas.save();
  6. // 回転軸の決定
  7. PointF axis = new PointF(getWidth() / 2, getHeight() / 2);
  8. super.onDraw(canvas);
  9. canvas.rotate(90, axis.x, axis.y);
  10. super.onDraw(canvas);
  11. canvas.rotate(180, axis.x, axis.y);
  12. super.onDraw(canvas);
  13. canvas.rotate(270, axis.x, axis.y);
  14. super.onDraw(canvas);
  15. canvas.restore();
  16. }
  17. };
こんな感じで簡単にViewの編集が行える

0 件のコメント:

コメントを投稿