たぼさんの部屋

いちょぼとのんびり

L002) SurfaceViewを複数インスタンス生成&移動

目的

複数のSurfaceViewを可動状態にして移動させる。
SurfaceView内でCircleを描画して移動させておく。

  • SurfaceViewそのもののOnTouchによる移動
  • CircleのOnTouchによる移動

構成

  • Main.java
    • extends Activity

MySurfaceViewをインスタンス
配列で複数起動
それぞれのSurfaceViewインスタンスにsetOnTouchListenerセット

  • MySurfaceView.java
    • extends SurfaceView
    • implements Runnable , SurfaceHolder.Callback

RunメソッドでdrawCircle
circleにsetOnTouchListenerセット

Main.java

/**
 * FIXME:動作が遅い(移動時に残像:背景黒い)
 * FIXME:SurfaceViewの上下重ね順が変わらない
 * FIXME:VIEWのサイズが取得できない(RelativeLayout.getWidth()=0が返る)
 * XXX:未実装=>MyCircle.classでの図形描画(色・サイズをランダム化)
 * XXX:未実装=>MyCircle.classのOnTouchListener
 * @date:2012/11/16 13:53
 */
package com.example.l002_relativl_surface_circle;

import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.Display;
import android.view.MotionEvent;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewGroup.MarginLayoutParams;
import android.view.WindowManager;
import android.widget.RelativeLayout;
import android.widget.TextView;
/**
 * 
 * @author kamogashiratsuyoshi
 *
 */
public class Main extends Activity {
	Context context;
	RelativeLayout base;
	TextView tv;
    final int quantity = 3;
	MySurfaceView[] surfaces;
	static int dispWidth;
	static int dispHeight;
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		// context
		context = getApplicationContext();
		base = new RelativeLayout(context);
		base.setBackgroundColor(Color.BLACK);
		setContentView(base);
		
        WindowManager wm = (WindowManager)getSystemService(WINDOW_SERVICE);
        // ディスプレイのインスタンス生成
        Display disp = wm.getDefaultDisplay();
        dispWidth = disp.getWidth();
        dispHeight = disp.getHeight();
//        Log.v("disp","width="+disp.getWidth());
//        Log.v("disp","height="+disp.getHeight());
        
        Log.v("base","width="+base.getWidth());
        
		// textView
		tv = new TextView(context);
		base.addView(tv);
		tv.setText("hoge");
		tv.setId(2);
		tv.setBackgroundColor(Color.RED);
		MarginLayoutParams tvParams = (MarginLayoutParams) tv.getLayoutParams();
		tvParams.leftMargin = 10;
		tv.setLayoutParams(tvParams);
		
		//surface
		// SurfaceView
		final SurfaceView surface = new SurfaceView(context);
		base.addView(surface);
		surface.setId(3);
		MarginLayoutParams surfaceParams = (MarginLayoutParams) surface
				.getLayoutParams();
		surfaceParams.topMargin = 150;
		surfaceParams.leftMargin = 50;
		surfaceParams.width = 100;
		surfaceParams.height = 100;
		surface.setLayoutParams(surfaceParams);
		
        //複数のSurfaceView


        //SurfaceViewの配列実体化
        surfaces = new MySurfaceView[quantity];
        for(int i=0;i<surfaces.length;i++){
        	//SurfaceViewインスタンスの生成
        	surfaces[i] = new MySurfaceView(context);
        	
        	//addView
        	base.addView(surfaces[i]);
        	//レイアウト指定
        	surfaces[i].setLayoutParams(getRndLayoutParams(surfaces[i]));
        	surfaces[i].setId(i);
        	//Listenerセット


        	surfaces[i].setOnTouchListener(listener);
        }
		

