SurfaceViewは、
描画用のスレッドがアプリケーションのスレッドと独立しているため、ゲームなど定期的な描画が要求される場合に向いている。
なお、SurfaceViewはAPI Level1から利用できる。
試しに、適当なサンプルを作成してみる。
1.Activityは最初に生成されるものから変更なし
- package com.runpeta.android.angle;
-
- import android.app.Activity;
- import android.os.Bundle;
-
- public class RpAngleActivity extends Activity {
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- }
- }
package com.runpeta.android.angle;
import android.app.Activity;
import android.os.Bundle;
public class RpAngleActivity extends Activity {
// アクティビティ作成時に最初に呼ばれる
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
2.SurfaceViewのサブクラスを作り、線だけ描画する
- package com.runpeta.android.angle;
-
- import android.content.Context;
- import android.graphics.Canvas;
- import android.graphics.Color;
- import android.graphics.Paint;
- import android.util.AttributeSet;
- import android.view.SurfaceHolder;
- import android.view.SurfaceView;
-
- public class RpAngleSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
- public RpAngleSurfaceView(Context context) {
- super(context);
- getHolder().addCallback(this);
- }
- public RpAngleSurfaceView(Context context, AttributeSet attrs) {
- super(context, attrs);
- getHolder().addCallback(this);
- }
- public RpAngleSurfaceView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- getHolder().addCallback(this);
- }
- public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
-
- }
- public void surfaceCreated(SurfaceHolder holder) {
- doDraw();
- }
- public void surfaceDestroyed(SurfaceHolder holder) {
-
- }
- private void doDraw() {
-
- Canvas c = getHolder().lockCanvas();
- c.save();
-
-
- Paint p = new Paint();
- p.setColor(Color.BLACK);
- c.drawColor(Color.WHITE);
- c.drawLines(new float[]{20,20,60,60}, p);
-
-
- c.restore();
- getHolder().unlockCanvasAndPost(c);
- }
- }
package com.runpeta.android.angle;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class RpAngleSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
public RpAngleSurfaceView(Context context) {
super(context);
getHolder().addCallback(this);
}
public RpAngleSurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
getHolder().addCallback(this);
}
public RpAngleSurfaceView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
getHolder().addCallback(this);
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
public void surfaceCreated(SurfaceHolder holder) {
doDraw();
}
public void surfaceDestroyed(SurfaceHolder holder) {
}
private void doDraw() {
// キャンバスをロックする
Canvas c = getHolder().lockCanvas();
c.save();
// ここにCanvasに描画処理を書く
Paint p = new Paint();
p.setColor(Color.BLACK);
c.drawColor(Color.WHITE);
c.drawLines(new float[]{20,20,60,60}, p);
// キャンバスのロックを解除する
c.restore();
getHolder().unlockCanvasAndPost(c);
}
}
3.メインレイアウトに作成したSurfaceViewを追加します。
・id:surface (とりあえず)
・width:fill_parent
・height:fill_parent
これで線なるものが描画されているハズだ。
これは非常に分かりづらいサンプルになってしまった。
ゲームのように定期的に再描画を行ってみる。
さきほどの"onDraw"をタイマーで定期的に呼び出すために、"ScheduledExecutorService"を利用します。
こんな感じにしようできますので、(定期処理内容)で"onDraw"を呼びます。
-
- ScheduledExecutorService schedule;
- schedule = Executors.newSingleThreadScheduledExecutor();
- schedule.scheduleAtFixedRate(new Runnable(){
- public void run() {
-
-
- }
- }, 0, 100, TimeUnit.MILLISECONDS);
-
-
- schedule.shutdown();
// タイマーを開始する
ScheduledExecutorService schedule;
schedule = Executors.newSingleThreadScheduledExecutor();
schedule.scheduleAtFixedRate(new Runnable(){
public void run() {
//定期処理内容
}
}, 0, 100, TimeUnit.MILLISECONDS);
// タイマーを終了する
schedule.shutdown();
さきほどの線がアニメーションで伸び縮みするようにしてみます。
- package com.runpeta.android.angle;
-
- import java.util.concurrent.Executors;
- import java.util.concurrent.ScheduledExecutorService;
- import java.util.concurrent.TimeUnit;
-
- import android.content.Context;
- import android.graphics.Canvas;
- import android.graphics.Color;
- import android.graphics.Paint;
- import android.util.AttributeSet;
- import android.view.SurfaceHolder;
- import android.view.SurfaceView;
-
- public class RpAngleSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
- private ScheduledExecutorService mSchedule;
- private Runnable repeatDraw = new Runnable() {
- public void run() {
- size += 5;
- if (size > 400) {
- size = 100;
- }
- doDraw();
- }
- };
- private int size = 100;
- public RpAngleSurfaceView(Context context) {
- super(context);
- getHolder().addCallback(this);
- }
- public RpAngleSurfaceView(Context context, AttributeSet attrs) {
- super(context, attrs);
- getHolder().addCallback(this);
- }
- public RpAngleSurfaceView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- getHolder().addCallback(this);
- }
- public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
-
- }
- public void surfaceCreated(SurfaceHolder holder) {
- doDraw();
- mSchedule = Executors.newSingleThreadScheduledExecutor();
- mSchedule.scheduleAtFixedRate(repeatDraw, 0, 100, TimeUnit.MILLISECONDS);
- }
- public void surfaceDestroyed(SurfaceHolder holder) {
- mSchedule.shutdown();
- mSchedule = null;
- }
- private void doDraw() {
-
- Canvas c = getHolder().lockCanvas();
- c.save();
-
-
- Paint p = new Paint();
- p.setColor(Color.BLACK);
- c.drawColor(Color.WHITE);
- c.drawLines(new float[]{20,20,size,size}, p);
-
-
- c.restore();
- getHolder().unlockCanvasAndPost(c);
- }
- }
package com.runpeta.android.angle;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class RpAngleSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
private ScheduledExecutorService mSchedule;
private Runnable repeatDraw = new Runnable() {
public void run() {
size += 5;
if (size > 400) {
size = 100;
}
doDraw();
}
};
private int size = 100;
public RpAngleSurfaceView(Context context) {
super(context);
getHolder().addCallback(this);
}
public RpAngleSurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
getHolder().addCallback(this);
}
public RpAngleSurfaceView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
getHolder().addCallback(this);
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
public void surfaceCreated(SurfaceHolder holder) {
doDraw();
mSchedule = Executors.newSingleThreadScheduledExecutor();
mSchedule.scheduleAtFixedRate(repeatDraw, 0, 100, TimeUnit.MILLISECONDS);
}
public void surfaceDestroyed(SurfaceHolder holder) {
mSchedule.shutdown();
mSchedule = null;
}
private void doDraw() {
// キャンバスをロックする
Canvas c = getHolder().lockCanvas();
c.save();
// ここにCanvasに描画処理を書く
Paint p = new Paint();
p.setColor(Color.BLACK);
c.drawColor(Color.WHITE);
c.drawLines(new float[]{20,20,size,size}, p);
// キャンバスのロックを解除する
c.restore();
getHolder().unlockCanvasAndPost(c);
}
}
こんな感じで描画ができることが分かったので、後はCanvasとPaintの使い方次第でいろいろ描画できます。