Androidでドラッグできる画像を作りたい
サンプル動画(上のやつ)
クラス構成
コメント
- Swingのrepaint()と対応するものはinvalidate()かな?
- 本当は画像自身がクリックされたかどうか判定するような機構を作りたかったけど、画面全体からeventを受け流す形で落ち着いてしまった。
ソース
DragImage.java
package net.voidy21.dragimage; import android.app.Activity; import android.os.Bundle; public class DragImage extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(new DragImageView(this)); } }
DragImageView.java
package net.voidy21.dragimage; import android.content.res.Resources; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.view.MotionEvent; import android.view.View; public class DragImageView extends View{ private ControlPriority cp; public DragImageView(Context context) { super(context); setFocusable(true); cp = new ControlPriority(context); //画像の読み込み Resources res = context.getResources(); Bitmap image1 = BitmapFactory.decodeResource(res,R.drawable.oda); Bitmap image2 = BitmapFactory.decodeResource(res,R.drawable.icon); Bitmap image3 = BitmapFactory.decodeResource(res,R.drawable.hiyoko); cp.add(image1); cp.add(image2); cp.add(image3); cp.initPriority(); } @Override public void onDraw(Canvas canvas) { cp.drawBitmaps(canvas); } @Override public boolean onTouchEvent(MotionEvent event){ switch(event.getAction()){ case MotionEvent.ACTION_DOWN: cp.callClickEvent(event); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_MOVE: cp.callMoveEvent(event); break; } invalidate(); return true; } @Override public boolean onTrackballEvent(MotionEvent event) { cp.callTouchEvent(event); invalidate(); return true; } }
DraggableBitmap.java
package net.voidy21.dragimage; import android.content.Context; import android.view.MotionEvent; import android.view.View; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Point; import android.graphics.Rect; public class DraggableBitmap extends View{ private Bitmap bitmap; private int imageWidth = 0; private int imageHeight = 0; private Rect src; private Rect dst; private int touchAction; private int ballAction; private float scaleX = 1.0f; private float scaleY = 1.0f; private boolean isDragable = false; private Point preXY; private Point touchXY; private int priority = -1; private Paint paint; public DraggableBitmap(Context context) { super(context); paint = new Paint(); preXY = new Point(0,0); touchXY = new Point(0,0); paint.setAntiAlias(true); //フォーカス指定 setFocusable(true); } public void setBitmap(Bitmap bmp) { if( bmp == null ) return; bitmap = bmp; imageWidth = bitmap.getWidth(); imageHeight = bitmap.getHeight(); src = new Rect(0, 0, imageWidth, imageHeight); dst = new Rect(src); } public void move(int x, int y) { dst.left = x; dst.top = y; dst.right = x + imageWidth; dst.bottom = y + imageHeight; invalidate(); } public int getImageWidth() { return imageWidth; } public int getImageHeight() { return imageHeight; } public void scale() { dst.right = (int)(src.right * scaleX); dst.bottom = (int)(src.bottom * scaleY); imageWidth = dst.width(); imageHeight = dst.height(); invalidate(); } @Override public void onDraw(Canvas canvas) { if( bitmap == null ) return; canvas.drawBitmap(bitmap, src, dst, paint); } @Override public boolean onTouchEvent(MotionEvent event) { touchAction = event.getAction(); int x = (int)event.getX(); int y = (int)event.getY(); if( touchAction == MotionEvent.ACTION_MOVE && isDragable ){ touchXY.set(x, y); int newX = dst.left + (touchXY.x - preXY.x); int newY = dst.top + (touchXY.y - preXY.y); move(newX,newY); preXY.set(touchXY.x,touchXY.y); } if(isTouchImage(x, y)){ if( touchAction == MotionEvent.ACTION_DOWN ){ preXY.set(x, y); isDragable = true; }else if( touchAction == MotionEvent.ACTION_UP ) { isDragable = false; } }else{ return false; } return true; } @Override public boolean onTrackballEvent(MotionEvent event) { ballAction = event.getAction(); int x = (int)event.getX(); int y = (int)event.getY(); if( ballAction == MotionEvent.ACTION_MOVE ){ float newScaleX = scaleX+(float)(x/20.0f); float newScaleY = scaleY+(float)(y/20.0f); if(newScaleX > 0.4f && newScaleY > 0.4f) setScale(newScaleX,newScaleY); } return true; } private boolean isTouchImage(int x,int y) { int imgX = dst.left; int imgY = dst.top; return x-imgX >= 0 && x-imgX < dst.width() && y-imgY >= 0 && y-imgY < dst.height(); } public void setPriority(int priority) { this.priority = priority; } public int getPriority() { return priority; } public void downPriority() { --priority; } public void setScale(float scaleX,float scaleY){ this.scaleX = scaleX; this.scaleY = scaleY; scale(); } }
ControlPriority.java
package net.voidy21.dragimage; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.view.MotionEvent; public class ControlPriority { private ArrayList<DraggableBitmap> dBitmaps; private int draggingNum; private Context context; public ControlPriority(Context context) { this.context = context; dBitmaps = new ArrayList<DraggableBitmap>(); } public void initPriority() { int i = 0; for( DraggableBitmap dBmp : dBitmaps ){ dBmp.setPriority(i++); } } public void add(DraggableBitmap dBitmap){ dBitmaps.add(dBitmap); } public void add(Bitmap bitmap) { DraggableBitmap dBitmap = new DraggableBitmap(context); dBitmap.setBitmap(bitmap); dBitmaps.add(dBitmap); } public void drawBitmaps(Canvas canvas) { for( int i = dBitmaps.size()- 1; i >= 0; --i ) { dBitmaps.get(i).draw(canvas); } } public void callClickEvent(MotionEvent event){ int size = dBitmaps.size(); for( int i = 0; i < size; ++i ) { if( dBitmaps.get(i).onTouchEvent(event) ){ draggingNum = i; break; } } int dPriority = dBitmaps.get(draggingNum).getPriority(); for( DraggableBitmap dBmp : dBitmaps ) if(dBmp.getPriority() > dPriority) dBmp.downPriority(); dBitmaps.get(draggingNum).setPriority(size); //ソート Collections.sort(dBitmaps, new Comparator<DraggableBitmap>(){ public int compare(DraggableBitmap db1, DraggableBitmap db2) { return db2.getPriority() - db1.getPriority(); } }); } public void callMoveEvent(MotionEvent event) { dBitmaps.get(0).onTouchEvent(event); } public void callTouchEvent(MotionEvent event) { dBitmaps.get(0).onTrackballEvent(event); } }
最後に
次はViewじゃなくてSurfaceViewってやつを使ってみたいです!
あと、実機がほしいです!