スキップしてメイン コンテンツに移動

Androidのアプリを はじめて作ってみる #6 SurfaceViewのCanvasをデバイスの幅に合わせて調整する

USBデバッグをしてみたら、エミュレータで試していた時よりサイズが小さくて、ちょっと残念な気持ちになりました。

そこで、デバイスのサイズに合わせてキャンバスサイズを調整するインプリをしてみようと思います。

ソースコード:https://github.com/et79/Game15
まとめページ:http://smallstepeveryday.blogspot.jp/p/android-15.html

SurfaceHolder.Callback を継承

SurfaceView作成時に、サイズ調整用の割合をきめるため、SurfaceHolder.Callback を継承します。

public class GameView extends SurfaceView implements SurfaceHolder.Callback {

コンストラクタで、サーフェースの情報を保持します。

getHolder.addCallback(this);

キャンバス上の表示に合わせる比率の算出

コールバック(surfaceCreated、surfaceDestroyed、surfaceChanged)を用意します。SurfaceHolder.Callback を継承した場合、これらのコードの記述が必要になります。

そして、surfaceCreatedにてプログラム上のサイズをキャンバス上の表示に合わせて拡大/縮小するための比率scaleを算出します。

他のコールバックは、現在のプログラムでは使用していません。

// サーフェースのコールバック
public void surfaceCreated(SurfaceHolder holder)
{
    // サイズ調整用の比率(縦横それぞれ)を取得
    float scaleX = getWidth() / (float)( gridWidth + gridOrg.x * 2 );
    float scaleY = getHeight() / (float)( gridWidth + gridOrg.y );

    // 比率の小さい方を採用
    scale = scaleX > scaleY ? scaleY : scaleX;
}
public void surfaceDestroyed(SurfaceHolder holder)
{
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h)
{
}

スケール変換をかけていきます

タッチされた座標に、スケールの変換をかけていきます。

@Override
public boolean onTouchEvent(MotionEvent event){
    int action = event.getAction();
    if(( action & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_UP)
    {
        // タッチ座標に、プログラム上座標への変換スケールをかける
        float touchedX = event.getX() / scale;
        float touchedY = event.getY() / scale;

変換スケールをかけた後は、いままでのプログラム内での座標系で扱えばOKです。ってか、こうやるんですね。なるほど。

描画するときも、変換スケールをかけます。これには、Canvasクラスのscaleメソッドを使います。

public void onDraw(Canvas canvas){

    // キャンバスサイズを、画面サイズに合わせて調整
    canvas.scale(scale, scale);

これで、うまくいくはずです。

うまくいきました!これまた、嬉しい。これなら、人に見せられます。

元のプログラムを左上を原点に考えて組んでいたから、これでうまくいきましたが、canvas.translateをして中心を動かすとかしないといけない場合もあるみたいですね。

わかるような、わからないような…。今は、そんな感じです。とりあえず、どんどん進めます。


参考

コメント

Amazon Affiliate