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
特徴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
B. reqestWindow
概要
アクションバー
コンテンツをオーバーレイするアクションバー
表示スペースが存在しないとき、コンテンツの
オーバーレイを許可するアクションバー
コンテキストメニュー
カスタムタイトル
不確定プログレス
左アイコン
タイトルなし
オプションパネル
プログレス
右アイコン
C. setContentsView
void setContentView(View view)
【機能】実画面に表示するViewクラスを指定
本例では、描画を行うクラスを指定指定している。
【引数】view : ビュー
D. setAntiAlias
void setAntiArias(boolean antiarias)
【機能】アンチエイリアス(文字や線を滑らかにする処
理)を有効にするかどうかを設定。
【引数】 antiarias : アンチエイリアスの有効/無効
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))
【機能】RGBで色を指定。【返却値】色の値
【引数】a: 透明度(0~255),r,g,bはrgbと同じ
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)
H. 連続線分の描画
[Canvasクラス]
void drawPath(Path path, Paint paint)
【機能】複合図形(path)の描画
【引数】path : パス情報(複合図形の情報)
paint : 描画オブジェクト
始点(x0, y0)
[Pathクラス]pathを使って連続線分
void moveTo(float x, float y)
【機能】連続線分の開始座標の指定
頂点(x1, y1)
【引数】x : X座標,
y : Y座標
void lineTo(float x, float y)
頂点(x2, y2)
【機能】終点からの線分の追加
【引数】x : X座標,
y : Y座標
頂点(x3, y3)
I. 矩形描画
[Canvasクラス]
void drawRect(Rect rect, Paint paint)
【機能】矩形(rect)の描画
【引数】rect : 矩形情報
paint : 描画オブジェクト
[Rectクラス]
Rect(int left, int top,int right, int bottom)
【機能】Rectクラスのコンストラクタ
left
【引数】left : 矩形の左上X座標
top
top
: 矩形の左上Y座標
right : 矩形の右下X座標
bottom : 矩形の右下Y座標
bottom
right
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
right
【引数】left : 矩形の左上X座標
rx
top
top
: 矩形の左上Y座標
ry
right : 矩形の右下X座標
bottom : 矩形の右下Y座標
bottom
K. 円の描画
[Canvasクラス]
void drawCircle(float cx, float cy, float radius,Paint
paint)
【機能】円の描画
【引数】cx
: 中心点のX座標
cy
: 中心点のY座標
radius : 半径
paint : 描画オブジェクト
cx
radius
cy
中心点
L. 楕円描画
[Canvasクラス]
void drawOval(RectF rectf, Paint paint)
【機能】各丸矩形の描画
【引数】rectf : 浮動小数点座標による矩形情報
rx, ry : コーナーのX半径,Y半径
paint : 描画オブジェクト
[RectFクラス]については「J. 各丸矩形の描画」参照
(高さと幅を同じにすると円描画となる)
left
top
bottom
right
(3)Javaクラスの追加
A. Javaファイルのコピーと貼り付け
(プロジェクト名:DrawFigure)
①「~Activity.java」
を選択して、右ボタン
をクリック。
②プルダウンメニュー
から、「コピー」を選択
③プルダウンメニュー
から、「貼り付け」を選択
②
③
①右ボタンクリック
B. 新規ファイル名の指定
①「名前の競合」画面で、新規ファイル名を入力して
「OK」ボタンをクリックすると、新規ファイルが追加
される。
package jp.eclipse;
import android.content.Context;
A.
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)プログラムの入力
GraphicsView.java(その1)
//線分描画
p.setStrokeWidth(1);
GraphicsView.java(その2)
p.setStyle(Paint.Style.STROKE);
p.setColor(Color.argb(255,255, 0, 0));
canvas.drawLine(50, 10, 50, 90, p);
//連続線分描画
p.setStyle(Paint.Style.STROKE);
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.setStyle(Paint.Style.STROKE);
p.setColor(Color.argb(255, 0, 0, 255));
canvas.drawRect(new Rect(10,100,90,180),p);
//矩形塗り潰し
p.setStyle(Paint.Style.FILL);
p.setColor(Color.argb(255, 0, 0, 255));
canvas.drawRect(new Rect(110,100,190,180),p);
//角丸矩形描画
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);
p.setColor(Color.argb(255, 0, 255, 0));
canvas.drawRoundRect(new RectF(110,200,190,280), 10, 10, p);
//円描画
p.setStyle(Paint.Style.STROKE);
p.setColor(Color.argb(255, 0, 255, 255));
canvas.drawCircle(50, 340, 40, p);
//円塗り潰し
p.setStyle(Paint.Style.FILL);
p.setColor(Color.argb(255, 0, 255, 255));
canvas.drawCircle(150, 340, 40, p);
}
}
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));
}
}
Java 1.6で実行
(5)実行例
(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 未満の整数の乱数が得られる。
ランダムな位置、色を発生させて描画するプログラム例を示す。
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);
g=rn.nextInt(256);
}
}
}
ランダムな位置にランダムな色の円が描かれている
C. 実行例
(8)ビューをめくる
A. めくる動画の作成例
① ランダムに円を書いた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座標
package jp.eclipse;
C. プログラム例(その1)
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);
vf =new ViewFlipper(this);
プログラム例(その2)
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);
プログラム例(その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;
}
}
class RandomView extends View{
プログラム例(その4)
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);
}
}
}
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);
setContentView(LL);
}
プログラム例(その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);
// 平行移動
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);
}
}
}
スケーリング
しながら
回転する図形
D. 実行例