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セット
Reference
画面サイズの取得
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(); } } } }