image animation when i click on image - android

i have image it moves all directions on the canvas
my requirement is when i click on moving image it change the direction to the top but i unable to do this,below i will drop total code,please help me
animatedview.java:
public class AnimatedView extends ImageView{
int c=0;
static int count=0;
private Context mContext;
int x = 150;
int y = 450;
private float a,b;
private int xVelocity = 20;
private int yVelocity = 20;
private Handler h;
private final int FRAME_RATE = 25;
BitmapDrawable ball;
boolean touching;
boolean dm_touched = false;
float move=3;
int bm_x = 0, bm_y = 0, bm_offsetx, bm_offsety,bm_w,bm_h;
public AnimatedView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
h = new Handler();
}
private Runnable r = new Runnable() {
#Override
public void run() {
//Log.e("bharat","run called");
if(touching = true)
invalidate();
}
};
#Override
protected void onDraw(Canvas c) {
//Log.e("bharat","ondraw called");
//int z= c.getHeight()/2;
//Log.e("bharat","z is"+z);
BitmapDrawable ball = (BitmapDrawable) mContext.getResources().getDrawable(R.drawable.ball);
if (x<0 && y <0) {
//x = this.getWidth()/2;
y = c.getHeight()/2;
} else {
x += xVelocity;
y += yVelocity;
if ((x > this.getWidth() - ball.getBitmap().getWidth()) || (x < 0)) {
xVelocity = xVelocity*-1;
}
if (y >( this.getHeight() - ball.getBitmap().getHeight()) ||y <0) {
yVelocity = yVelocity*-1;
}
}
c.drawBitmap(ball.getBitmap(), x, y, null);
//Log.e("sarat",""+touching);
if(touching){
// Log.e("bharat","iftouch called called");
h.postDelayed(r, FRAME_RATE);
bm_w=ball.getBitmap().getWidth();
bm_h=ball.getBitmap().getHeight();
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
// Log.d("bharat","ontouch called");
int touchType = event.getAction();
switch(touchType){
case MotionEvent.ACTION_MOVE:
a = event.getX();
b = event.getY();
touching = true;
/* if (dm_touched) {
x = (int) a - bm_offsetx;
y = (int) b - bm_offsety;
}*/
//invalidate();
break;
case MotionEvent.ACTION_DOWN:
//x and y give you your touch coordinates
a = event.getX();
b = event.getY();
touching = true;
//Log.d("bharat","action_down called");
Log.e("s",""+ a);
Log.e("s",""+ b);
Log.e("s",""+ x);
Log.e("s",""+ y);
Log.e("s",""+ bm_w);
Log.e("s",""+ bm_h);
if ((a > x) && (a < bm_w + x) && (b > y) && (b < bm_h + y)) {
count++;
MainActivity.setCount(count);
invalidate();
Log.i("bharat",""+count);
/* if(b>450)
{
// Toast.makeText(getContext(),"game over",Toast.LENGTH_LONG).show();
}*/
}
if (dm_touched) {
if ((a > x) && (a < bm_w + x) && (b > y) && (b < bm_h + y)) {
move+=2;
//x = (int) a - bm_offsetx;
y = (int)b-300;
}}
// dm_touched = true;
case MotionEvent.ACTION_UP:c++;
a = event.getX();
b = event.getY();
if(a>x+20&&a<330&&b<=y+320&&b>y){
invalidate();}
if ((a > x) && (a < bm_w + x) && (b > y) && (b < bm_h + y)) {
Log.e("bharat","clicked");
}
default:
dm_touched = true;
//touching = true;
}
return true;
}
#Override
public void destroyDrawingCache() {
count=0;
super.destroyDrawingCache();
}
}

Related

How to draw by finger on canvas after pinch to zoom coordinates changed in android?

