5-3 図形の描画 (1)図形を表示する手順 ①実画面に表示するクラスを作成する。 5-3 図形の描画 (1)図形を表示する手順 ①実画面に表示するクラスを作成する。 ②ActivityクラスのonCreate の後で実画面に表示するクラスを指定する。 【例】 public void onCreate(Bundle savedInstanceState) { //親クラスのonCreate処理を行う。 super.onCreate(savedInstanceState); //初期状態のままだとタイトルが表示されるのでこれを消す。 requestWindowFeature(Window.FEATURE_NO_TITLE); //実画面に表示するクラスをGraphicsViewとする。 setContentView(new GraphicsView(this)); }
(2)使用するメソッド A. onCreate void onCreate(Bundle bundle) 【機能】 アプリ起動時呼出し 呼び出されたら、まず最初に親クラスのonCreate 処理を行う必要がある。 super.onCreate(bundle); 【引数】bundle : 呼出し時に渡されるデータ
void reqestWindow(int ID) 【機能】ウィンドウの特徴IDの設定 【引数】 ID : 特徴ID B. reqestWindow void reqestWindow(int ID) 【機能】ウィンドウの特徴IDの設定 【引数】 ID : 特徴ID 特徴ID 概要 Window.FEATURE_ACTION_BAR アクションバー Window.FEATURE_ACTION_BAR_OVERLAY コンテンツをオーバーレイするアクションバー Window.FEATURE_ACTION_MODE_OVERLAY 表示スペースが存在しないとき、コンテンツの オーバーレイを許可するアクションバー Window.FEATURE_CONTEXT_MENU コンテキストメニュー Window.FEATURE_CUSTOM_TITLE カスタムタイトル Window.FEATURE_INDETERMINATE_PROGRESS 不確定プログレス Window.FEATURE_LEFT_ICON 左アイコン Window.FEATURE_NO_TITLE タイトルなし Window.FEATURE_OPTION_PANEL オプションパネル Window.FEATURE_PROGRESS プログレス Window.FEATURE_RIGHT_ICON 右アイコン
C. setContentsView void setContentView(View view) 【機能】実画面に表示するViewクラスを指定 本例では、描画を行うクラスを指定指定している。 【引数】view : ビュー
D. setAntiAlias void setAntiArias(boolean antiarias) 【機能】アンチエイリアス(文字や線を滑らかにする処理)を有効にするかどうかを設定。 【引数】 antiarias : アンチエイリアスの有効/無効
図形を表示するには、Paintクラスのメソッドを用いて、 線幅や描画スタイルを指定する必要がある。 E. 線幅、描画スタイルの指定 図形を表示するには、Paintクラスのメソッドを用いて、 線幅や描画スタイルを指定する必要がある。 void setStrokeWidth(float width) 【機能】線の太さの指定 【引数】width : 線の太さ void setStyle(Paint.Style style) 【機能】描画スタイル 【引数】style: スタイル style 概要 Paint.Style.FILL 塗りつぶし Paint.Style.FILL_AND_STROKE 塗りつぶし+ライン Paint.Style.STROKE ライン
F. 色の指定 [Paintクラス] void setColor(int color) 【機能】色の指定 【引数】color : 透明度・赤・緑・青の16進数で指定 [Colorクラス] void rgb(int r, int g, int, b)) 【機能】RGBで色を指定。【返却値】色の値 【引数】r: 赤,g: 緑,b: 青 (r, g, bは0~255) void argb(int a, int r, int g, int, b)) 【引数】a: 透明度(0~255),r,g,bはrgbと同じ
void drawLine(int x0, inty0,int x1,int x2,Paint paint) 【機能】線分の描画 G. 線分の描画 [Canvasクラス] void drawLine(int x0, inty0,int x1,int x2,Paint paint) 【機能】線分の描画 【引数】 x0 : 始点のX座標 y0 : 始点のY座標 x1 : 終点のX座標 y1 : 終点のY座標 paint : 描画オブジェクト 始点(x0, y0) 終点(x1, y1)
void drawPath(Path path, Paint paint) 【機能】複合図形(path)の描画 [Canvasクラス] void drawPath(Path path, Paint paint) 【機能】複合図形(path)の描画 【引数】 path : パス情報(複合図形の情報) paint : 描画オブジェクト [Pathクラス]pathを使って連続線分 void moveTo(float x, float y) 【機能】連続線分の開始座標の指定 【引数】 x : X座標, y : Y座標 void lineTo(float x, float y) 【機能】終点からの線分の追加 始点(x0, y0) 頂点(x1, y1) 頂点(x2, y2) 頂点(x3, y3)
void drawRect(Rect rect, Paint paint) 【機能】矩形(rect)の描画 【引数】 rect : 矩形情報 [Canvasクラス] void drawRect(Rect rect, Paint paint) 【機能】矩形(rect)の描画 【引数】 rect : 矩形情報 paint : 描画オブジェクト [Rectクラス] Rect(int left, int top,int right, int bottom) 【機能】Rectクラスのコンストラクタ 【引数】 left : 矩形の左上X座標 top : 矩形の左上Y座標 right : 矩形の右下X座標 bottom : 矩形の右下Y座標 left right top bottom
void drawRoundRect(RectF rectf, float rx, float ry, Paint paint) J. 角丸矩形描画 [Canvasクラス] void drawRoundRect(RectF rectf, float rx, float ry, Paint paint) 【機能】各丸矩形の描画(rx = ry = 0にすると矩形になる) 【引数】 rectf : 浮動小数点座標による矩形情報 rx, ry : コーナーのX半径,Y半径 paint : 描画オブジェクト [RectFクラス] RectF(float left, float top,float right, float bottom) 【機能】Rectクラスのコンストラクタ 【引数】 left : 矩形の左上X座標 top : 矩形の左上Y座標 right : 矩形の右下X座標 bottom : 矩形の右下Y座標 left right rx top ry bottom
void drawCircle(float cx, float cy, float radius,Paint paint) 【機能】円の描画 K. 円の描画 [Canvasクラス] void drawCircle(float cx, float cy, float radius,Paint paint) 【機能】円の描画 【引数】cx : 中心点のX座標 cy : 中心点のY座標 radius : 半径 paint : 描画オブジェクト cx radius cy 中心点
void drawOval(RectF rectf, Paint paint) 【機能】各丸矩形の描画 [Canvasクラス] void drawOval(RectF rectf, Paint paint) 【機能】各丸矩形の描画 【引数】 rectf : 浮動小数点座標による矩形情報 rx, ry : コーナーのX半径,Y半径 paint : 描画オブジェクト [RectFクラス]については「J. 各丸矩形の描画」参照 (高さと幅を同じにすると円描画となる) left right top bottom
(3)Javaクラスの追加 A. Javaファイルのコピーと貼り付け (プロジェクト名:DrawFigure) ①「~Activity.java」 を選択して、右ボタン をクリック。 ②プルダウンメニュー から、「コピー」を選択 ③プルダウンメニュー から、「貼り付け」を選択 ② ③ ①右ボタンクリック
B. 新規ファイル名の指定 ①「名前の競合」画面で、新規ファイル名を入力して「OK」ボタンをクリックすると、新規ファイルが追加される。
(4)プログラムの入力 A. GraphicsView.java(その1) package jp.eclipse; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.graphics.Rect; import android.graphics.RectF; import android.view.View; //図形描画 public class GraphicsView extends View { //コンストラクタ public GraphicsView(Context context) { super(context); setBackgroundColor(Color.WHITE); } //描画 protected void onDraw(Canvas canvas){ //描画オブジェクト生成 Paint p = new Paint(); p.setAntiAlias(true); (4)プログラムの入力 A. GraphicsView.java(その1)
GraphicsView.java(その2) //線分描画 p.setStrokeWidth(1); p.setStyle(Paint.Style.STROKE); p.setColor(Color.argb(255,255, 0, 0)); canvas.drawLine(50, 10, 50, 90, p); //連続線分描画 p.setColor(Color.argb(255,0, 255, 0)); Path path = new Path(); path.moveTo(110,10); path.lineTo(170, 20); path.lineTo(130, 50); path.lineTo(190, 60); canvas.drawPath(path, p); //矩形描画 p.setColor(Color.argb(255, 0, 0, 255)); canvas.drawRect(new Rect(10,100,90,180),p); //矩形塗り潰し p.setStyle(Paint.Style.FILL); canvas.drawRect(new Rect(110,100,190,180),p); GraphicsView.java(その2)
GraphicsView.java(その3) //角丸矩形描画 p.setStyle(Paint.Style.STROKE); p.setColor(Color.argb(255, 0, 255, 0)); canvas.drawRoundRect(new RectF(10,200,90,280), 10, 10, p); //角丸矩形塗り潰し p.setStyle(Paint.Style.FILL); canvas.drawRoundRect(new RectF(110,200,190,280), 10, 10, p); //円描画 p.setColor(Color.argb(255, 0, 255, 255)); canvas.drawCircle(50, 340, 40, p); //円塗り潰し canvas.drawCircle(150, 340, 40, p); } GraphicsView.java(その3)
B. DrawFigureActivity.java] package jp.eclipse; import android.app.Activity; import android.os.Bundle; import android.view.Window; public class DrawFigureActivity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(new GraphicsView(this)); }
(5)実行例 Java 1.6で実行
(6)再描画 A.再描画を行うには 何らかのイベントが発生したとき、再描画を行うには、 Invalidate() (android.view.Viewクラス) を呼び出して、現ビューを無効にすることによって再描画する。 【例】画面にタッチしたとき呼び出されるメソッド onTouchEvent(MotionEvent e)
B. プログラム例(その1) package jp.eclips; import android.app.Activity; import android.os.Bundle; import android.content.*; import android.graphics.*; import android.view.*; import android.widget.*; public class TouchVActivity extends Activity { /** Called when the activity is first created. */ TouchView tv; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); LinearLayout layout=new LinearLayout(this); setContentView(layout); tv=new TouchView(this); layout.addView(tv); }
プログラム例(その2) class TouchView extends View{ float x,y; //コンストラクタ public TouchView(Context context) { super(context); x = -10; y = -10; } // 画面にタッチしたときのメソッド public boolean onTouchEvent(MotionEvent e){ x = e.getX(); y = e.getY();//タッチしたときの位置 this.invalidate();//再描画 return true; protected void onDraw(Canvas canvas){ super.onDraw(canvas); Paint paint=new Paint(); paint.setColor(Color.YELLOW); paint.setStyle(Paint.Style.FILL); canvas.drawCircle(x, y, 10, paint);
C. 実行例 画面上にタッチすると円形が移動する
(7)ランダムに描画する A. 乱数の発生 乱数を発生させるには java.util.Randomクラス を使い、nextInt(int R)を呼び出すと、 0 以上 R 未満の整数の乱数が得られる。 ランダムな位置、色を発生させて描画するプログラム例を示す。
B. プログラム例(その1) package jp.eclipse; import java.util.*; import android.app.Activity; import android.os.Bundle; import android.content.*; import android.graphics.*; import android.view.View; import android.widget.*; public class RandomVActivity extends Activity { /** Called when the activity is first created. */ static final int num=50; Random rn = new Random(); RandomView rv; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); LinearLayout LL=new LinearLayout(this); setContentView(LL); rv=new RandomView(this); LL.addView(rv); } B. プログラム例(その1)
B. プログラム例(その2) class RandomView extends View{ ArrayList <Ball> b1; public RandomView(Context context) { super(context); b1=new ArrayList<Ball>(); for (int i=0;i<num;i++){ b1.add(new Ball(460,762)); } protected void onDraw(Canvas canvas){ super.onDraw(canvas); Paint p =new Paint(); for (int i=0; i<num;i++){ Ball b=b1.get(i); p.setColor(Color.rgb(b.r, b.g, b.b)); p.setStyle(Paint.Style.FILL); canvas.drawCircle(b.x, b.y, 10,p);
B. プログラム例(その3) class Ball{ public int x, y, r, g, b; public Ball(int W, int H){ x=rn.nextInt(W); y=rn.nextInt(H); r=rn.nextInt(256); g=rn.nextInt(256); }
C. 実行例 ランダムな位置にランダムな色の円が描かれている
(8)ビューをめくる A. めくる動画の作成例 ① ランダムに円を書いた3つのビューを用意する。 ① ランダムに円を書いた3つのビューを用意する。 ② showNext メソッドで次のビューへ、showPrevious メソッドで前のビューへ戻る。 ③ ViewFlipper でビューをめくる際のアニメーションを設定する。 ・setInAnimation : 入るときのビューアニメーション ・setOutAnimation : 出るときのビューアニメーション ④ YranlateAnimation クラスを使うと、移動アニメーションを作成することができる。 【指定方法】 TranslateAnimation inanim = new TranslateAnimation(移動前のX座標, 移動後のX座標, 移動前のY座標, 移動後のY座標);
B. 関連するクラス 【android.widget.ViewFlipper クラス】 ViewFlipper ViewFlipperオブジェクトを作成する。 【android.widget.ViewAnimation クラス】 setInAnimation(Animation anim) 画面に表示されるときに再生されるアニメーションの指定 setOutAnimation(Animation anim) 画面に表示されるときに再生されるアニメーションの指定 void showNext() 次のビューに移動 void showPrevious() 前のビューに移動 【android.view.animation.TranslateAnimation クラス】 translateAnimation(float fxd, float txd, float fyd, float tyd) 指定した移動アニメーションを作成 fxd 移動前X座標 txd 移動後Y座標 fyd 移動前Y座標 tyd 移動後Y座標
C. プログラム例(その1) package jp.eclipse; import java.util.*; import android.app.Activity; import android.os.*; import android.content.*; import android.graphics.*; import android.view.*; import android.view.View.OnTouchListener; import android.view.animation.*; import android.widget.*; public class RandomVActivity extends Activity { /** Called when the activity is first created. */ static final int num=50; ViewFlipper vf; RandomView[] rv=new RandomView[3];//ビューを3つ用意 LinearLayout[] LL=new LinearLayout[3]; float x; Random rn = new Random(); @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); LinearLayout LLp = new LinearLayout(this); setContentView(LLp); C. プログラム例(その1)
プログラム例(その2) vf =new ViewFlipper(this); for (int i=0;i<rv.length;i++){ LL[i]=new LinearLayout(this); rv[i]=new RandomView(this); //円を描くビュー LL[i].addView(rv[i]); vf.addView(LL[i]); //ViewFlipperに追加 } LLp.addView(vf); setContentView(LLp); LLp.setOnTouchListener(new FlipTouchListener()); class FlipTouchListener implements OnTouchListener{ public boolean onTouch(View v, MotionEvent e) { int ev=e.getAction(); if(ev==MotionEvent.ACTION_DOWN) x=e.getX(); else if(ev==MotionEvent.ACTION_UP){ if(x>e.getX()){// 右方向に進むようめくった場合 TranslateAnimation inAnim = //入ってくるアニメーション new TranslateAnimation(rv[0].getWidth(),0,0,0); TranslateAnimation outAnim= //出ていくアニメーション new TranslateAnimation(0,-rv[0].getWidth(),0,0); プログラム例(その2)
プログラム例(その3) outAnim.setDuration(1000); //再生時間を1000ミリ秒とする vf.setInAnimation(inAnim); //画面に表示されるときのアニメ vf.setInAnimation(outAnim); //画面から消えるときのアニメ vf.showNext(); //次ページに進む } else if(x<e.getX()){// 左方向に進むようめくった場合 TranslateAnimation inAnim= //入ってくるアニメーション new TranslateAnimation(-rv[0].getWidth(),0,0,0); TranslateAnimation outAnim= //出ていくアニメーション new TranslateAnimation(0,rv[0].getWidth(),0,0); outAnim.setDuration(1000); vf.setInAnimation(inAnim); vf.setInAnimation(outAnim); vf.showPrevious(); //前ページに戻る } return true;
プログラム例(その4) class RandomView extends View{ ArrayList<Ball> b1; public RandomView(Context context) { super(context); b1=new ArrayList<Ball>(); for (int i=0;i<num;i++) b1.add(new Ball(460,762)); } protected void onDraw(Canvas canvas){ super.onDraw(canvas); Paint p =new Paint(); for (int i=0; i<num;i++){ Ball b=b1.get(i); p.setColor(Color.rgb(b.r, b.g, b.b)); p.setStyle(Paint.Style.FILL); canvas.drawCircle(b.x, b.y, 10,p); class Ball{ public int x, y, r, g, b; public Ball(int W, int H){ x=rn.nextInt(W); y=rn.nextInt(H); r=rn.nextInt(256); g=rn.nextInt(256); g=rn.nextInt(256); プログラム例(その4)
D. 実行例 左方向にめくったとき 右方向にめくったとき
(9)絵を動かす A. ボールの反射動画の作成例 ① メインのActivityに Runnable インターフェースを実装する。 ② 画面をフルスクリーンにしてタイトルを消す。 ③ 遅延時間を指定してrunメソッドを呼び出す。 ④ 呼び出されるrunメソッドでは、画面外にはみ出したとき移動量の符号を反転させるようにし、その後、ビューを無効にする(invalidate())ことによって再描画を行う。 ⑤ 描画を行うクラスを作成する。
B. 関連するクラス 【android.os.Handler クラス】 Handler() ハンドラを作成。 boolean postDelayed 実行を指定時間(dm)だけ遅延する (Runnable r, long dm) void removeCallbacks() 実行待ちの処理を取り除く。 【android.app.Activity クラス】 Object getSystemService(String name) システムサービスを取得。 Window getWindow() ウィンドウを取得。 boolean requestWindowFeature(int id) フィーチャを指定。 【android.view.Window クラス】 void addFlags(int f) フラグを追加。 【android.view.WindowManager インターフェース】 Display getDefaultDisplay() ディスプレイを取得。
C. プログラム例(その1) package jp.eclipse; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.content.*; import android.graphics.*; import android.view.*; import android.widget.*; // Runnableインターフェースを実装する(inplements Runnableを追加) public class BallMoveActivity extends Activity implements Runnable { /** Called when the activity is first created. */ ScreenView sv; Handler hn; float x, y, dx, dy; float maxLeft, maxBottom; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //画面をフルスクリーンにする getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); //タイトル消去 requestWindowFeature(Window.FEATURE_NO_TITLE); LinearLayout ll = new LinearLayout(this); setContentView(ll);
C. プログラム例(その2) //画面範囲の設定 WindowManager wm = (WindowManager)getSystemService(WINDOW_SERVICE); Display dp = wm.getDefaultDisplay(); maxLeft = dp.getWidth() -10; maxBottom = dp.getHeight()-10; hn = new Handler(); hn.postDelayed(this, 5); // Runメソッドを遅らせて実行 sv = new ScreenView(this); ll.addView(sv); //ビューの追加 } public void run() { if(x<=10 || x>=maxLeft) dx = -dx;//反射 if(y<=10 || y>=maxBottom) dy = -dy; x+=dx; y+=dy; sv.invalidate(); //移動と再描画 hn.postDelayed(this, 5);//遅らせて繰り返す public void onDestroy() { // 画面破棄のとき解除 super.onDestroy(); hn.removeCallbacks(this);
C. プログラム例(その3) class ScreenView extends View { public ScreenView(Context cn) { // 初期設定 super(cn); x = 100; y = 100; dx = 5; dy = 5; } protected void onDraw(Canvas cs) { super.onDraw(cs); Paint p = new Paint(); p.setColor(Color.YELLOW);p.setStyle(Paint.Style.FILL); cs.drawCircle(x, y, 10, p);
D. 実行例 画面の境目で反射する
(10)座標変換 A. 手順 長方形やテキストを斜めに描くには、座標軸の変換を行う。 ① 以下のメソッドを使ってキャンバスの座標変換を行う。 [Canvas].translate(x,y) 平行移動 [Canvas].scale(sx,sy) スケーリング [Canvas].rotate(degree) 回転 ③ キャンバスにdrawRect(長方形)やdrawText(テキスト)を行う。 ④ 元の状態に戻すには、以下のメソッドを用いる。 [Canvas].save() 保存 [Canvas].restore() リストア
B. プログラム例(その1) package jp.eclipse.coord; import java.util.*; import android.app.*; import android.os.*; import android.content.*; import android.graphics.*; import android.view.*; import android.view.View.*; import android.widget.*; public class CoordActivity extends Activity { /** Called when the activity is first created. */ CoordView cv; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); LinearLayout LL=new LinearLayout(this); setContentView(LL); cv=new CoordView(this); LL.addView(cv); }
プログラム例(その2) class CoordView extends View{ public CoordView(Context context) { super(context);} protected void onDraw(Canvas cs){ super.onDraw(cs); int w=cs.getWidth();int h=cs.getHeight(); int r = w / 3; cs.drawColor(Color.rgb(255,255,128)); cs.save(); // キャンバス保存 Paint p=new Paint(); p.setColor(Color.argb(50, 255, 0, 0)); cs.translate(w / 2,h/3-r); // 平行移動 for(int i=0; i<64;i++){ cs.scale(0.9F, 0.9F); cs.rotate(20f); // スケーリングと回転 cs.drawRect(new Rect(0,0,r,r), p); } cs.restore(); // キャンバス回復 p.setColor(Color.argb(50, 0, 0, 255)); cs.translate(w / 2,h/3+r); // 平行移動 cs.scale(0.9F, 0.9F); cs.rotate(20f); // スケーリングと回転
D. 実行例 スケーリング しながら 回転する図形