		tv.setOnTouchListener(listener);
		surface.setOnTouchListener(listener);
		
	}
	OnTouchListener listener = new OnTouchListener() {

		private float downX;
		private float downY;

		private int downLeftMargin;
		private int downTopMargin;

		@Override
		public boolean onTouch(View v, MotionEvent event) {
			tv.setText("move");
//			Log.v("OnTouch", "getId()=" + v.getId());
//			Log.v("OnTouch", "getLeft()=" + v.getLeft());
//			Log.v("OnTouch", "getX()=" + event.getX());
//			Log.v("OnTouch", "getRawX()=" + event.getRawX());
			//View.view.bringToFront() 重ね順を一番上に。
			v.bringToFront();

			final MarginLayoutParams params = (MarginLayoutParams) v
					.getLayoutParams();
			if (event.getAction() == MotionEvent.ACTION_DOWN) {
				downX = event.getRawX();
				downY = event.getRawY();

				downLeftMargin = params.leftMargin;
				downTopMargin = params.topMargin;

				return true;
			} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
				params.leftMargin = downLeftMargin
						+ (int) (event.getRawX() - downX);
				params.topMargin = downTopMargin
						+ (int) (event.getRawY() - downY);

				v.layout(params.leftMargin, params.topMargin,
						params.leftMargin + v.getWidth(), params.topMargin
								+ v.getHeight());

				return true;
			}

			return false;
		}
	};
    private MarginLayoutParams getRndLayoutParams(SurfaceView v){
    	MarginLayoutParams params = (MarginLayoutParams)v.getLayoutParams();
    	final int minWidth = 50;
    	final int minHeight = 50;
    	final int maxWidth = dispWidth / 2;
    	final int maxHeight = dispHeight / 2;
    	final int w = getIntRand(minWidth, maxWidth);
    	final int h = getIntRand(minHeight, maxHeight);

    	params.width = w;
    	params.height = h;
    	params.leftMargin = getIntRand(0, dispWidth - w);
    	params.topMargin = getIntRand(0, dispHeight - h);
    	//log
//    	Log.v("params","w"+params.width);
//    	Log.v("params","h"+params.height);
//    	Log.v("base","getWidth="+base.getWidth()+",getHeight="+base.getHeight());
//    	Log.v("params","l"+params.leftMargin);
//    	Log.v("params","t"+params.topMargin);
		return params;
    }
    public static int getIntRand(int min , int max){
    	int ret = (int)Math.floor(Math.random()*(max-min+1))+min;
//    	Log.v("ret","min="+min+",max="+max+",ret="+ret);
    	return ret;
    }
}

MySurfaceView.java

package com.example.l002_relativl_surface_circle;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;

public class MySurfaceView extends SurfaceView implements Runnable, Callback {
	//配列circleクラスの定義
	MyCircle[] circles;
	SurfaceHolder holder;
	Thread thread;

	//param
	private int 
	px = 10,		//X座標
	py = 10,		//Y座標
	r = 10,			//半径
	vx = 3,			//X速度
	vy = 3;			//Y速度
	
	public MySurfaceView(Context context) {
		super(context);
		//SurfaceHolder
		holder = this.getHolder();	//extends SurfaceViewだから取得できる
		holder.addCallback(this);
	}

	@Override
	public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void surfaceCreated(SurfaceHolder arg0) {
		// TODO Auto-generated method stub
		thread = new Thread(this);
		thread.start();
		
	}

	@Override
	public void surfaceDestroyed(SurfaceHolder arg0) {
		// TODO Auto-generated method stub
		thread = null;
	}

	@SuppressWarnings("static-access")
	@Override
	public void run() {
		Canvas canvas;
		Paint paint = new Paint();
		paint.setAntiAlias(true);
		paint.setColor(Color.YELLOW);
		while(thread != null){
			//ダブルバッファリング
			canvas = holder.lockCanvas();
			canvas.drawColor(Color.GRAY);	//ここで背景書く
			canvas.drawCircle(px,py,r,paint);
			holder.unlockCanvasAndPost(canvas);
			
			//ぶつかり判定と移動
			//width,heightも取得できる
			//getWidth,getHeightはthisで使う。(SurfaceView)
			if(px-r < 0 || this.getWidth() < px+r){
				vx = -vx;
			}
			if(py-r < 0 || this.getHeight() < py+r){
				vy = -vy;
			}
			px += vx;
			py += vy;
			
			try {
				thread.sleep(50);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
	}

}