Can any body have solution regarding how to draw on canvas using finger after zoom in and zoom out? I done pinch to zoom for canvas but stucking point is not draw right coordinate. I done more R&D from google. I have CustomView Class which i share on below.
public class DrawingView extends View {
ArrayList<Path> pathList = new ArrayList<Path>();
Rect mRect = new Rect();
private static final int INVALID_POINTER_ID = -1;
public Bitmap mMyChracter;
private float mPosX;
private float mPosY;
private float mLastTouchX;
private float mLastTouchY;
private int mActivePointerId = INVALID_POINTER_ID;
View currentView;
private ScaleGestureDetector mScaleDetector;
private float mScaleFactor = 1.f;
private float focusX;
private float focusY;
private float lastFocusX = -1;
private float lastFocusY = -1;
static final int IMG_WIDTH = 640;
static final int IMG_HEIGHT = 480;
static final int IMAGE_X_POS = 560;
static final int IMAGE_Y_POS = 20;
boolean mFalgPath=false;
boolean mFlagDrawAgain;
float sy;
float sx;
public static Context context;
Path path = new Path();
MyPath p1 = new MyPath();
MyPath p2 = new MyPath();
Path mNewPath = new Path();
// -------------------------------------
// ...................................
/*private final Bitmap bitmap;
private final int width;
private final int height;*/
private Matrix transform = new Matrix();
private Vector2D position = new Vector2D();
private float scale = 1;
private float angle = 0;
private TouchManager touchManager = new TouchManager(2);
private boolean isInitialized = false;
// Debug helpers to draw lines between the two touch points
private Vector2D vca = null;
private Vector2D vcb = null;
private Vector2D vpa = null;
private Vector2D vpb = null;
int mWidth;
int mHeight;
// ...............................
private final Paint mDefaultPaint;
private Paint mFillPaint;
float x, y;
private Canvas mLayerCanvas = new Canvas();
private Bitmap mLayerBitmap;
private Stack<DrawOp> mDrawOps = new Stack<>();
private Stack<DrawOp> mUndoOps = new Stack<>();
private SparseArray<DrawOp> mCurrentOps = new SparseArray<>(0);
// For Drag and Pan zoom Code initialization
private static float MIN_ZOOM = 1f;
private static float MAX_ZOOM = 2f;
private float scaleFactor = 1.f;
private static ScaleGestureDetector detector;
boolean mFlagDrawing;
private final Matrix mMatrix = new Matrix();
int y_old=0,y_new=0;int zoomMode=0;
float pinch_dist_old=0,pinch_dist_new=0;
int zoomControllerScale=1;//new and old pinch distance to determine Zoom scale
// These matrices will be used to move and zoom image
Matrix matrix = new Matrix();
Matrix savedMatrix = new Matrix();
// Remember some things for zooming
PointF start = new PointF();
PointF mid = new PointF();
float oldDist = 1f;
// We can be in one of these 3 states
static final int NONE = 0;
static final int PAN = 1;
static final int ZOOM = 2;
int mode = NONE;
private static final String TAG = "DebugTag";
// New Code
private Bitmap imgBitmap = null;
private int containerWidth;
private int containerHeight;
Paint background;
//Matrices will be used to move and zoom image
// Matrix matrix = new Matrix();
// Matrix savedMatrix = new Matrix();
// PointF start = new PointF();
float currentScale;
float curX;
float curY;
//We can be in one of these 3 states
// static final int NONE = 0;
// static final int DRAG = 1;
// static final int ZOOM = 2;
// int mode = NONE;
//For animating stuff
float targetX;
float targetY;
float targetScale;
float targetScaleX;
float targetScaleY;
float scaleChange;
float targetRatio;
float transitionalRatio;
float easing = 0.2f;
boolean isAnimating = false;
float scaleDampingFactor = 0.5f;
//For pinch and zoom
// float oldDist = 1f;
// PointF mid = new PointF();
private Handler mHandler = new Handler();
float minScale;
float maxScale = 8.0f;
float wpRadius = 25.0f;
float wpInnerRadius = 20.0f;
float screenDensity;
private GestureDetector gestureDetector;
public static final int DEFAULT_SCALE_FIT_INSIDE = 0;
public static final int DEFAULT_SCALE_ORIGINAL = 1;
private int defaultScale;
private static final String EXTRA_EVENT_LIST = "event_list";
private static final String EXTRA_STATE = "instance_state";
private ArrayList<MotionEvent> eventList = new ArrayList<MotionEvent>(100);
public DrawingView(Context context) {
this(context, null, 0);
}
public DrawingView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
// detector = new ScaleGestureDetector(getContext(), new ScaleListener());
}
public DrawingView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mDefaultPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mDefaultPaint.setStyle(Paint.Style.STROKE);
mDefaultPaint.setStrokeJoin(Paint.Join.ROUND);
mDefaultPaint.setStrokeCap(Paint.Cap.ROUND);
mDefaultPaint.setStrokeWidth(40);
mDefaultPaint.setColor(Color.GREEN);
/*mFillPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mFillPaint.setStyle(Paint.Style.STROKE);
mFillPaint.setStrokeJoin(Paint.Join.ROUND);
mFillPaint.setStrokeCap(Paint.Cap.ROUND);
mDefaultPaint.setStrokeWidth(40);
mFillPaint.setColor(Color.GREEN);*/
setFocusable(true);
setFocusableInTouchMode(true);
setBackgroundColor(Color.WHITE);
setLayerType(LAYER_TYPE_SOFTWARE, null);
setSaveEnabled(true);
// Code for Zoom start
// detector = new ScaleGestureDetector(getContext(), new ScaleListener());
// Code for Zoom finish
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
}
private static float getDegreesFromRadians(float angle) {
return (float)(angle * 180.0 / Math.PI);
}
// Single Touch Code
#Override
public boolean onTouchEvent(#NonNull MotionEvent event) {
/* float j = event.getX() / mScaleFactor + mRect.left;
float k = event.getY() / mScaleFactor + mRect.top;*/
final int pointerCount = MotionEventCompat.getPointerCount(event);
switch (MotionEventCompat.getActionMasked(event)) {
// switch(event.getAction()){
// switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
// case MotionEventCompat.ACTION_POINTER_DOWN:
{
if (mFlagDrawing == true) {
System.out.println("mFlagDrawing: " + mFlagDrawing);
// Code for Zoom start
// detector.onTouchEvent(event);
mScaleDetector.onTouchEvent(event);
// Code for Zoom finish
/* float dx = event.getX();
float dy = event.getY();
if(mScaleFactor==1.f){
dx = event.getX() - mPosX;
dy = event.getY() - mPosY;
}
// tempPath = new Path();
DrawOp current = new DrawOp(mDefaultPaint);
current.getPath().moveTo(dx, dy);*/
} else if (mFlagDrawing == false) {
DrawOp currentNew = new DrawOp(mDefaultPaint);
if(mFlagDrawAgain == true){
p1.moveTo(event.getX(), event.getY());
/* path.moveTo(event.getX(), event.getY());
mNewPath.addPath(path);*/
}
else{
System.out.println("mFlagDrawing: " + mFlagDrawing);
for (int p = 0; p < pointerCount; p++) {
final int id = MotionEventCompat.getPointerId(event, p);
DrawOp current = new DrawOp(mDefaultPaint);
current.getPath().moveTo(event.getX(), event.getY());
// current.getPath().setLastPoint(dx, dy)
// mNewPath.addPath(current.getPath());
mCurrentOps.put(id, current);
}
}
}
// mFlagZoom = true;
// }
}
break;
case MotionEvent.ACTION_MOVE: {
// for(int p = 0; p < pointerCount; p++){
if (mFlagDrawing == true) {
System.out.println("mFlagDrawing: " + mFlagDrawing);
// Code for Zoom start
// detector.onTouchEvent(event);
mScaleDetector.onTouchEvent(event);
// Code for Zoom finish
/* float dx = event.getX();
float dy = event.getY();;
if(mScaleFactor==1.f){
dx = event.getX() - mPosX;
dy = event.getY() - mPosY;
}
// mFalgPath = true;
path.lineTo(dx, dy);*/
} else if (mFlagDrawing == false) {
// mFalgPath = true;
// Rect rect = new Rect();
if(mFlagDrawAgain == true){
float dx = event.getX();
float dy = event.getY();
final int id = MotionEventCompat.getPointerId(event, 0);
DrawOp current = mCurrentOps.get(id);
if(mScaleFactor==1.f){
dx = event.getX() - mPosX;
dy = event.getY() - mPosY;
}
p1.lineTo(dx, dy);
/*p1.addPath(current.getPath());*/
/*path.lineTo(dx, dy);
mNewPath.addPath(path);*/
}
else{
System.out.println("mFlagDrawing: " + mFlagDrawing);
final int id = MotionEventCompat.getPointerId(event, 0);
DrawOp current = mCurrentOps.get(id);
final int historySize = event.getHistorySize();
for (int h = 0; h < historySize; h++) {
x = event.getHistoricalX(h);
y = event.getHistoricalY(h);
current.getPath().lineTo(x, y);
// mNewPath.addPath(current.getPath());
// mNewPath.lineTo(x, y);
}
x = MotionEventCompat.getX(event, 0);
y = MotionEventCompat.getY(event, 0);
current.getPath().lineTo(x, y);
}
}
// path.lineTo(x, y);
// }
}
break;
case MotionEvent.ACTION_UP:
// case MotionEventCompat.ACTION_POINTER_UP:
// {
if (mFlagDrawing == true) {
System.out.println("mFlagDrawing: " + mFlagDrawing);
// Code for Zoom start
// detector.onTouchEvent(event);
mScaleDetector.onTouchEvent(event);
// Code for Zoom finish
mActivePointerId = INVALID_POINTER_ID;
} else if (mFlagDrawing == false) {
System.out.println("mFlagDrawing: " + mFlagDrawing);
for (int p = 0; p < pointerCount; p++) {
final int id = MotionEventCompat.getPointerId(event, p);
mDrawOps.push(mCurrentOps.get(id));
mCurrentOps.remove(id);
// }
updateLayer();
}
}
// }
break;
case MotionEvent.ACTION_CANCEL: {
if (mFlagDrawing == true) {
System.out.println("mFlagDrawing: " + mFlagDrawing);
// Code for Zoom start
// detector.onTouchEvent(event);
mScaleDetector.onTouchEvent(event);
// Code for Zoom finish
mActivePointerId = INVALID_POINTER_ID;
} else if (mFlagDrawing == false) {
System.out.println("mFlagDrawing: " + mFlagDrawing);
for (int p = 0; p < pointerCount; p++) {
mCurrentOps
.remove(MotionEventCompat.getPointerId(event, p));
}
}
// mFlagZoom = true;
// }
}
break;
case MotionEvent.ACTION_POINTER_UP: {
final int pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
final int pointerId = event.getPointerId(pointerIndex);
if (pointerId == mActivePointerId) {
// This was our active pointer going up. Choose a new
// active pointer and adjust accordingly.
final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
mLastTouchX = event.getX(newPointerIndex) / mScaleFactor;
mLastTouchY = event.getY(newPointerIndex) / mScaleFactor;
mActivePointerId = event.getPointerId(newPointerIndex);
}
break;
}
default:
return false;
}
invalidate();
return true;
}
#Override
protected void onSizeChanged(int w, int h, int oldW, int oldH) {
super.onSizeChanged(w, h, oldW, oldH);
if(mLayerBitmap == null){
mLayerBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
}else{
Bitmap temporary = Bitmap.createScaledBitmap(mLayerBitmap, w, h, true);
mLayerBitmap = temporary;
}
mLayerCanvas = new Canvas(mLayerBitmap);
}
private void updateLayer() {
mLayerCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
for (DrawOp drawOp : mDrawOps) {
if (drawOp != null) {
drawOp.draw(mLayerCanvas);
}
}
invalidate();
}
#SuppressWarnings("null")
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (isInEditMode()) {
return;
}
canvas.save();
canvas.scale(mScaleFactor, mScaleFactor, focusX, focusY);
canvas.translate(mPosX, mPosY);
canvas.drawBitmap(mLayerBitmap, 0, 0, null);
if(mScaleFactor!=1.f)
canvas.restore();
if(mScaleFactor==1.f)
canvas.restore();
if(mFlagDrawAgain == true){
// canvas.drawPath(path, mDefaultPaint);
canvas.drawPath(p1, mDefaultPaint);
}
else{
for (int i = 0; i < mCurrentOps.size(); i++) {
DrawOp current = mCurrentOps.valueAt(i);
if (current != null) {
current.draw(canvas);
}
}
}
canvas.restore();
}
public void operationClear() {
path.reset();
mDrawOps.clear();
mUndoOps.clear();
mCurrentOps.clear();
updateLayer();
}
public void operationUndo() {
if (mDrawOps.size() > 0) {
mUndoOps.push(mDrawOps.pop());
updateLayer();
}
}
public void operationRedo() {
if (mUndoOps.size() > 0) {
mDrawOps.push(mUndoOps.pop());
updateLayer();
}
}
public void setPaintStrokeWidth(float widthPx) {
mDefaultPaint.setStrokeWidth(widthPx);
}
public void setPaintOpacity(int percent) {
int alphaValue = (int) Math.round(percent * (255.0 / 100.0));
mDefaultPaint.setColor(combineAlpha(mDefaultPaint.getColor(),
alphaValue));
}
public void setPaintColor(String color) {
mDefaultPaint.setColor(combineAlpha(Color.parseColor(color), mDefaultPaint.getAlpha()));
}
public void setPaintColor(int color) {
mDefaultPaint.setColor(combineAlpha(color, mDefaultPaint.getAlpha()));
}
public void setPaintMaskFilter(MaskFilter filter) {
mDefaultPaint.setMaskFilter(filter);
}
public void setPaintShader(BitmapShader shader) {
mDefaultPaint.setShader(shader);
}
public void setPaintColorFilter(ColorFilter colorFilter) {
mDefaultPaint.setColorFilter(colorFilter);
}
private static int combineAlpha(int color, int alpha) {
return (color & 0x00FFFFFF) | ((alpha & 0xFF) << 24);
}
private static class DrawOp {
private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private final Path mPath = new Path();
public DrawOp(Paint paint) {
reset(paint);
}
void reset(Paint paint) {
mPath.reset();
update(paint);
}
void update(Paint paint) {
mPaint.set(paint);
}
void draw(Canvas canvas) {
canvas.drawPath(mPath, mPaint);
}
public Path getPath() {
return mPath;
}
}
public void fillShapeColor(){
}
private class ScaleListener extends
ScaleGestureDetector.SimpleOnScaleGestureListener {
#Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
// float x = detector.getFocusX();
// float y = detector.getFocusY();
lastFocusX = -1;
lastFocusY = -1;
return true;
}
#Override
public boolean onScale(ScaleGestureDetector detector) {
mScaleFactor *= detector.getScaleFactor();
focusX = detector.getFocusX();
focusY = detector.getFocusY();
if (lastFocusX == -1)
lastFocusX = focusX;
if (lastFocusY == -1)
lastFocusY = focusY;
mPosX += (focusX - lastFocusX);
mPosY += (focusY - lastFocusY);
Log.v("Hi Zoom", "Factor:" + mScaleFactor);
// Don't let the object get too small or too large.
mScaleFactor = Math.max(1.f, Math.min(mScaleFactor, 2.0f));
lastFocusX = focusX;
lastFocusY = focusY;
invalidate();
return true;
}
}
public void setDrawingFlag(boolean flag) {
// System.out.println("Before Set mFlag " + mFlagDrawing);
this.mFlagDrawing = flag;
// System.out.println("After Set mFlag " + mFlagDrawing);
}
public void setDrawPath(boolean flag){
this.mFalgPath = flag;
}
public void setDrawAgain(boolean flag){
this.mFlagDrawAgain = flag;
}
}
After lots of research i found solution for moving actual canvas with finger and used ZoomControlButton for zoom in and zoom out canvas. I post my code here for someone help.
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (isInEditMode()) {
return;
}
if (mScaleFactor == 1.f)
canvas.save();
canvas.drawRGB(224, 224, 224);
canvas.translate(-mPosX, -mPosY);
canvas.drawBitmap(mLayerBitmap, new Matrix(), mDefaultPaint);
Log.v("onDraw", "scale f : " + mScaleFactor);
for (int i = 0; i < mCurrentOps.size(); i++) {
Log.v("onDraw", "current ops");
DrawOp current = mCurrentOps.valueAt(i);
if (current != null) {
current.draw(canvas);
}
}
canvas.restore();
}
In onTouch() i used following code
#Override
public boolean onTouchEvent(#NonNull MotionEvent event) {
final int pointerCount = MotionEventCompat.getPointerCount(event);
switch (MotionEventCompat.getActionMasked(event)) {
// switch(event.getAction()){
// switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
// case MotionEventCompat.ACTION_POINTER_DOWN:
{
if (mFlagDrawing == true) {
System.out.println("mFlagDrawing: " + mFlagDrawing);
// Code for Zoom start
// detector.onTouchEvent(event);
mScaleDetector.onTouchEvent(event);
// Code for Zoom finish
} else if (mFlagDrawing == false) {
System.out.println("mFlagDrawing: " + mFlagDrawing);
float dx = event.getX();
float dy = event.getY();
if(mScaleFactor==1.f){
dx = event.getX() - mPosX;
dy = event.getY() - mPosY;
}
for (int p = 0; p < pointerCount; p++) {
final int id = MotionEventCompat.getPointerId(event, p);
DrawOp current = new DrawOp(mDefaultPaint);
current.getPath().moveTo(event.getX() + mPosX, event.getY() + mPosY);
mCurrentOps.put(id, current);
}
}
}
break;
case MotionEvent.ACTION_MOVE: {
// for(int p = 0; p < pointerCount; p++){
if (mFlagDrawing == true) {
System.out.println("mFlagDrawing: " + mFlagDrawing);
// Code for Zoom start
// detector.onTouchEvent(event);
mScaleDetector.onTouchEvent(event);
// Code for Zoom finish
} else if (mFlagDrawing == false) {
System.out.println("mFlagDrawing: " + mFlagDrawing);
final int id = MotionEventCompat.getPointerId(event, 0);
DrawOp current = mCurrentOps.get(id);
final int historySize = event.getHistorySize();
for (int h = 0; h < historySize; h++) {
x = event.getHistoricalX(h) + mPosX;
y = event.getHistoricalY(h) + mPosY;
current.getPath().lineTo(x, y);
}
x = MotionEventCompat.getX(event, 0) + mPosX;
y = MotionEventCompat.getY(event, 0) + mPosY;
current.getPath().lineTo(x, y);
}
}
break;
case MotionEvent.ACTION_UP:
// case MotionEventCompat.ACTION_POINTER_UP:
// {
if (mFlagDrawing == true) {
System.out.println("mFlagDrawing: " + mFlagDrawing);
// Code for Zoom start
// detector.onTouchEvent(event);
mScaleDetector.onTouchEvent(event);
// Code for Zoom finish
mActivePointerId = INVALID_POINTER_ID;
} else if (mFlagDrawing == false) {
System.out.println("mFlagDrawing: " + mFlagDrawing);
for (int p = 0; p < pointerCount; p++) {
final int id = MotionEventCompat.getPointerId(event, p);
mDrawOps.push(mCurrentOps.get(id));
mCurrentOps.remove(id);
// }
updateLayer();
}
}
// }
break;
case MotionEvent.ACTION_CANCEL: {
if (mFlagDrawing == true) {
System.out.println("mFlagDrawing: " + mFlagDrawing);
// Code for Zoom start
// detector.onTouchEvent(event);
mScaleDetector.onTouchEvent(event);
// Code for Zoom finish
mActivePointerId = INVALID_POINTER_ID;
} else if (mFlagDrawing == false) {
System.out.println("mFlagDrawing: " + mFlagDrawing);
for (int p = 0; p < pointerCount; p++) {
mCurrentOps
.remove(MotionEventCompat.getPointerId(event, p));
}
}
// mFlagZoom = true;
// }
}
break;
default:
return false;
}
invalidate();
return true;
}
When updating the whole Layer then i used following syntax:
private void updateLayer() {
mLayerCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
mLayerCanvas.drawRGB(255, 255, 255);
mLayerCanvas.save();
for (DrawOp drawOp : mDrawOps) {
if (drawOp != null) {
drawOp.draw(mLayerCanvas);
}
}
mLayerCanvas.restore();
invalidate();
}

Canvas getting wrong coordinates for finger drawing after pinch to zoom

I create canvas finger drawing app like line brush which is on https://play.google.com/store/apps/details?id=jp.naver.linebrush.android, I done pinch to zoom functionality but problem is after zoom in and zoom out, not drawing properly position on canvas area. For more understanding I share my View class for canvas drawing:
public class DrawingView extends View {
// Zooming Code 16-6-2015 4.12pm
private static final int INVALID_POINTER_ID = -1;
public Bitmap mMyChracter;
private float mPosX;
private float mPosY;
private float mLastTouchX;
private float mLastTouchY;
private int mActivePointerId = INVALID_POINTER_ID;
View currentView;
private ScaleGestureDetector mScaleDetector;
private float mScaleFactor = 1.f;
private float focusX;
private float focusY;
private float lastFocusX = -1;
private float lastFocusY = -1;
static final int IMG_WIDTH = 640;
static final int IMG_HEIGHT = 480;
static final int IMAGE_X_POS = 560;
static final int IMAGE_Y_POS = 20;
float sy;
float sx;
public static Context context;
// -------------------------------------
// ...................................
/*private final Bitmap bitmap;
private final int width;
private final int height;*/
private Matrix transform = new Matrix();
private Vector2D position = new Vector2D();
private float scale = 1;
private float angle = 0;
private TouchManager touchManager = new TouchManager(2);
private boolean isInitialized = false;
// Debug helpers to draw lines between the two touch points
private Vector2D vca = null;
private Vector2D vcb = null;
private Vector2D vpa = null;
private Vector2D vpb = null;
int mWidth;
int mHeight;
// ...............................
private final Paint mDefaultPaint;
private Paint mFillPaint;
float x, y;
private Canvas mLayerCanvas = new Canvas();
private Bitmap mLayerBitmap;
private Stack<DrawOp> mDrawOps = new Stack<>();
private Stack<DrawOp> mUndoOps = new Stack<>();
private SparseArray<DrawOp> mCurrentOps = new SparseArray<>(0);
// For Drag and Pan zoom Code initialization
private static float MIN_ZOOM = 1f;
private static float MAX_ZOOM = 2f;
private float scaleFactor = 1.f;
private static ScaleGestureDetector detector;
boolean mFlagDrawing;
private final Matrix mMatrix = new Matrix();
int y_old=0,y_new=0;int zoomMode=0;
float pinch_dist_old=0,pinch_dist_new=0;
int zoomControllerScale=1;//new and old pinch distance to determine Zoom scale
// These matrices will be used to move and zoom image
Matrix matrix = new Matrix();
Matrix savedMatrix = new Matrix();
// Remember some things for zooming
PointF start = new PointF();
PointF mid = new PointF();
float oldDist = 1f;
// We can be in one of these 3 states
static final int NONE = 0;
static final int PAN = 1;
static final int ZOOM = 2;
int mode = NONE;
private static final String TAG = "DebugTag";
// New Code
private Bitmap imgBitmap = null;
private int containerWidth;
private int containerHeight;
Paint background;
//Matrices will be used to move and zoom image
// Matrix matrix = new Matrix();
// Matrix savedMatrix = new Matrix();
// PointF start = new PointF();
float currentScale;
float curX;
float curY;
//We can be in one of these 3 states
// static final int NONE = 0;
// static final int DRAG = 1;
// static final int ZOOM = 2;
// int mode = NONE;
//For animating stuff
float targetX;
float targetY;
float targetScale;
float targetScaleX;
float targetScaleY;
float scaleChange;
float targetRatio;
float transitionalRatio;
float easing = 0.2f;
boolean isAnimating = false;
float scaleDampingFactor = 0.5f;
//For pinch and zoom
// float oldDist = 1f;
// PointF mid = new PointF();
private Handler mHandler = new Handler();
float minScale;
float maxScale = 8.0f;
float wpRadius = 25.0f;
float wpInnerRadius = 20.0f;
float screenDensity;
private GestureDetector gestureDetector;
public static final int DEFAULT_SCALE_FIT_INSIDE = 0;
public static final int DEFAULT_SCALE_ORIGINAL = 1;
private int defaultScale;
private static final String EXTRA_EVENT_LIST = "event_list";
private static final String EXTRA_STATE = "instance_state";
private ArrayList<MotionEvent> eventList = new ArrayList<MotionEvent>(100);
public DrawingView(Context context) {
this(context, null, 0);
}
public DrawingView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
// detector = new ScaleGestureDetector(getContext(), new ScaleListener());
}
public DrawingView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mDefaultPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mDefaultPaint.setStyle(Paint.Style.STROKE);
mDefaultPaint.setStrokeJoin(Paint.Join.ROUND);
mDefaultPaint.setStrokeCap(Paint.Cap.ROUND);
mDefaultPaint.setStrokeWidth(40);
mDefaultPaint.setColor(Color.GREEN);
/*mFillPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mFillPaint.setStyle(Paint.Style.STROKE);
mFillPaint.setStrokeJoin(Paint.Join.ROUND);
mFillPaint.setStrokeCap(Paint.Cap.ROUND);
mDefaultPaint.setStrokeWidth(40);
mFillPaint.setColor(Color.GREEN);*/
setFocusable(true);
setFocusableInTouchMode(true);
setBackgroundColor(Color.WHITE);
setLayerType(LAYER_TYPE_SOFTWARE, null);
setSaveEnabled(true);
// Code for Zoom start
// detector = new ScaleGestureDetector(getContext(), new ScaleListener());
// Code for Zoom finish
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
}
private static float getDegreesFromRadians(float angle) {
return (float)(angle * 180.0 / Math.PI);
}
// Single Touch Code
#Override
public boolean onTouchEvent(#NonNull MotionEvent event) {
vca = null;
vcb = null;
vpa = null;
vpb = null;
final int pointerCount = MotionEventCompat.getPointerCount(event);
switch (MotionEventCompat.getActionMasked(event)) {
// switch(event.getAction()){
// switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
// case MotionEventCompat.ACTION_POINTER_DOWN:
{
if (mFlagDrawing == true) {
/* final float xx = event.getX() / mScaleFactor;
final float yy = event.getY() / mScaleFactor;
mLastTouchX = xx;
mLastTouchY = yy;
mActivePointerId = event.getPointerId(0);*/
try {
touchManager.update(event);
if (touchManager.getPressCount() == 1) {
vca = touchManager.getPoint(0);
vpa = touchManager.getPreviousPoint(0);
position.add(touchManager.moveDelta(0));
}
else {
if (touchManager.getPressCount() == 2) {
vca = touchManager.getPoint(0);
vpa = touchManager.getPreviousPoint(0);
vcb = touchManager.getPoint(1);
vpb = touchManager.getPreviousPoint(1);
Vector2D current = touchManager.getVector(0, 1);
Vector2D previous = touchManager.getPreviousVector(0, 1);
float currentDistance = current.getLength();
float previousDistance = previous.getLength();
if (previousDistance != 0) {
scale *= currentDistance / previousDistance;
}
angle -= Vector2D.getSignedAngleBetween(current, previous);
}
}
invalidate();
}
catch(Throwable t) {
// So lazy...
}
System.out.println("mFlagDrawing: " + mFlagDrawing);
// Code for Zoom start
// detector.onTouchEvent(event);
// mScaleDetector.onTouchEvent(event);
// Code for Zoom finish
} else if (mFlagDrawing == false) {
System.out.println("mFlagDrawing: " + mFlagDrawing);
for (int p = 0; p < pointerCount; p++) {
final int id = MotionEventCompat.getPointerId(event, p);
DrawOp current = new DrawOp(mDefaultPaint);
current.getPath().moveTo(event.getX(), event.getY());
mCurrentOps.put(id, current);
}
}
// mFlagZoom = true;
// }
}
break;
case MotionEvent.ACTION_MOVE: {
// for(int p = 0; p < pointerCount; p++){
if (mFlagDrawing == true) {
/* final int pointerIndex = event.findPointerIndex(mActivePointerId);
final float xx = event.getX(pointerIndex) / mScaleFactor;
final float yy = event.getY(pointerIndex) / mScaleFactor;
// Only move if the ScaleGestureDetector isn't processing a gesture.
if (!mScaleDetector.isInProgress()) {
final float dx = xx - mLastTouchX;
final float dy = yy - mLastTouchY;
mPosX += dx;
mPosY += dy;
invalidate();
}
mLastTouchX = xx;
mLastTouchY = yy;*/
try {
touchManager.update(event);
if (touchManager.getPressCount() == 1) {
vca = touchManager.getPoint(0);
vpa = touchManager.getPreviousPoint(0);
position.add(touchManager.moveDelta(0));
// current.add(touchManager.moveDelta(0));
}
else {
if (touchManager.getPressCount() == 2) {
vca = touchManager.getPoint(0);
vpa = touchManager.getPreviousPoint(0);
vcb = touchManager.getPoint(1);
vpb = touchManager.getPreviousPoint(1);
Vector2D current = touchManager.getVector(0, 1);
Vector2D previous = touchManager.getPreviousVector(0, 1);
float currentDistance = current.getLength();
float previousDistance = previous.getLength();
if (previousDistance != 0) {
scale *= currentDistance / previousDistance;
}
angle -= Vector2D.getSignedAngleBetween(current, previous);
}
}
invalidate();
}
catch(Throwable t) {
// So lazy...
}
System.out.println("mFlagDrawing: " + mFlagDrawing);
// Code for Zoom start
// detector.onTouchEvent(event);
// mScaleDetector.onTouchEvent(event);
// Code for Zoom finish
} else if (mFlagDrawing == false) {
System.out.println("mFlagDrawing: " + mFlagDrawing);
final int id = MotionEventCompat.getPointerId(event, 0);
DrawOp current = mCurrentOps.get(id);
final int historySize = event.getHistorySize();
for (int h = 0; h < historySize; h++) {
x = event.getHistoricalX(h);
y = event.getHistoricalY(h);
current.getPath().lineTo(x, y);
}
x = MotionEventCompat.getX(event, 0);
y = MotionEventCompat.getY(event, 0);
current.getPath().lineTo(x, y);
// position.add(current.getPath());
// }
}
}
break;
case MotionEvent.ACTION_UP:
// case MotionEventCompat.ACTION_POINTER_UP:
// {
if (mFlagDrawing == true) {
// mActivePointerId = INVALID_POINTER_ID;
try {
touchManager.update(event);
if (touchManager.getPressCount() == 1) {
vca = touchManager.getPoint(0);
vpa = touchManager.getPreviousPoint(0);
position.add(touchManager.moveDelta(0));
}
else {
if (touchManager.getPressCount() == 2) {
vca = touchManager.getPoint(0);
vpa = touchManager.getPreviousPoint(0);
vcb = touchManager.getPoint(1);
vpb = touchManager.getPreviousPoint(1);
Vector2D current = touchManager.getVector(0, 1);
Vector2D previous = touchManager.getPreviousVector(0, 1);
float currentDistance = current.getLength();
float previousDistance = previous.getLength();
if (previousDistance != 0) {
scale *= currentDistance / previousDistance;
}
angle -= Vector2D.getSignedAngleBetween(current, previous);
}
}
invalidate();
}
catch(Throwable t) {
// So lazy...
}
System.out.println("mFlagDrawing: " + mFlagDrawing);
// Code for Zoom start
// detector.onTouchEvent(event);
// mScaleDetector.onTouchEvent(event);
// Code for Zoom finish
} else if (mFlagDrawing == false) {
System.out.println("mFlagDrawing: " + mFlagDrawing);
for (int p = 0; p < pointerCount; p++) {
final int id = MotionEventCompat.getPointerId(event, p);
mDrawOps.push(mCurrentOps.get(id));
mCurrentOps.remove(id);
// }
updateLayer();
}
}
// }
break;
case MotionEvent.ACTION_CANCEL: {
if (mFlagDrawing == true) {
// mActivePointerId = INVALID_POINTER_ID;
try {
touchManager.update(event);
if (touchManager.getPressCount() == 1) {
vca = touchManager.getPoint(0);
vpa = touchManager.getPreviousPoint(0);
position.add(touchManager.moveDelta(0));
}
else {
if (touchManager.getPressCount() == 2) {
vca = touchManager.getPoint(0);
vpa = touchManager.getPreviousPoint(0);
vcb = touchManager.getPoint(1);
vpb = touchManager.getPreviousPoint(1);
Vector2D current = touchManager.getVector(0, 1);
Vector2D previous = touchManager.getPreviousVector(0, 1);
float currentDistance = current.getLength();
float previousDistance = previous.getLength();
if (previousDistance != 0) {
scale *= currentDistance / previousDistance;
}
angle -= Vector2D.getSignedAngleBetween(current, previous);
}
}
invalidate();
}
catch(Throwable t) {
// So lazy...
}
System.out.println("mFlagDrawing: " + mFlagDrawing);
// Code for Zoom start
// detector.onTouchEvent(event);
// mScaleDetector.onTouchEvent(event);
// Code for Zoom finish
} else if (mFlagDrawing == false) {
System.out.println("mFlagDrawing: " + mFlagDrawing);
for (int p = 0; p < pointerCount; p++) {
mCurrentOps
.remove(MotionEventCompat.getPointerId(event, p));
}
}
// mFlagZoom = true;
// }
}
break;
/*case MotionEvent.ACTION_POINTER_UP: {
final int pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
final int pointerId = event.getPointerId(pointerIndex);
if (pointerId == mActivePointerId) {
// This was our active pointer going up. Choose a new
// active pointer and adjust accordingly.
final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
mLastTouchX = event.getX(newPointerIndex) / mScaleFactor;
mLastTouchY = event.getY(newPointerIndex) / mScaleFactor;
mActivePointerId = event.getPointerId(newPointerIndex);
}
break;
}*/
default:
return false;
}
invalidate();
return true;
}
#Override
protected void onSizeChanged(int w, int h, int oldW, int oldH) {
super.onSizeChanged(w, h, oldW, oldH);
/*mLayerBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mLayerCanvas.setBitmap(mLayerBitmap);*/
if(mLayerBitmap == null){
mLayerBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
}else{
Bitmap temporary = Bitmap.createScaledBitmap(mLayerBitmap, w, h, true);
mLayerBitmap = temporary;
}
mLayerCanvas = new Canvas(mLayerBitmap);
// mLayerCanvas.rotate(90);
/* matrix.setTranslate(1.5f,1.5f);
matrix.postRotate(90, 2.5f, 2.5f);*/
// updateLayer();
/* //Reset the width and height. Will draw bitmap and change
containerWidth = w;
containerHeight = h;
if(mLayerBitmap != null) {
int imgHeight = mLayerBitmap.getHeight();
int imgWidth = mLayerBitmap.getWidth();
float scale;
int initX = 0;
int initY = 0;
if(defaultScale == DrawingView.DEFAULT_SCALE_FIT_INSIDE) {
if(imgWidth > containerWidth) {
scale = (float)containerWidth / imgWidth;
float newHeight = imgHeight * scale;
initY = (containerHeight - (int)newHeight)/2;
matrix.setScale(scale, scale);
matrix.postTranslate(0, initY);
}
else {
scale = (float)containerHeight / imgHeight;
float newWidth = imgWidth * scale;
initX = (containerWidth - (int)newWidth)/2;
matrix.setScale(scale, scale);
matrix.postTranslate(initX, 0);
}
curX = initX;
curY = initY;
currentScale = scale;
minScale = scale;
}
else {
if(imgWidth > containerWidth) {
initY = (containerHeight - (int)imgHeight)/2;
matrix.postTranslate(0, initY);
}
else {
initX = (containerWidth - (int)imgWidth)/2;
matrix.postTranslate(initX, 0);
}
curX = initX;
curY = initY;
currentScale = 1.0f;
minScale = 1.0f;
}
invalidate();
}*/
}
private void updateLayer() {
mLayerCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
for (DrawOp drawOp : mDrawOps) {
if (drawOp != null) {
drawOp.draw(mLayerCanvas);
}
}
invalidate();
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (isInEditMode()) {
return;
}
// if(mFlagDrawing == true){
if (!isInitialized) {
int w = getWidth();
int h = getHeight();
position.set(w / 2, h / 2);
isInitialized = true;
}
mWidth = mLayerBitmap.getWidth();
mHeight = mLayerBitmap.getHeight();
// Code for Zoom start
/* canvas.save();
canvas.scale(mScaleFactor, mScaleFactor, focusX, focusY);
canvas.translate(mPosX, mPosY);*/
// canvas.scale(scaleFactor, scaleFactor);
/*canvas.scale(mScaleFactor, mScaleFactor, super.getWidth() * 0.5f,
super.getHeight() * 0.5f);*/
// Code for Zoom finish
// canvas.save();
transform.reset();
transform.postTranslate(-mWidth / 2.0f, -mHeight / 2.0f);
// transform.postRotate(getDegreesFromRadians(angle));
transform.postScale(scale, scale);
transform.postTranslate(position.getX(), position.getY());
canvas.drawBitmap(mLayerBitmap, transform, null);
// }
// else if(mFlagDrawing == false){
// canvas.drawBitmap(mLayerBitmap, 0, 0, null);
for (int i = 0; i < mCurrentOps.size(); i++) {
DrawOp current = mCurrentOps.valueAt(i);
if (current != null) {
current.draw(canvas);
}
}
// }
// Code for Zoom
// canvas.restore();
}
public void operationClear() {
mDrawOps.clear();
mUndoOps.clear();
mCurrentOps.clear();
updateLayer();
}
public void operationUndo() {
if (mDrawOps.size() > 0) {
mUndoOps.push(mDrawOps.pop());
updateLayer();
}
}
public void operationRedo() {
if (mUndoOps.size() > 0) {
mDrawOps.push(mUndoOps.pop());
updateLayer();
}
}
public void setPaintStrokeWidth(float widthPx) {
mDefaultPaint.setStrokeWidth(widthPx);
}
public void setPaintOpacity(int percent) {
int alphaValue = (int) Math.round(percent * (255.0 / 100.0));
mDefaultPaint.setColor(combineAlpha(mDefaultPaint.getColor(),
alphaValue));
}
public void setPaintColor(String color) {
mDefaultPaint.setColor(combineAlpha(Color.parseColor(color), mDefaultPaint.getAlpha()));
}
public void setPaintColor(int color) {
mDefaultPaint.setColor(combineAlpha(color, mDefaultPaint.getAlpha()));
}
public void setPaintMaskFilter(MaskFilter filter) {
mDefaultPaint.setMaskFilter(filter);
}
public void setPaintShader(BitmapShader shader) {
mDefaultPaint.setShader(shader);
}
public void setPaintColorFilter(ColorFilter colorFilter) {
mDefaultPaint.setColorFilter(colorFilter);
}
private static int combineAlpha(int color, int alpha) {
return (color & 0x00FFFFFF) | ((alpha & 0xFF) << 24);
}
private static class DrawOp {
private float x,y;
private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private final Path mPath = new Path();
public DrawOp(Paint paint) {
reset(paint);
}
/*public void add(Vector2D moveDelta) {
// TODO Auto-generated method stub
this.x += moveDelta.getX();
this.y += moveDelta.getY();
}*/
void reset(Paint paint) {
mPath.reset();
update(paint);
}
void update(Paint paint) {
mPaint.set(paint);
}
void draw(Canvas canvas) {
canvas.drawPath(mPath, mPaint);
}
public Path getPath() {
return mPath;
}
/* public DrawOp add(DrawOp value) {
this.x += value.getX();
this.y += value.getY();
return this;
}*/
/*public float getX() {
return x;
}
public float getY() {
return y;
}*/
}
public void fillShapeColor(){
}
// Code for Zoom
/* private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
#Override
public boolean onScale(ScaleGestureDetector detector) {
scaleFactor *= detector.getScaleFactor();
scaleFactor = Math.max(MIN_ZOOM, Math.min(scaleFactor, MAX_ZOOM));
invalidate();
return true;
}
}*/
private class ScaleListener extends
ScaleGestureDetector.SimpleOnScaleGestureListener {
#Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
// float x = detector.getFocusX();
// float y = detector.getFocusY();
lastFocusX = -1;
lastFocusY = -1;
return true;
}
#Override
public boolean onScale(ScaleGestureDetector detector) {
mScaleFactor *= detector.getScaleFactor();
focusX = detector.getFocusX();
focusY = detector.getFocusY();
if (lastFocusX == -1)
lastFocusX = focusX;
if (lastFocusY == -1)
lastFocusY = focusY;
mPosX += (focusX - lastFocusX);
mPosY += (focusY - lastFocusY);
Log.v("Hi Zoom", "Factor:" + mScaleFactor);
// Don't let the object get too small or too large.
mScaleFactor = Math.max(0.5f, Math.min(mScaleFactor, 2.0f));
lastFocusX = focusX;
lastFocusY = focusY;
invalidate();
return true;
}
}
/* #Override
public Parcelable onSaveInstanceState()
{
System.out.println("save instance");
Bundle bundle = new Bundle();
bundle.putParcelable(EXTRA_STATE, super.onSaveInstanceState());
bundle.putParcelableArrayList(EXTRA_EVENT_LIST, eventList);
return bundle;
}
#Override
public void onRestoreInstanceState(Parcelable state)
{
if (state instanceof Bundle)
{
Bundle bundle = (Bundle) state;
super.onRestoreInstanceState(bundle.getParcelable(EXTRA_STATE));
eventList = bundle.getParcelableArrayList(EXTRA_EVENT_LIST);
if (eventList == null) {
eventList = new ArrayList<MotionEvent>(100);
}
for (MotionEvent event : eventList) {
// performTouchEvent(event);
}
return;
}
super.onRestoreInstanceState(state);
}*/
public void setDrawingFlag(boolean flag) {
// System.out.println("Before Set mFlag " + mFlagDrawing);
this.mFlagDrawing = flag;
// System.out.println("After Set mFlag " + mFlagDrawing);
}
public void moveCanvas(float x, float y) {
float dx = x - mLastTouchX;
float dy = y - mLastTouchY;
// Adjust for zoom factor. Otherwise, the user's finger moving 10 pixels
// at 200% zoom causes the image to slide 20 pixels instead of perfectly
// following the user's touch
dx /= (mScaleFactor * 2);
dy /= (mScaleFactor * 2);
mPosX += dx;
mPosY += dy;
// Log.v(TAG, "moving by " + dx + "," + dy + " mScaleFactor: " +
// mScaleFactor);
}
}
I found mistake and correct it by my self. Below is my code.
public void resetZoom() {
mPanX = mPanY = 0;
final Matrix m = new Matrix();
m.postScale(1f / DENSITY, 1f / DENSITY);
setZoom(m);
invalidate();
}
public void setZoomPosNoInval(float x, float y) {
mPanX = x;
mPanY = y;
}
public void setZoomPos(float x, float y) {
setZoomPosNoInval(x, y);
invalidate();
}
public void setZoomPosNoInval(float[] pos) {
setZoomPosNoInval(pos[0], pos[1]);
}
public void setZoomPos(float[] pos) {
setZoomPosNoInval(pos);
invalidate();
}
public float[] getZoomPos(float[] pos) {
if (pos == null)
pos = new float[2];
pos[0] = mPanX;
pos[1] = mPanY;
return pos;
}
public float getZoomPosX() {
return mPanX;
}
public float getZoomPosY() {
return mPanY;
}
public Matrix getZoom() {
return mZoomMatrix;
}
public Matrix getZoomInv() {
return mZoomMatrixInv;
}
public void setZoom(Matrix m) {
mZoomMatrix.set(m);
mZoomMatrix.invert(mZoomMatrixInv);
}

how to change the intent when ball touch the bottom or top the canvas

in my game ball moves from top to bottom and bottom to top,my requirement is when ball touches top edge or bottom edge i want to print a toast message like "game over".later i want to move control some other intent.to animate the ball i am using following code
public class AnimatedView extends ImageView{
static int count=0;
private Context mContext;
int x = 130;
int y = 450;
private float a,b;
private int xVelocity = 25;
private int yVelocity = 20;
private Handler h;
private final int FRAME_RATE = 30;
BitmapDrawable ball;
boolean touching;
boolean dm_touched = false;
float move=3;
int bm_x = 0, bm_y = 0, bm_offsetx, bm_offsety,bm_w,bm_h;
boolean paused;
public AnimatedView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
h = new Handler();
}
#Override
public void buildDrawingCache() {
// TODO Auto-generated method stub
super.buildDrawingCache();
}
private Runnable r = new Runnable() {
#Override
public void run() {
//Log.e("game","run called");
if(touching = true)
invalidate();
}
};
#Override
protected void onDraw(Canvas c) {
BitmapDrawable ball = (BitmapDrawable) mContext.getResources().getDrawable(R.drawable.ball);
if (x<0 && y <0) {
//x = this.getWidth()/2;
y = c.getHeight()/2;
} else {
y += yVelocity;
if (y >( this.getHeight() - ball.getBitmap().getHeight()) ||y <0) {
yVelocity = yVelocity*-1;
}
}
c.drawBitmap(ball.getBitmap(), x, y, null);
//Log.e("sarat",""+touching);
if(touching){
// Log.e("game","iftouch called called");
h.postDelayed(r, FRAME_RATE);
bm_w=ball.getBitmap().getWidth();
bm_h=ball.getBitmap().getHeight();
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
// Log.d("game","ontouch called");
int touchType = event.getAction();
switch(touchType){
case MotionEvent.ACTION_MOVE:
a = event.getX();
b = event.getY();
touching = true;
if ((a > x) && (a < bm_w + x) && (b > y) && (b < bm_h + y))
{
if(bm_h+a>600 ||bm_h+b<0){
Toast.makeText(getContext(),"game over",Toast.LENGTH_LONG).show();
}
break;
case MotionEvent.ACTION_DOWN:
//x and y give you your touch coordinates
a = event.getX();
b = event.getY();
touching = true;
Log.e("s",""+ a);
Log.e("s",""+ b);
Log.e("s",""+ x);
Log.e("s",""+ y);
Log.e("s",""+ bm_w);
Log.e("s",""+ bm_h);
if ((a > x) && (a < bm_w + x) && (b > y) && (b < bm_h + y)) {
count++;
MainActivity.setCount(count);
Log.i("score",""+count);
}
if (dm_touched) {
if ((a > x) && (a < bm_w + x) && (b > y) && (b < bm_h + y)) {
move+=2;
y = yVelocity*-1;
}}
case MotionEvent.ACTION_UP:
a = event.getX();
b = event.getY();
if(a>x+20&&a<330&&b<=y+320&&b>y){
invalidate();}
if ((a > x) && (a < bm_w + x) && (b > y) && (b < bm_h + y)) {
Log.e("game","clicked");
}
default:
dm_touched = true;
}
return true;
}
#Override
public void destroyDrawingCache() {
count=0;
super.destroyDrawingCache();
}
}

how to move object inside the canvas when object was touched?

I'm new to Android, and I'm having problems moving an object inside onDraw(Canvas c).
Below is my code. I hope someone can tell me how to fix it.
public class GameviewLuzon1 extends ImageView {
int y = 0;
int x = 0;
int obj1 = R.drawable.obj_androidball;
int obj2 = R.drawable.obj_drum;
/****************************************/
Drawable dr1 = getResources().getDrawable(obj1);
Bitmap bitmap1 = ((BitmapDrawable) dr1).getBitmap();
Drawable d1 = new BitmapDrawable(getResources(), Bitmap.createScaledBitmap(bitmap1, 20, 20, true));
float d1_startX = (float) 0.00;
float d1_startY = (float) 0.00;
float d1_movementX = 2;
float d1_movementY = 2;
Drawable dr2 = getResources().getDrawable(obj2);
Bitmap bitmap2 = ((BitmapDrawable) dr2).getBitmap();
Drawable d2 = new BitmapDrawable(getResources(), Bitmap.createScaledBitmap(bitmap2, 35, 35, true));
float d2_startX = (float) 0.00;
float d2_startY = (float) 0.00;
/****************************************/
public GameviewLuzon1(Context context, AttributeSet attrs) {
super(context, attrs);
}
protected void onDraw(Canvas c) {
d1_startX = (float) (this.getWidth()/d1_movementX);
d1_startY = (float) (this.getHeight()/d1_movementY);
d2_startX = (float) (this.getWidth()/5.75);
d2_startY = (float) (this.getHeight()/7.99);
/****************************************/
c.drawBitmap(((BitmapDrawable) d1).getBitmap(), d1_startX, d1_startY, null);
c.drawBitmap(((BitmapDrawable) d2).getBitmap(), d2_startX, d2_startY, null);
/****************************************/
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float touchX = event.getX();
float touchY = event.getY();
if( touchX >= d1_startX && touchX <= (d1_startX + d1.getIntrinsicWidth())
&& touchY >= d1_startY && touchY <= (d1_startY +d1.getIntrinsicHeight())) {
Log.w("d1 success","you touched object");
d1_movementX = 0;
d1_movementY = 0;
}
else if( touchX >= d2_startX && touchX <= (d2_startX + d2.getIntrinsicWidth())
&& touchY >= d2_startY && touchY <= (d2_startY +d2.getIntrinsicHeight())) {
Log.w("d2 success","you touched object");
invalidate();
}
else {
Log.w("epic","wala jud ka kaigu");
}
/*Commented out for debugging purpose only*/
/*Log.w("touch",Float.toString(touchX));
Log.w("start of Image",Float.toString(d1_startX));
Log.w("edge of image",Float.toString(d1_startX + d1.getIntrinsicWidth()));*/
return true;
}
}
public class Game1LuzonAnimation extends ImageView {
int y = 0;
int x = 0;
int zoomControler = 0;
/*****************TEST*******************/
private Context mContext;
private Handler h;
private final int FRAME_RATE = 30;
private int xVelocity = 10;
boolean animateObj = false;
boolean setVisibleObj = true;
/*****************TEST*******************/
/*Create variable obj1 and so on, so that
* we can create a dynamic objects..,
* if we need it to be dynamic.
* */
int obj1 = R.drawable.obj_androidball;
int obj2 = R.drawable.obj_drum;
/****************************************/
/* Assign some obj values into their respective places and
* set their sizes to fit in our screen sizes
* */
Drawable dr1 = getResources().getDrawable(obj1);
Bitmap bitmap1 = ((BitmapDrawable) dr1).getBitmap();
Drawable d1 = new BitmapDrawable(getResources(), Bitmap.createScaledBitmap(bitmap1, 20, 20, true));
float d1max_width = d1.getIntrinsicWidth() * 2;
float d1max_height = d1.getIntrinsicHeight() * 2;
float d1_startX = (float) 0.00; //initialize the position value of first object
float d1_startY = (float) 0.00; //initialize the position value of first object
/****************************************/
public Game1LuzonAnimation(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
h = new Handler();
}
private Runnable r = new Runnable() {
#Override
public void run() {
invalidate();
}
};
protected void onDraw(Canvas c) {
/* put the values for position of each object from database;
* */
if(animateObj == false){
d1_startX = (float) (c.getWidth()/2);
d1_startY = (float) (c.getHeight()/2);
}
else {
if (d1_startX < 0) {
animateObj = false;
setVisibleObj = false;
}
else {
d1_startX -= xVelocity;
if(d1_startX > c.getWidth()){
xVelocity = xVelocity*-1;
}
}
}
if(setVisibleObj == true) {
c.drawBitmap(((BitmapDrawable) d1).getBitmap(), d1_startX, d1_startY, null);
h.postDelayed(r, FRAME_RATE);
}
/*Log.w("d1max_width", Float.toString(d1max_width));
Log.w("d1max_height", Float.toString(d1max_height));
Log.w("d1_startX", Float.toString(d1_startX));
Log.w("d1_startY", Float.toString(d1_startY));*/
/****************************************/
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float touchX = event.getX();
float touchY = event.getY();
if( touchX >= d1_startX && touchX <= (d1_startX + d1.getIntrinsicWidth())
&& touchY >= d1_startY && touchY <= (d1_startY +d1.getIntrinsicHeight())) {
Log.w("d1 success","you touched object");
if(d1.getIntrinsicWidth() < d1max_width && d1.getIntrinsicHeight() < d1max_height) {
d1 = new BitmapDrawable(getResources(), Bitmap.createScaledBitmap(bitmap1, d1.getIntrinsicWidth()*2, d1.getIntrinsicHeight()*2, true));
animateObj = true;
}
}
else {
Log.w("epic","wala jud ka kaigu");
}
return true;
}
}

rotate and resize the image view with single finger in android

I am developing an app which has feature that resizing and rotating the imageview by dragging its bottom right corner button.
I saw one app which has feature that if we drag the bottom right corner button diagonally imageview size had resized or else if we drag the button left or right side direction imageview had rotated as per direction. I wish to implement this feature in my app
I am struggling to implement single finger rotation as well as resizing the imageview.
Please guide me in right way.
I am trying this code, and try to apply zoom and rotate but not able to do please help me.
belove code to do zoom and rotate finger base action.
public class ScaleActivity extends Activity {
ViewGroup lLayout;
static ImageView img, backgrndImg;
Canvas mCanvas;
float d;
private float mAspectQuotient;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lLayout = (FrameLayout) findViewById(R.id.lLayout);
final CropView cv = new CropView(this);
lLayout.addView(cv);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public class CropView extends ImageView {
private static final int SELECTION_RECT_PAINT_COLOR = 0xFF000000;
private static final int SELECTION_RECT_FILL_COLOR = 0x70FFFFFF;
private static final int TOUCH_TOLERANCE = 25;
private static final int xInc = 25;
private static final int yInc = 25;
Paint paint = new Paint();
private int initial_size = 200;
private Point leftTop, rightBottom, center, previous, currentPoint,
rectPos;
private Paint fillPaint;
private Paint rectPaint;
protected Rect selection, dest;
private boolean isAffectedBottom = false;
Bitmap bitmap, backgroundBitmap;
Rect rectf;
Rect knobRect;
private Context mContext;
int width, height;
private Matrix matrix = new Matrix();
Bitmap resizedBitmap;
// Adding parent class constructors
public CropView(Context context) {
super(context);
mContext = context;
backgroundBitmap = BitmapFactory.decodeResource(getContext()
.getResources(), R.drawable.toast_bkgrd);
bitmap = BitmapFactory.decodeResource(getContext().getResources(),
R.drawable.aviary_adjust_knob);
rectPaint = new Paint();
rectPaint.setStyle(Style.STROKE);
rectPaint.setColor(SELECTION_RECT_PAINT_COLOR);
fillPaint = new Paint();
fillPaint.setStyle(Style.FILL);
fillPaint.setColor(SELECTION_RECT_FILL_COLOR);
currentPoint = new Point(getWidth() / 2, getHeight() / 2);
width = backgroundBitmap.getWidth();
height = backgroundBitmap.getHeight();
initCropView();
}
public CropView(Context context, AttributeSet attrs) {
super(context, attrs, 0);
initCropView();
}
public CropView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initCropView();
}
#SuppressLint("DrawAllocation")
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mCanvas = canvas;
if (leftTop.equals(0, 0))
resetPoints();
mCanvas.save();
resizedBitmap = Bitmap.createBitmap(backgroundBitmap, 0, 0,
backgroundBitmap.getWidth(), backgroundBitmap.getHeight(),
matrix, true);
// mCanvas.drawBitmap(backgroundBitmap, matrix, rectPaint);
mCanvas.drawBitmap(resizedBitmap, null, selection, rectPaint);
mCanvas.drawBitmap(bitmap, selection.right - 25,
selection.bottom - 25, null);
rectPos.set(selection.left, selection.top);
mCanvas.restore();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
int eventaction = event.getAction();
switch (eventaction) {
case MotionEvent.ACTION_DOWN:
touchDown((int) event.getX(), (int) event.getY());
previous.set((int) event.getX(), (int) event.getY());
break;
case MotionEvent.ACTION_MOVE:
touchMove((int) event.getX(), (int) event.getY());
if (isActionInsideRectangle(event.getX(), event.getY())
&& !isAffectedBottom) {
drag((int) event.getX(), (int) event.getY());
invalidate(); // redraw rectangle
previous.set((int) event.getX(), (int) event.getY());
}
previous.set((int) event.getX(), (int) event.getY());
break;
case MotionEvent.ACTION_UP:
touchUp((int) event.getX(), (int) event.getY());
previous = new Point();
break;
}
return true;
}
private void initCropView() {
paint.setColor(Color.WHITE);
paint.setStyle(Style.STROKE);
paint.setStrokeWidth(5);
leftTop = new Point();
rightBottom = new Point();
center = new Point();
previous = new Point();
rectPos = new Point();
}
public void resetPoints() {
center.set(getWidth() / 2, getHeight() / 2);
leftTop.set((getWidth() - initial_size) / 2,
(getHeight() - initial_size) / 2);
rightBottom.set(leftTop.x + initial_size, leftTop.y + initial_size);
selection = new Rect(leftTop.x, leftTop.y, rightBottom.x,
rightBottom.y);
knobRect = new Rect(selection.right, selection.bottom,
bitmap.getWidth(), bitmap.getHeight());
dest = selection;
}
private boolean isActionInsideRectangle(float x, float y) {
int buffer = 10;
return (x >= (selection.left) && x <= (selection.right)
&& y >= (selection.top) && y <= (selection.bottom)) ? true
: false;
}
void touchDown(int x, int y) {
System.out.println("selection " + selection);
int dx = (previous.x - x) / 2;
int dy = (previous.y - y) / 2;
// d= rotation(dx,dy);
currentPoint.set(x, y);
if (pointsAreClose(x, y, selection.right, selection.bottom)) {
isAffectedBottom = true;
System.out.println("isAffectedBottom " + isAffectedBottom);
}
}
void touchMove(int x, int y) {
currentPoint.set(x, y);
if (isAffectedBottom) {
int dx = (previous.x - x) / 2;
int dy = (previous.y - y) / 2;
double startAngle = getAngle(previous.x, previous.y);
double currentAngle = getAngle(x, y);
matrix.postRotate((float) (startAngle - currentAngle),
selection.width() / 2.0f, selection.height() / 2.0f);
// selection.inset(dx, dy);
invalidate();
}
}
void touchUp(int x, int y) {
currentPoint.set(x, y);
isAffectedBottom = false;
}
private boolean pointsAreClose(float x1, float y1, float x2, float y2) {
return Math.hypot(x1 - x2, y1 - y2) < TOUCH_TOLERANCE;
}
private void drag(int x, int y) {
int movement;
movement = x - previous.x;
int movementY = y - previous.y;
selection.set(selection.left + movement, selection.top + movementY,
selection.right + movement, selection.bottom + movementY);
selection.sort();
invalidate();
}
/**
* Calculate the degree to be rotated by.
*
* #param event
* #return Degrees
*/
// private float rotation(float dx, float dy) {
//
// // double delta_x = (dx);
// // double delta_y = (dy);
// double radians = Math.atan2((selection.left) - (previous.y),
// (selection.top) - (previous.x));
// double radians2 = Math.atan2((selection.left) - (dy),
// (selection.top) - (dx));
//
// System.out.println("radians" + radians);
// System.out.println("" + radians2);
// System.out.println("radians2-radians" + (radians2 - radians));
// System.out.println(Math.toDegrees(radians2 - radians));
// return (float) Math.toDegrees(radians2 - radians);
//
// }
private double getAngle(double xTouch, double yTouch) {
double x = xTouch - (getWidth() / 2d);
double y = getHeight() - yTouch - (getHeight() / 2d);
switch (getQuadrant(x, y)) {
case 1:
System.out.println("1");
return Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI;
case 2:
case 3:
System.out.println("32");
return 180 - (Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI);
case 4:
System.out.println("4");
return 360 + Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI;
default:
// ignore, does not happen
return 0;
}
}
/**
* #return The selected quadrant.
*/
private int getQuadrant(double x, double y) {
if (x >= 0) {
return y >= 0 ? 1 : 4;
} else {
return y >= 0 ? 2 : 3;
}
}
}
}
I have Design A Layout that may work as your need.
Download Demo here
Java File
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.RelativeLayout;
public class ClipArt extends RelativeLayout {
int baseh;
int basew;
int basex;
int basey;
ImageButton btndel;
ImageButton btnrot;
ImageButton btnscl;
RelativeLayout clip;
Context cntx;
boolean freeze = false;
int h;
int i;
ImageView image;
String imageUri;
boolean isShadow;
int iv;
RelativeLayout layBg;
RelativeLayout layGroup;
RelativeLayout.LayoutParams layoutParams;
public LayoutInflater mInflater;
int margl;
int margt;
float opacity = 1.0F;
Bitmap originalBitmap;
int pivx;
int pivy;
int pos;
Bitmap shadowBitmap;
float startDegree;
String[] v;
public ClipArt(Context paramContext) {
super(paramContext);
cntx = paramContext;
layGroup = this;
basex = 0;
basey = 0;
pivx = 0;
pivy = 0;
mInflater = ((LayoutInflater) paramContext.getSystemService("layout_inflater"));
mInflater.inflate(R.layout.clipart, this, true);
btndel = ((ImageButton) findViewById(R.id.del));
btnrot = ((ImageButton) findViewById(R.id.rotate));
btnscl = ((ImageButton) findViewById(R.id.sacle));
layoutParams = new RelativeLayout.LayoutParams(250, 250);
layGroup.setLayoutParams(layoutParams);
image = ((ImageView) findViewById(R.id.clipart));
image.setImageResource(R.drawable.ic_launcher);
setOnTouchListener(new View.OnTouchListener() {
final GestureDetector gestureDetector = new GestureDetector(ClipArt.this.cntx,
new GestureDetector.SimpleOnGestureListener() {
public boolean onDoubleTap(MotionEvent paramAnonymous2MotionEvent) {
return false;
}
});
public boolean onTouch(View paramAnonymousView, MotionEvent event) {
if (!ClipArt.this.freeze) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
layGroup.invalidate();
gestureDetector.onTouchEvent(event);
layGroup.performClick();
basex = ((int) (event.getRawX() - layoutParams.leftMargin));
basey = ((int) (event.getRawY() - layoutParams.topMargin));
break;
case MotionEvent.ACTION_MOVE:
int i = (int) event.getRawX();
int j = (int) event.getRawY();
layBg = ((RelativeLayout) getParent());
if ((i - basex > -(layGroup.getWidth() * 2 / 3))
&& (i - basex < layBg.getWidth() - layGroup.getWidth() / 3)) {
layoutParams.leftMargin = (i - basex);
}
if ((j - basey > -(layGroup.getHeight() * 2 / 3))
&& (j - basey < layBg.getHeight() - layGroup.getHeight() / 3)) {
layoutParams.topMargin = (j - basey);
}
layoutParams.rightMargin = -1000;
layoutParams.bottomMargin = -1000;
layGroup.setLayoutParams(layoutParams);
break;
}
return true;
}
return true;
}
});
this.btnscl.setOnTouchListener(new View.OnTouchListener() {
#SuppressLint({ "NewApi" })
public boolean onTouch(View paramAnonymousView, MotionEvent event) {
if (!ClipArt.this.freeze) {
int j = (int) event.getRawX();
int i = (int) event.getRawY();
layoutParams = (RelativeLayout.LayoutParams) layGroup.getLayoutParams();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
ClipArt.this.layGroup.invalidate();
ClipArt.this.basex = j;
ClipArt.this.basey = i;
ClipArt.this.basew = ClipArt.this.layGroup.getWidth();
ClipArt.this.baseh = ClipArt.this.layGroup.getHeight();
int[] loaction = new int[2];
layGroup.getLocationOnScreen(loaction);
margl = layoutParams.leftMargin;
margt = layoutParams.topMargin;
break;
case MotionEvent.ACTION_MOVE:
float f2 = (float) Math.toDegrees(Math.atan2(i - ClipArt.this.basey, j - ClipArt.this.basex));
float f1 = f2;
if (f2 < 0.0F) {
f1 = f2 + 360.0F;
}
j -= ClipArt.this.basex;
int k = i - ClipArt.this.basey;
i = (int) (Math.sqrt(j * j + k * k)
* Math.cos(Math.toRadians(f1 - ClipArt.this.layGroup.getRotation())));
j = (int) (Math.sqrt(i * i + k * k)
* Math.sin(Math.toRadians(f1 - ClipArt.this.layGroup.getRotation())));
k = i * 2 + ClipArt.this.basew;
int m = j * 2 + ClipArt.this.baseh;
if (k > 150) {
layoutParams.width = k;
layoutParams.leftMargin = (ClipArt.this.margl - i);
}
if (m > 150) {
layoutParams.height = m;
layoutParams.topMargin = (ClipArt.this.margt - j);
}
ClipArt.this.layGroup.setLayoutParams(layoutParams);
ClipArt.this.layGroup.performLongClick();
break;
}
return true;
}
return ClipArt.this.freeze;
}
});
this.btnrot.setOnTouchListener(new View.OnTouchListener() {
#SuppressLint({ "NewApi" })
public boolean onTouch(View paramAnonymousView, MotionEvent event) {
if (!ClipArt.this.freeze) {
layoutParams = (RelativeLayout.LayoutParams) ClipArt.this.layGroup.getLayoutParams();
ClipArt.this.layBg = ((RelativeLayout) ClipArt.this.getParent());
int[] arrayOfInt = new int[2];
layBg.getLocationOnScreen(arrayOfInt);
int i = (int) event.getRawX() - arrayOfInt[0];
int j = (int) event.getRawY() - arrayOfInt[1];
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
ClipArt.this.layGroup.invalidate();
ClipArt.this.startDegree = layGroup.getRotation();
ClipArt.this.pivx = (layoutParams.leftMargin + ClipArt.this.getWidth() / 2);
ClipArt.this.pivy = (layoutParams.topMargin + ClipArt.this.getHeight() / 2);
ClipArt.this.basex = (i - ClipArt.this.pivx);
ClipArt.this.basey = (ClipArt.this.pivy - j);
break;
case MotionEvent.ACTION_MOVE:
int k = ClipArt.this.pivx;
int m = ClipArt.this.pivy;
j = (int) (Math.toDegrees(Math.atan2(ClipArt.this.basey, ClipArt.this.basex))
- Math.toDegrees(Math.atan2(m - j, i - k)));
i = j;
if (j < 0) {
i = j + 360;
}
ClipArt.this.layGroup.setRotation((ClipArt.this.startDegree + i) % 360.0F);
break;
}
return true;
}
return ClipArt.this.freeze;
}
});
this.btndel.setOnClickListener(new View.OnClickListener() {
public void onClick(View paramAnonymousView) {
if (!ClipArt.this.freeze) {
layBg = ((RelativeLayout) ClipArt.this.getParent());
layBg.performClick();
layBg.removeView(ClipArt.this.layGroup);
}
}
});
}
public void disableAll() {
this.btndel.setVisibility(4);
this.btnrot.setVisibility(4);
this.btnscl.setVisibility(4);
}
public ImageView getImageView() {
return this.image;
}
public void setFreeze(boolean paramBoolean) {
this.freeze = paramBoolean;
}
}
Layout file
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent">
<ImageButton android:id="#+id/rotate" android:layout_width="50dp" android:layout_height="50dp" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:adjustViewBounds="true" android:background="#android:color/transparent" android:scaleType="fitCenter" android:src="#drawable/rotation"/>
<ImageButton android:id="#+id/sacle" android:layout_width="50dp" android:layout_height="50dp" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:adjustViewBounds="true" android:background="#android:color/transparent" android:scaleType="fitCenter" android:src="#drawable/pointer"/>
<ImageButton android:id="#+id/del" android:layout_width="50dp" android:layout_height="50dp" android:layout_alignParentRight="true" android:layout_alignParentTop="true" android:adjustViewBounds="true" android:background="#android:color/transparent" android:scaleType="fitCenter" android:src="#drawable/close"/>
<ImageView android:id="#+id/clipart" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="10dp"/>
</RelativeLayout>
and images put in drawable
please check the repository in github i create it .
count the distance from center point in the rotate and zoom view to the push point.
just use :
private float getDistance(Point a, Point b) {
float v = ((a.x - b.x) * (a.x - b.x)) + ((a.y - b.y) * (a.y - b.y));
return ((int) (Math.sqrt(v) * 100)) / 100f;
}
and count the OA/OB that value can count the view new height and width
count the angle AOB, the A is the first push point , the B is the last move point ,the O is the center of the View Point .
and then just set new height and width for view ,and count the left and top for view .
souce link : https://github.com/ryanch741/android-view-rotate-zoom-single-finger
the code:
Point pushPoint;
int lastImgWidth;
int lastImgHeight;
int lastImgLeft;
int lastImgTop;
int lastImgAngle;
double lastComAngle;
int pushImgWidth;
int pushImgHeight;
int lastPushBtnLeft;
int lastPushBtnTop;
private View mView;
private Point mViewCenter;
private static final double PI = 3.14159265359;
public PushBtnTouchListener(View mView) {
this.mView = mView;
}
private FrameLayout.LayoutParams pushBtnLP;
private FrameLayout.LayoutParams imgLP;
float lastX = -1;
float lastY = -1;
#Override
public boolean onTouch(View pushView, MotionEvent event) {
switch (event.getAction() & MotionEvent.ACTION_MASK) {
// 主点按下
case MotionEvent.ACTION_DOWN:
pushBtnLP = (FrameLayout.LayoutParams) pushView.getLayoutParams();
imgLP = (FrameLayout.LayoutParams) mView.getLayoutParams();
pushPoint = getPushPoint(pushBtnLP, event);
lastImgWidth = imgLP.width;
lastImgHeight = imgLP.height;
lastImgLeft = imgLP.leftMargin;
lastImgTop = imgLP.topMargin;
lastImgAngle = (int) mView.getRotation();
lastPushBtnLeft = pushBtnLP.leftMargin;
lastPushBtnTop = pushBtnLP.topMargin;
pushImgWidth = pushBtnLP.width;
pushImgHeight = pushBtnLP.height;
lastX = event.getRawX();
lastY = event.getRawY();
refreshImageCenter();
break;
// 副点按下
case MotionEvent.ACTION_POINTER_DOWN:
break;
case MotionEvent.ACTION_UP: {
break;
}
case MotionEvent.ACTION_POINTER_UP:
break;
case MotionEvent.ACTION_MOVE:
float rawX = event.getRawX();
float rawY = event.getRawY();
if (lastX != -1) {
if (Math.abs(rawX - lastX) < 5 && Math.abs(rawY - lastY) < 5) {
return false;
}
}
lastX = rawX;
lastY = rawY;
Point O = mViewCenter, A = pushPoint, B = getPushPoint(pushBtnLP, event);
float dOA = getDistance(O, A);
float dOB = getDistance(O, B);
float f = dOB / dOA;
int newWidth = (int) (lastImgWidth * f);
int newHeight = (int) (lastImgHeight * f);
imgLP.leftMargin = lastImgLeft - ((newWidth - lastImgWidth) / 2);
imgLP.topMargin = lastImgTop - ((newHeight - lastImgHeight) / 2);
imgLP.width = newWidth;
imgLP.height = newHeight;
mView.setLayoutParams(imgLP);
float fz = (((A.x - O.x) * (B.x - O.x)) + ((A.y - O.y) * (B.y - O.y)));
float fm = dOA * dOB;
double comAngle = (180 * Math.acos(fz / fm) / PI);
if (Double.isNaN(comAngle)) {
comAngle = (lastComAngle < 90 || lastComAngle > 270) ? 0 : 180;
} else if ((B.y - O.y) * (A.x - O.x) < (A.y - O.y) * (B.x - O.x)) {
comAngle = 360 - comAngle;
}
lastComAngle = comAngle;
float angle = (float) (lastImgAngle + comAngle);
angle = angle % 360;
mView.setRotation(angle);
Point imageRB = new Point(mView.getLeft() + mView.getWidth(), mView.getTop() + mView.getHeight());
Point anglePoint = getAnglePoint(O, imageRB, angle);
pushBtnLP.leftMargin = (int) (anglePoint.x - pushImgWidth / 2);
pushBtnLP.topMargin = (int) (anglePoint.y - pushImgHeight / 2);
pushView.setLayoutParams(pushBtnLP);
break;
}
return false;
}
private void refreshImageCenter() {
int x = mView.getLeft() + mView.getWidth() / 2;
int y = mView.getTop() + mView.getHeight() / 2;
mViewCenter = new Point(x, y);
}
private Point getPushPoint(FrameLayout.LayoutParams lp, MotionEvent event) {
return new Point(lp.leftMargin + (int) event.getX(), lp.topMargin + (int) event.getY());
}
private float getDistance(Point a, Point b) {
float v = ((a.x - b.x) * (a.x - b.x)) + ((a.y - b.y) * (a.y - b.y));
return ((int) (Math.sqrt(v) * 100)) / 100f;
}
private Point getAnglePoint(Point O, Point A, float angle) {
int x, y;
float dOA = getDistance(O, A);
double p1 = angle * PI / 180f;
double p2 = Math.acos((A.x - O.x) / dOA);
x = (int) (O.x + dOA * Math.cos(p1 + p2));
double p3 = Math.acos((A.x - O.x) / dOA);
y = (int) (O.y + dOA * Math.sin(p1 + p3));
return new Point(x, y);
}
I'm assuming the rotation/scaling happens from the image center? In that case, it's simple trigonometry to find the rotation angle and the size:
Calculate dx and dy of the finger's coordinates minus the center coordinates. Math.atan2(dy, dx) is the rotation angle (in radians) and Math.hypot(dx,dy) can be used for the relative size, or just double the dx/dy and use directly.

Categories

Resources