How to add multiple pin marker on image dyanamically - android

I want to put marker on image with below functionality
-Dynamically adding multiple markers on image with zoom and scroll functionality on image.
-Blink animation on marker after added on image.
-Marker can be click-able and drag & drop on image.
-Marker's x & y position on image to sync same with other devices
I have used https://github.com/davemorrissey/subsampling-scale-image-view library
Java Code :
public class PinMarkerView extends SubsamplingScaleImageView implements View.OnTouchListener {
private PointF sPin;
private Bitmap pin;
private int resId;
public float vX;
public float vY;
private PointF vPrevious;
private PointF vStart;
private boolean drawing = false;
private boolean markerTouch = false;
private int strokeWidth;
private ArrayList<MapPins> allPins = new ArrayList<MapPins>();
private ArrayList<DrawPins> drawnPins = new ArrayList<DrawPins>();
public PinView(Context context) {
this(context, null);
}
public PinView(Context context, AttributeSet attr) {
super(context, attr);
// initialise();
}
public void setPin(PointF sPin, #DrawableRes int resid, String extras) {
MapPins mapPins = new MapPins();
mapPins.setPointF(sPin);
mapPins.setResId(resid);
mapPins.setExtrasData(extras);
mapPins.setX(sPin.x);
mapPins.setY(sPin.y);
allPins.add(mapPins);
//this.sPin = sPin;
// this.resId = resid;
initialise();
invalidate();
}
public PointF getPin() {
return sPin;
}
public Bitmap getMarker() {
return pin;
}
private void initialise() {
setOnTouchListener(this);
float density = getResources().getDisplayMetrics().densityDpi;
strokeWidth = (int) (density / 60f);
for (int i = 0; i < allPins.size(); i++) {
MapPins mapPins = allPins.get(i);
Bitmap localpin = BitmapFactory.decodeResource(this.getResources(), mapPins.getResId());
float w = (density / 100f) * localpin.getWidth();
float h = (density / 100f) * localpin.getHeight();
//pin = Bitmap.createScaledBitmap(pin, (int) w, (int) h, true);
pin = Bitmap.createScaledBitmap(localpin, localpin.getWidth(), localpin.getHeight(), true);
mapPins.setCreatedBitmap(pin);
allPins.set(i, mapPins);
//-------
}
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// Don't draw pin before image is ready so it doesn't move around during setup.
if (!isReady()) {
return;
}
Paint paint = new Paint();
paint.setAntiAlias(true);
for (int i = 0; i < allPins.size(); i++) {
MapPins mapPins = allPins.get(i);
if (mapPins.getPointF() != null && mapPins.getCreatedBitmap() != null) {
PointF vPin = sourceToViewCoord(mapPins.getPointF());
vX = vPin.x - (mapPins.getCreatedBitmap().getWidth() / 2);
vY = vPin.y - mapPins.getCreatedBitmap().getHeight();
canvas.drawBitmap(mapPins.getCreatedBitmap(), vX, vY, paint);
}
}
}
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
setMaxScale(5f);
return false;
}
#Override
public boolean onTouchEvent(#NonNull MotionEvent event) {
/* if (isZoomEnabled()) {
return super.onTouchEvent(event);
}*/
boolean consumed = false;
int touchCount = event.getPointerCount();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_1_DOWN:
vStart = new PointF(event.getX(), event.getY());
vPrevious = new PointF(event.getX(), event.getY());
getPinIdByPoint(vStart, viewToSourceCoord(event.getX(), event.getY()));
handleActionDown((int) event.getX(), (int) event.getY());
break;
case MotionEvent.ACTION_POINTER_2_DOWN:
// Abort any current drawing, user is zooming
vStart = null;
vPrevious = null;
break;
case MotionEvent.ACTION_MOVE:
if (markerTouch) {
setPanEnabled(false);
PointF sCurrentF = viewToSourceCoord(event.getX(), event.getY());
PointF sCurrent = new PointF(sCurrentF.x, sCurrentF.y);
PointF sStart = vStart == null ? null : new PointF(viewToSourceCoord(vStart).x, viewToSourceCoord(vStart).y);
if (touchCount == 1 && vStart != null) {
float vDX = Math.abs(event.getX() - vPrevious.x);
float vDY = Math.abs(event.getY() - vPrevious.y);
if (vDX >= strokeWidth * 5 || vDY >= strokeWidth * 5) {
if (sPin == null) {
sPin = sStart;
}
sPin = sCurrent;
vPrevious.x = event.getX();
vPrevious.y = event.getY();
drawing = true;
}
consumed = true;
invalidate();
} else if (touchCount == 1) {
// Consume all one touch drags to prevent odd panning effects handled by the superclass.
consumed = true;
}
} else {
return super.onTouchEvent(event);
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
invalidate();
setPanEnabled(true);
drawing = false;
markerTouch = false;
vPrevious = null;
vStart = null;
}
// Use parent to handle pinch and two-finger pan.
return consumed || super.onTouchEvent(event);
}
public void handleActionDown(int eventX, int eventY) {
if (eventX >= (sPin.x - pin.getWidth()) && (eventX <= (sPin.x + pin.getWidth()))) {
if (eventY >= (sPin.y - pin.getHeight()) && (sPin.y <= (sPin.y + pin.getHeight()))) {
markerTouch = true;
} else {
markerTouch = false;
}
} else {
markerTouch = false;
}
}
public int getPinIdByPoint(PointF tappedCoordinate, PointF deeplinkCoordinate) {
for (int i = allPins.size() - 1; i >= 0; i--) {
MapPins dPin = allPins.get(i);
int blockWidth = dPin.getCreatedBitmap().getWidth();
int blockHeight = dPin.getCreatedBitmap().getHeight();
int deeplinkX = (int) (deeplinkCoordinate.x - (dPin.getCreatedBitmap().getWidth() / 2));
int deeplinkY = (int) (deeplinkCoordinate.y - dPin.getCreatedBitmap().getHeight());
// center coordinate -/+ blockWidth actually sets touchable area to 2x icon size
if (tappedCoordinate.x >= deeplinkX - blockWidth && tappedCoordinate.x <= deeplinkX + blockWidth &&
tappedCoordinate.y >= deeplinkY - blockHeight && tappedCoordinate.y <= deeplinkY + blockHeight) {
sPin = dPin.getPointF();
pin = dPin.getCreatedBitmap();
return dPin.getId();
}
}
return -1; //negative no means no pin selected
}
}
Currently, I am able to add multiple marker, but I am facing issue of marker click and dragging on image.

Related

I can not use MotionEvent with Rajawali

Rajawali Version or Branch
rajawali:1.0.186
Device and Android Version
ADV Nexus 5X API 19 Android 4.4
Summary
I'm trying to make the camera moves when a MotionEvent (touch) occurs. I tried the code from https://github.com/Rajawali/Rajawali/issues/428 but it did not work for me.
My code
public class Renderer extends RajawaliRenderer {
public Context context;
private DirectionalLight directionalLight;
public Renderer(Context context) {
super(context);
this.context = context;
setFrameRate(60);
}
private Object3D object, star;
public void initScene(){
getCurrentScene().setBackgroundColor(Color.rgb(5,104,255));
directionalLight = new DirectionalLight(1f, .2f, -1.0f);
directionalLight.setColor(1.0f, 1.0f, 1.0f);
directionalLight.setPower(2);
getCurrentScene().addLight(directionalLight);
//LoaderOBJ objParser = new LoaderOBJ(this,"Load/1c_obj");
LoaderOBJ objParser = new LoaderOBJ(mContext.getResources(),mTextureManager, R.raw.primo_obj);
LoaderOBJ starParser = new LoaderOBJ(mContext.getResources(),mTextureManager,R.raw.star_obj);
try {
objParser.parse();
starParser.parse();
object = objParser.getParsedObject();
star = starParser.getParsedObject();
getCurrentScene().addChild(star);
getCurrentScene().addChild(object);
} catch (ParsingException e) {
e.printStackTrace();
}
getCurrentCamera().setLookAt(object.getWorldPosition());
Log.d("->",getCurrentCamera().getX()+","+getCurrentCamera().getY()+","+getCurrentCamera().getZ());
getCurrentCamera().setZ(40);
}
#Override
public void onRender(final long elapsedTime, final double deltaTime) {
super.onRender(elapsedTime, deltaTime);
Camera cam = getCurrentCamera();
Vector3 s = cam.getPosition();
if (touchTurn != 0) {
if (flagMulti) {
Double r = Math.sqrt(s.x * s.x + s.z * s.z);
angle += touchTurn;
angle %= 360;
cam.setPosition((float) (r * Math.cos(angle)), s.y, (float) (r * Math.sin(angle)));
cam.setLookAt(object.getLookAt());
}
else{
s.x+=touchTurn*5;
cam.setPosition(s);
}
touchTurn = 0;
}
if (touchTurnUp != 0) {
if (!flagMulti) {
s.z += touchTurnUp * 5;
cam.setPosition(s);
}
touchTurnUp = 0;
}
}
#Override
public void onTouchEvent(MotionEvent me){
Log.d("touch ","Log touch");
int pointerCount = me.getPointerCount();
if(pointerCount == 2)
flagMulti = true;
if (me.getAction() == MotionEvent.ACTION_DOWN) {
xpos = me.getX();
ypos = me.getY();
}
if (me.getAction() == MotionEvent.ACTION_UP) {
xpos = -1;
ypos = -1;
touchTurn = 0;
touchTurnUp = 0;
}
if (me.getAction() == MotionEvent.ACTION_MOVE) {
float xd = me.getX() - xpos;
float yd = me.getY() - ypos;
xpos = me.getX();
ypos = me.getY();
touchTurn = xd / -100f;
touchTurnUp = yd / -100f;
Log.d("touchTurn ", touchTurn+" - "+touchTurnUp);
}
try {
Thread.sleep(15);
} catch (Exception e) {
}
}
public void onOffsetsChanged(float x, float y, float z, float w, int i, int j){
}}
Would you consider arcballCamera and target to your 3D object. You can then rotate the 3D object and zoom in/out with arcballCamera.

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();
}

Android ImageView Scaling and translating issue

I’m developing an android application (API 19 4.4) and I encounter some issue with ImageViews.
I have a SurfaceView, in which I dynamically add ImageViews which I want to react to touch events.
On so far, I have managed to make the ImageView move and scale smoothly but I have an annoying behavior.
When I scale down the image to a certain limit (I would say half the original size) and I try to move it, the image flicker.
After a short analysis, it seems that it’s switching its position symmetrically around the finger point on the screen, cumulating distance, and finally gets out of sight (all that happens very fast ( < 1s).
I think I am missing something with the relative value of the touch event to the ImageView/SurfaceView, but I’m a quite a noob and I’m stucked…
Here is my code
public class MyImageView extends ImageView {
private ScaleGestureDetector mScaleDetector ;
private static final int MAX_SIZE = 1024;
private static final String TAG = "MyImageView";
PointF DownPT = new PointF(); // Record Mouse Position When Pressed Down
PointF StartPT = new PointF(); // Record Start Position of 'img'
public MyImageView(Context context) {
super(context);
mScaleDetector = new ScaleGestureDetector(context,new MySimpleOnScaleGestureListener());
setBackgroundColor(Color.RED);
setScaleType(ScaleType.MATRIX);
setAdjustViewBounds(true);
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
lp.setMargins(-MAX_SIZE, -MAX_SIZE, -MAX_SIZE, -MAX_SIZE);
this.setLayoutParams(lp);
this.setX(MAX_SIZE);
this.setY(MAX_SIZE);
}
int firstPointerID;
boolean inScaling=false;
#Override
public boolean onTouchEvent(MotionEvent event) {
// get pointer index from the event object
int pointerIndex = event.getActionIndex();
// get pointer ID
int pointerId = event.getPointerId(pointerIndex);
//First send event to scale detector to find out, if it's a scale
boolean res = mScaleDetector.onTouchEvent(event);
if (!mScaleDetector.isInProgress()) {
int eid = event.getAction();
switch (eid & MotionEvent.ACTION_MASK)
{
case MotionEvent.ACTION_MOVE :
if(pointerId == firstPointerID) {
PointF mv = new PointF( (int)(event.getX() - DownPT.x), (int)( event.getY() - DownPT.y));
this.setX((int)(StartPT.x+mv.x));
this.setY((int)(StartPT.y+mv.y));
StartPT = new PointF( this.getX(), this.getY() );
}
break;
case MotionEvent.ACTION_DOWN : {
firstPointerID = pointerId;
DownPT.x = (int) event.getX();
DownPT.y = (int) event.getY();
StartPT = new PointF( this.getX(), this.getY() );
break;
}
case MotionEvent.ACTION_POINTER_DOWN: {
break;
}
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
case MotionEvent.ACTION_CANCEL: {
firstPointerID = -1;
break;
}
default :
break;
}
return true;
}
return true;
}
public boolean onScaling(ScaleGestureDetector detector) {
this.setScaleX(this.getScaleX()*detector.getScaleFactor());
this.setScaleY(this.getScaleY()*detector.getScaleFactor());
invalidate();
return true;
}
private class MySimpleOnScaleGestureListener extends SimpleOnScaleGestureListener {
#Override
public boolean onScale(ScaleGestureDetector detector) {
return onScaling(detector);
}
#Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
Log.d(TAG, "onScaleBegin");
return true;
}
#Override
public void onScaleEnd(ScaleGestureDetector arg0) {
Log.d(TAG, "onScaleEnd");
}
}
}
I have also another questions about rotations. How should I implement this?
Could I use the ScalegestureDetector in some way or have I to make this works in the view touch event? I would like to be able to scale and rotate in the same gesture (and move in another).
Thank for helping me, I would really appreciate!
Sorry for my english
this is a working example of two fingers move/scale/rotate (note: the code is quite short due to smart detector used - see MatrixGestureDetector):
class ViewPort extends View {
List<Layer> layers = new LinkedList<Layer>();
int[] ids = {R.drawable.layer0, R.drawable.layer1, R.drawable.layer2};
public ViewPort(Context context) {
super(context);
Resources res = getResources();
for (int i = 0; i < ids.length; i++) {
Layer l = new Layer(context, this, BitmapFactory.decodeResource(res, ids[i]));
layers.add(l);
}
}
#Override
protected void onDraw(Canvas canvas) {
for (Layer l : layers) {
l.draw(canvas);
}
}
private Layer target;
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
target = null;
for (int i = layers.size() - 1; i >= 0; i--) {
Layer l = layers.get(i);
if (l.contains(event)) {
target = l;
layers.remove(l);
layers.add(l);
invalidate();
break;
}
}
}
if (target == null) {
return false;
}
return target.onTouchEvent(event);
}
}
class Layer implements MatrixGestureDetector.OnMatrixChangeListener {
Matrix matrix = new Matrix();
Matrix inverse = new Matrix();
RectF bounds;
View parent;
Bitmap bitmap;
MatrixGestureDetector mgd = new MatrixGestureDetector(matrix, this);
public Layer(Context ctx, View p, Bitmap b) {
parent = p;
bitmap = b;
bounds = new RectF(0, 0, b.getWidth(), b.getHeight());
matrix.postTranslate(50 + (float) Math.random() * 50, 50 + (float) Math.random() * 50);
}
public boolean contains(MotionEvent event) {
matrix.invert(inverse);
float[] pts = {event.getX(), event.getY()};
inverse.mapPoints(pts);
if (!bounds.contains(pts[0], pts[1])) {
return false;
}
return Color.alpha(bitmap.getPixel((int) pts[0], (int) pts[1])) != 0;
}
public boolean onTouchEvent(MotionEvent event) {
mgd.onTouchEvent(event);
return true;
}
#Override
public void onChange(Matrix matrix) {
parent.invalidate();
}
public void draw(Canvas canvas) {
canvas.drawBitmap(bitmap, matrix, null);
}
}
class MatrixGestureDetector {
private static final String TAG = "MatrixGestureDetector";
private int ptpIdx = 0;
private Matrix mTempMatrix = new Matrix();
private Matrix mMatrix;
private OnMatrixChangeListener mListener;
private float[] mSrc = new float[4];
private float[] mDst = new float[4];
private int mCount;
interface OnMatrixChangeListener {
void onChange(Matrix matrix);
}
public MatrixGestureDetector(Matrix matrix, MatrixGestureDetector.OnMatrixChangeListener listener) {
this.mMatrix = matrix;
this.mListener = listener;
}
public void onTouchEvent(MotionEvent event) {
if (event.getPointerCount() > 2) {
return;
}
int action = event.getActionMasked();
int index = event.getActionIndex();
switch (action) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
int idx = index * 2;
mSrc[idx] = event.getX(index);
mSrc[idx + 1] = event.getY(index);
mCount++;
ptpIdx = 0;
break;
case MotionEvent.ACTION_MOVE:
for (int i = 0; i < mCount; i++) {
idx = ptpIdx + i * 2;
mDst[idx] = event.getX(i);
mDst[idx + 1] = event.getY(i);
}
mTempMatrix.setPolyToPoly(mSrc, ptpIdx, mDst, ptpIdx, mCount);
mMatrix.postConcat(mTempMatrix);
if(mListener != null) {
mListener.onChange(mMatrix);
}
System.arraycopy(mDst, 0, mSrc, 0, mDst.length);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
if (event.getPointerId(index) == 0) ptpIdx = 2;
mCount--;
break;
}
}
}
I tried to implementation of multiple touch on view not on bitmap using matrix, now i success. Now i think it will helpful to you for individual gesture for multiple image. Try it, it work best for me.
public class MultiTouchImageView extends ImageView implements OnTouchListener{
float[] lastEvent = null;
float d = 0f;
float newRot = 0f;
public static String fileNAME;
public static int framePos = 0;
//private ImageView view;
private boolean isZoomAndRotate;
private boolean isOutSide;
// We can be in one of these 3 states
private static final int NONE = 0;
private static final int DRAG = 1;
private static final int ZOOM = 2;
private int mode = NONE;
private PointF start = new PointF();
private PointF mid = new PointF();
float oldDist = 1f;
public MultiTouchImageView(Context context) {
super(context);
}
public MultiTouchImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public MultiTouchImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
#SuppressWarnings("deprecation")
#Override
public boolean onTouch(View v, MotionEvent event) {
//view = (ImageView) v;
bringToFront();
// Handle touch events here...
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
//savedMatrix.set(matrix);
start.set(event.getX(), event.getY());
mode = DRAG;
lastEvent = null;
break;
case MotionEvent.ACTION_POINTER_DOWN:
oldDist = spacing(event);
if (oldDist > 10f) {
midPoint(mid, event);
mode = ZOOM;
}
lastEvent = new float[4];
lastEvent[0] = event.getX(0);
lastEvent[1] = event.getX(1);
lastEvent[2] = event.getY(0);
lastEvent[3] = event.getY(1);
d = rotation(event);
break;
case MotionEvent.ACTION_UP:
isZoomAndRotate = false;
case MotionEvent.ACTION_OUTSIDE:
isOutSide = true;
mode = NONE;
lastEvent = null;
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
lastEvent = null;
break;
case MotionEvent.ACTION_MOVE:
if(!isOutSide){
if (mode == DRAG && !isZoomAndRotate) {
isZoomAndRotate = false;
setTranslationX((event.getX() - start.x) + getTranslationX());
setTranslationY((event.getY() - start.y) + getTranslationY());
} else if (mode == ZOOM && event.getPointerCount() == 2) {
isZoomAndRotate = true;
boolean isZoom = false;
if(!isRotate(event)){
float newDist = spacing(event);
if (newDist > 10f) {
float scale = newDist / oldDist * getScaleX();
setScaleX(scale);
setScaleY(scale);
isZoom = true;
}
}
else if(!isZoom){
newRot = rotation(event);
setRotation((float)(getRotation() + (newRot - d)));
}
}
}
break;
}
new GestureDetector(new MyGestureDectore());
Constants.currentSticker = this;
return true;
}
private class MyGestureDectore extends GestureDetector.SimpleOnGestureListener{
#Override
public boolean onDoubleTap(MotionEvent e) {
bringToFront();
return false;
}
#Override
public boolean onDoubleTapEvent(MotionEvent e) {
return false;
}
}
private float rotation(MotionEvent event) {
double delta_x = (event.getX(0) - event.getX(1));
double delta_y = (event.getY(0) - event.getY(1));
double radians = Math.atan2(delta_y, delta_x);
return (float) Math.toDegrees(radians);
}
private float spacing(MotionEvent event) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
return FloatMath.sqrt(x * x + y * y);
}
private void midPoint(PointF point, MotionEvent event) {
float x = event.getX(0) + event.getX(1);
float y = event.getY(0) + event.getY(1);
point.set(x / 2, y / 2);
}
private boolean isRotate(MotionEvent event){
int dx1 = (int) (event.getX(0) - lastEvent[0]);
int dy1 = (int) (event.getY(0) - lastEvent[2]);
int dx2 = (int) (event.getX(1) - lastEvent[1]);
int dy2 = (int) (event.getY(1) - lastEvent[3]);
Log.d("dx1 ", ""+ dx1);
Log.d("dx2 ", "" + dx2);
Log.d("dy1 ", "" + dy1);
Log.d("dy2 ", "" + dy2);
//pointer 1
if(Math.abs(dx1) > Math.abs(dy1) && Math.abs(dx2) > Math.abs(dy2)) {
if(dx1 >= 2.0 && dx2 <= -2.0){
Log.d("first pointer ", "right");
return true;
}
else if(dx1 <= -2.0 && dx2 >= 2.0){
Log.d("first pointer ", "left");
return true;
}
}
else {
if(dy1 >= 2.0 && dy2 <= -2.0){
Log.d("seccond pointer ", "top");
return true;
}
else if(dy1 <= -2.0 && dy2 >= 2.0){
Log.d("second pointer ", "bottom");
return true;
}
}
return false;
}
}
I finally use this (spacing is used to calculated the distance between two fingers), I offset the imageview after scaling to keep it centered, works fine for now :
float newDist = spacing(event);
float scale = newDist / oldDist;
int oldH =getLayoutParams().height;
int oldW =getLayoutParams().width;
int newH =(int) (getLayoutParams().height*scale);
int newW =(int) (getLayoutParams().width*scale);
if(newH<MAX_SIZE && newW<MAX_SIZE){
//scale the height and width of the view
getLayoutParams().height = newH;
getLayoutParams().width = newW;
//calculate the X and Y offset to apply after scaling to keep the image centered
int xOffset = (int)(getLayoutParams().height - oldH)/2;
int yOffset = (int)(getLayoutParams().width - oldW)/2;
setX(getX()-xOffset);
setY(getY()-yOffset);
requestLayout();
setAdjustViewBounds(true);
oldDist=newDist;
All these examples had a glitchy gesture support because of scaleType was set to matrix. When I tried to zoom, I was not able to keep the image in center and control the amount of zoom. So I did some study and wrote a small, easy but very pleasing code for this: https://stackoverflow.com/a/65697376/13339685

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;
}
}

getting android. view.inflateException when I use zoomView for pageCurlView

please tell me how can i remove the exception. or give me idea to implement zoom view with curlview.....
my xml file is like this,
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/relat">
<com.example.image.ZoomView
>
<com.example.image.PageCurlView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/dcgpagecurlPageCurlView1"
>
</com.example.image.PageCurlView>
my java file is
package com.example.image;
public class StandaloneExample extends Activity {
Button bt;LinearLayout lr;
/** Decoded bitmap image */
private Bitmap mBitmap;
private ZoomView zoomview;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(R.layout.standalone_example);
View v1 = ((LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.standalone_example, null, false);
v1.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
zoomview.addView(v1);
lr = (LinearLayout) findViewById(R.id.relat);
lr.addView(zoomview);
}
#Override
public void onDestroy(){
super.onDestroy();
System.gc();
finish();
}
public void lockOrientationLandscape() {
lockOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
public void lockOrientationPortrait() {
lockOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
public void lockOrientation( int orientation ) {
setRequestedOrientation(orientation);
}
}
i have implemented zoomView.java as described in a link
pagecurlview.java class is
public class PageCurlView extends View {
private final static String TAG = "PageCurlView";
private Paint mTextPaint;
private TextPaint mTextPaintShadow;
private int mCurlSpeed;
private int mUpdateRate;
private int mInitialEdgeOffset;
private int mCurlMode;
public static final int CURLMODE_SIMPLE = 0;
public static final int CURLMODE_DYNAMIC = 1;
private boolean bEnableDebugMode = false;
private WeakReference<Context> mContext;
private FlipAnimationHandler mAnimationHandler;
private float mFlipRadius;
private Vector2D mMovement;
private Vector2D mFinger;
private Vector2D mOldMovement;
private Paint mCurlEdgePaint;
private Vector2D mA, mB, mC, mD, mE, mF, mOldF, mOrigin;
private int mCurrentLeft, mCurrentTop;
private boolean bViewDrawn;
private boolean bFlipRight;
private boolean bFlipping;
private boolean bUserMoves;
private boolean bBlockTouchInput = false;
private boolean bEnableInputAfterDraw = false;
private Bitmap mForeground;
private Bitmap mBackground;
private ArrayList<Bitmap> mPages;
private int mIndex = 0;
private class Vector2D
{
public float x,y;
public Vector2D(float x, float y)
{
this.x = x;
this.y = y;
}
#Override
public String toString() {
// TODO Auto-generated method stub
return "("+this.x+","+this.y+")";
}
public float length() {
return (float) Math.sqrt(x * x + y * y);
}
public float lengthSquared() {
return (x * x) + (y * y);
}
public boolean equals(Object o) {
if (o instanceof Vector2D) {
Vector2D p = (Vector2D) o;
return p.x == x && p.y == y;
}
return false;
}
public Vector2D reverse() {
return new Vector2D(-x,-y);
}
public Vector2D sum(Vector2D b) {
return new Vector2D(x+b.x,y+b.y);
}
public Vector2D sub(Vector2D b) {
return new Vector2D(x-b.x,y-b.y);
}
public float dot(Vector2D vec) {
return (x * vec.x) + (y * vec.y);
}
public float cross(Vector2D a, Vector2D b) {
return a.cross(b);
}
public float cross(Vector2D vec) {
return x * vec.y - y * vec.x;
}
public float distanceSquared(Vector2D other) {
float dx = other.x - x;
float dy = other.y - y;
return (dx * dx) + (dy * dy);
}
public float distance(Vector2D other) {
return (float) Math.sqrt(distanceSquared(other));
}
public float dotProduct(Vector2D other) {
return other.x * x + other.y * y;
}
public Vector2D normalize() {
float magnitude = (float) Math.sqrt(dotProduct(this));
return new Vector2D(x / magnitude, y / magnitude);
}
public Vector2D mult(float scalar) {
return new Vector2D(x*scalar,y*scalar);
}
}
class FlipAnimationHandler extends Handler {
#Override
public void handleMessage(Message msg) {
PageCurlView.this.FlipAnimationStep();
}
public void sleep(long millis) {
this.removeMessages(0);
sendMessageDelayed(obtainMessage(0), millis);
}
}
public PageCurlView(Context context) {
super(context);
init(context);
ResetClipEdge();
}
public PageCurlView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
// Get the data from the XML AttributeSet
{
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PageCurlView);
// Get data
bEnableDebugMode = a.getBoolean(R.styleable.PageCurlView_enableDebugMode, bEnableDebugMode);
mCurlSpeed = a.getInt(R.styleable.PageCurlView_curlSpeed, mCurlSpeed);
mUpdateRate = a.getInt(R.styleable.PageCurlView_updateRate, mUpdateRate);
mInitialEdgeOffset = a.getInt(R.styleable.PageCurlView_initialEdgeOffset, mInitialEdgeOffset);
mCurlMode = a.getInt(R.styleable.PageCurlView_curlMode, mCurlMode);
Log.i(TAG, "mCurlSpeed: " + mCurlSpeed);
Log.i(TAG, "mUpdateRate: " + mUpdateRate);
Log.i(TAG, "mInitialEdgeOffset: " + mInitialEdgeOffset);
Log.i(TAG, "mCurlMode: " + mCurlMode);
// recycle object (so it can be used by others)
a.recycle();
}
ResetClipEdge();
}
private final void init(Context context) {
// Foreground text paint
mTextPaint = new Paint();
mTextPaint.setAntiAlias(true);
mTextPaint.setTextSize(16);
mTextPaint.setColor(0xFF000000);
// The shadow
mTextPaintShadow = new TextPaint();
mTextPaintShadow.setAntiAlias(true);
mTextPaintShadow.setTextSize(16);
mTextPaintShadow.setColor(0x00000000);
// Cache the context
mContext = new WeakReference<Context>(context);
// Base padding
setPadding(3, 3, 3, 3);
// The focus flags are needed
setFocusable(true);
setFocusableInTouchMode(true);
mMovement = new Vector2D(0,0);
mFinger = new Vector2D(0,0);
mOldMovement = new Vector2D(0,0);
// Create our curl animation handler
mAnimationHandler = new FlipAnimationHandler();
// Create our edge paint
mCurlEdgePaint = new Paint();
mCurlEdgePaint.setColor(Color.WHITE);
mCurlEdgePaint.setAntiAlias(true);
mCurlEdgePaint.setStyle(Paint.Style.FILL);
mCurlEdgePaint.setShadowLayer(10, -5, 5, 0x99000000);
// Set the default props, those come from an XML :D
mCurlSpeed = 30;
mUpdateRate = 33;
mInitialEdgeOffset = 20;
mCurlMode = 1;
// LEGACY PAGE HANDLING!
// Create pages
mPages = new ArrayList<Bitmap>();
mPages.add(BitmapFactory.decodeResource(getResources(), R.drawable.princess));
mPages.add(BitmapFactory.decodeResource(getResources(), R.drawable.temp));
// Create some sample images
mForeground = mPages.get(0);
mBackground = mPages.get(1);
}
public void ResetClipEdge()
{
// Set our base movement
mMovement.x = mInitialEdgeOffset;
mMovement.y = mInitialEdgeOffset;
mOldMovement.x = 0;
mOldMovement.y = 0;
// Now set the points
// TODO: OK, those points MUST come from our measures and
// the actual bounds of the view!
mA = new Vector2D(mInitialEdgeOffset, 0);
mB = new Vector2D(this.getWidth(), this.getHeight());
mC = new Vector2D(this.getWidth(), 0);
mD = new Vector2D(0, 0);
mE = new Vector2D(0, 0);
mF = new Vector2D(0, 0);
mOldF = new Vector2D(0, 0);
// The movement origin point
mOrigin = new Vector2D(this.getWidth(), 0);
}
private Context GetContext() {
return mContext.get();
}
public boolean IsCurlModeDynamic()
{
return mCurlMode == CURLMODE_DYNAMIC;
}
public void SetCurlSpeed(int curlSpeed)
{
if ( curlSpeed < 1 )
throw new IllegalArgumentException("curlSpeed must be greated than 0");
mCurlSpeed = curlSpeed;
}
public int GetCurlSpeed()
{
return mCurlSpeed;
}
public void SetUpdateRate(int updateRate)
{
if ( updateRate < 1 )
throw new IllegalArgumentException("updateRate must be greated than 0");
mUpdateRate = updateRate;
}
public int GetUpdateRate()
{
return mUpdateRate;
}
public void SetInitialEdgeOffset(int initialEdgeOffset)
{
if ( initialEdgeOffset < 0 )
throw new IllegalArgumentException("initialEdgeOffset can not negative");
mInitialEdgeOffset = initialEdgeOffset;
}
public int GetInitialEdgeOffset()
{
return mInitialEdgeOffset;
}
public void SetCurlMode(int curlMode)
{
if ( curlMode != CURLMODE_SIMPLE &&
curlMode != CURLMODE_DYNAMIC )
throw new IllegalArgumentException("Invalid curlMode");
mCurlMode = curlMode;
}
public int GetCurlMode()
{
return mCurlMode;
}
public void SetEnableDebugMode(boolean bFlag)
{
bEnableDebugMode = bFlag;
}
public boolean IsDebugModeEnabled()
{
return bEnableDebugMode;
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int finalWidth, finalHeight;
finalWidth = measureWidth(widthMeasureSpec);
finalHeight = measureHeight(heightMeasureSpec);
setMeasuredDimension(finalWidth, finalHeight);
}
private int measureWidth(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
// We were told how big to be
result = specSize;
} else {
// Measure the text
result = specSize;
}
return result;
}
private int measureHeight(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
// We were told how big to be
result = specSize;
} else {
// Measure the text (beware: ascent is a negative number)
result = specSize;
}
return result;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (!bBlockTouchInput) {
// Get our finger position
mFinger.x = event.getX();
mFinger.y = event.getY();
int width = getWidth();
// Depending on the action do what we need to
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mOldMovement.x = mFinger.x;
mOldMovement.y = mFinger.y;
// If we moved over the half of the display flip to next
if (mOldMovement.x > (width >> 1)) {
mMovement.x = mInitialEdgeOffset;
mMovement.y = mInitialEdgeOffset;
// Set the right movement flag
bFlipRight = true;
} else {
// Set the left movement flag
bFlipRight = false;
// go to next previous page
previousView();
// Set new movement
mMovement.x = IsCurlModeDynamic()?width<<1:width;
mMovement.y = mInitialEdgeOffset;
}
break;
case MotionEvent.ACTION_UP:
bUserMoves=false;
bFlipping=true;
FlipAnimationStep();
break;
case MotionEvent.ACTION_MOVE:
bUserMoves=true;
// Get movement
mMovement.x -= mFinger.x - mOldMovement.x;
mMovement.y -= mFinger.y - mOldMovement.y;
mMovement = CapMovement(mMovement, true);
// Make sure the y value get's locked at a nice level
if ( mMovement.y <= 1 )
mMovement.y = 1;
// Get movement direction
if (mFinger.x < mOldMovement.x ) {
bFlipRight = true;
} else {
bFlipRight = false;
}
// Save old movement values
mOldMovement.x = mFinger.x;
mOldMovement.y = mFinger.y;
// Force a new draw call
DoPageCurl();
this.invalidate();
break;
}
}
// TODO: Only consume event if we need to.
return true;
}
private Vector2D CapMovement(Vector2D point, boolean bMaintainMoveDir)
{
// Make sure we never ever move too much
if (point.distance(mOrigin) > mFlipRadius)
{
if ( bMaintainMoveDir )
{
// Maintain the direction
point = mOrigin.sum(point.sub(mOrigin).normalize().mult(mFlipRadius));
}
else
{
// Change direction
if ( point.x > (mOrigin.x+mFlipRadius))
point.x = (mOrigin.x+mFlipRadius);
else if ( point.x < (mOrigin.x-mFlipRadius) )
point.x = (mOrigin.x-mFlipRadius);
point.y = (float) (Math.sin(Math.acos(Math.abs(point.x-mOrigin.x)/mFlipRadius))*mFlipRadius);
}
}
return point;
}
public void FlipAnimationStep() {
if ( !bFlipping )
return;
int width = getWidth();
// No input when flipping
bBlockTouchInput = true;
// Handle speed
float curlSpeed = mCurlSpeed;
if ( !bFlipRight )
curlSpeed *= -1;
// Move us
mMovement.x += curlSpeed;
mMovement = CapMovement(mMovement, false);
// Create values
DoPageCurl();
// Check for endings :D
if (mA.x < 1 || mA.x > width - 1) {
bFlipping = false;
if (bFlipRight) {
//SwapViews();
nextView();
}
ResetClipEdge();
// Create values
DoPageCurl();
// Enable touch input after the next draw event
bEnableInputAfterDraw = true;
}
else
{
mAnimationHandler.sleep(mUpdateRate);
}
// Force a new draw call
this.invalidate();
}
private void DoPageCurl()
{
if(bFlipping){
if ( IsCurlModeDynamic() )
doDynamicCurl();
else
doSimpleCurl();
} else {
if ( IsCurlModeDynamic() )
doDynamicCurl();
else
doSimpleCurl();
}
}
private void doSimpleCurl() {
int width = getWidth();
int height = getHeight();
// Calculate point A
mA.x = width - mMovement.x;
mA.y = height;
// Calculate point D
mD.x = 0;
mD.y = 0;
if (mA.x > width / 2) {
mD.x = width;
mD.y = height - (width - mA.x) * height / mA.x;
} else {
mD.x = 2 * mA.x;
mD.y = 0;
}
double angle = Math.atan((height - mD.y) / (mD.x + mMovement.x - width));
double _cos = Math.cos(2 * angle);
double _sin = Math.sin(2 * angle);
mF.x = (float) (width - mMovement.x + _cos * mMovement.x);
mF.y = (float) (height - _sin * mMovement.x);
// If the x position of A is above half of the page we are still not
// folding the upper-right edge and so E and D are equal.
if (mA.x > width / 2) {
mE.x = mD.x;
mE.y = mD.y;
}
else
{
// So get E
mE.x = (float) (mD.x + _cos * (width - mD.x));
mE.y = (float) -(_sin * (width - mD.x));
}
}
private void doDynamicCurl() {
int width = getWidth();
int height = getHeight();
mF.x = width - mMovement.x+0.1f;
mF.y = height - mMovement.y+0.1f;
if(mA.x==0) {
mF.x= Math.min(mF.x, mOldF.x);
mF.y= Math.max(mF.y, mOldF.y);
}
// Get diffs
float deltaX = width-mF.x;
float deltaY = height-mF.y;
float BH = (float) (Math.sqrt(deltaX * deltaX + deltaY * deltaY) / 2);
double tangAlpha = deltaY / deltaX;
double alpha = Math.atan(deltaY / deltaX);
double _cos = Math.cos(alpha);
double _sin = Math.sin(alpha);
mA.x = (float) (width - (BH / _cos));
mA.y = height;
mD.y = (float) (height - (BH / _sin));
mD.x = width;
mA.x = Math.max(0,mA.x);
if(mA.x==0) {
mOldF.x = mF.x;
mOldF.y = mF.y;
}
// Get W
mE.x = mD.x;
mE.y = mD.y;
// Correct
if (mD.y < 0) {
mD.x = width + (float) (tangAlpha * mD.y);
mE.y = 0;
mE.x = width + (float) (Math.tan(2 * alpha) * mD.y);
}
}
#Deprecated
private void SwapViews() {
Bitmap temp = mForeground;
mForeground = mBackground;
mBackground = temp;
}
private void nextView() {
int foreIndex = mIndex + 1;
if(foreIndex >= mPages.size()) {
foreIndex = 0;
}
int backIndex = foreIndex + 1;
if(backIndex >= mPages.size()) {
backIndex = 0;
}
mIndex = foreIndex;
setViews(foreIndex, backIndex);
}
private void previousView() {
int backIndex = mIndex;
int foreIndex = backIndex - 1;
if(foreIndex < 0) {
foreIndex = mPages.size()-1;
}
mIndex = foreIndex;
setViews(foreIndex, backIndex);
}
private void setViews(int foreground, int background) {
mForeground = mPages.get(foreground);
mBackground = mPages.get(background);
}
#Override
protected void onDraw(Canvas canvas) {
mCurrentLeft = getLeft();
mCurrentTop = getTop();
if ( !bViewDrawn ) {
bViewDrawn = true;
onFirstDrawEvent(canvas);
}
canvas.drawColor(Color.WHITE);
Rect rect = new Rect();
rect.left = 0;
rect.top = 0;
rect.bottom = getHeight();
rect.right = getWidth();
// First Page render
Paint paint = new Paint();
// Draw our elements
drawForeground(canvas, rect, paint);
drawBackground(canvas, rect, paint);
drawCurlEdge(canvas);
// Draw any debug info once we are done
if ( bEnableDebugMode )
drawDebug(canvas);
// Check if we can re-enable input
if ( bEnableInputAfterDraw )
{
bBlockTouchInput = false;
bEnableInputAfterDraw = false;
}
// Restore canvas
//canvas.restore();
}
protected void onFirstDrawEvent(Canvas canvas) {
mFlipRadius = getWidth();
ResetClipEdge();
DoPageCurl();
}
private void drawForeground( Canvas canvas, Rect rect, Paint paint ) {
canvas.drawBitmap(mForeground, null, rect, paint);
// Draw the page number (first page is 1 in real life :D
// there is no page number 0 hehe)
drawPageNum(canvas, mIndex);
}
private Path createBackgroundPath() {
Path path = new Path();
path.moveTo(mA.x, mA.y);
path.lineTo(mB.x, mB.y);
path.lineTo(mC.x, mC.y);
path.lineTo(mD.x, mD.y);
path.lineTo(mA.x, mA.y);
return path;
}
private void drawBackground( Canvas canvas, Rect rect, Paint paint ) {
Path mask = createBackgroundPath();
// Save current canvas so we do not mess it up
canvas.save();
canvas.clipPath(mask);
canvas.drawBitmap(mBackground, null, rect, paint);
// Draw the page number (first page is 1 in real life :D
// there is no page number 0 hehe)
drawPageNum(canvas, mIndex);
canvas.restore();
}
private Path createCurlEdgePath() {
Path path = new Path();
path.moveTo(mA.x, mA.y);
path.lineTo(mD.x, mD.y);
path.lineTo(mE.x, mE.y);
path.lineTo(mF.x, mF.y);
path.lineTo(mA.x, mA.y);
return path;
}
private void drawCurlEdge( Canvas canvas )
{
Path path = createCurlEdgePath();
canvas.drawPath(path, mCurlEdgePaint);
}
private void drawPageNum(Canvas canvas, int pageNum)
{
mTextPaint.setColor(Color.WHITE);
String pageNumText = "- "+pageNum+" -";
drawCentered(canvas, pageNumText,canvas.getHeight()-mTextPaint.getTextSize()-5,mTextPaint,mTextPaintShadow);
}
public static void drawTextShadowed(Canvas canvas, String text, float x, float y, Paint textPain, Paint shadowPaint) {
canvas.drawText(text, x-1, y, shadowPaint);
canvas.drawText(text, x, y+1, shadowPaint);
canvas.drawText(text, x+1, y, shadowPaint);
canvas.drawText(text, x, y-1, shadowPaint);
canvas.drawText(text, x, y, textPain);
}
public static void drawCentered(Canvas canvas, String text, float y, Paint textPain, Paint shadowPaint)
{
float posx = (canvas.getWidth() - textPain.measureText(text))/2;
drawTextShadowed(canvas, text, posx, y, textPain, shadowPaint);
}
private void drawDebug(Canvas canvas)
{
float posX = 10;
float posY = 20;
Paint paint = new Paint();
paint.setStrokeWidth(5);
paint.setStyle(Style.STROKE);
paint.setColor(Color.BLACK);
canvas.drawCircle(mOrigin.x, mOrigin.y, getWidth(), paint);
paint.setStrokeWidth(3);
paint.setColor(Color.RED);
canvas.drawCircle(mOrigin.x, mOrigin.y, getWidth(), paint);
paint.setStrokeWidth(5);
paint.setColor(Color.BLACK);
canvas.drawLine(mOrigin.x, mOrigin.y, mMovement.x, mMovement.y, paint);
paint.setStrokeWidth(3);
paint.setColor(Color.RED);
canvas.drawLine(mOrigin.x, mOrigin.y, mMovement.x, mMovement.y, paint);
posY = debugDrawPoint(canvas,"A",mA,Color.RED,posX,posY);
posY = debugDrawPoint(canvas,"B",mB,Color.GREEN,posX,posY);
posY = debugDrawPoint(canvas,"C",mC,Color.BLUE,posX,posY);
posY = debugDrawPoint(canvas,"D",mD,Color.CYAN,posX,posY);
posY = debugDrawPoint(canvas,"E",mE,Color.YELLOW,posX,posY);
posY = debugDrawPoint(canvas,"F",mF,Color.LTGRAY,posX,posY);
posY = debugDrawPoint(canvas,"Mov",mMovement,Color.DKGRAY,posX,posY);
posY = debugDrawPoint(canvas,"Origin",mOrigin,Color.MAGENTA,posX,posY);
posY = debugDrawPoint(canvas,"Finger",mFinger,Color.GREEN,posX,posY);
}
private float debugDrawPoint(Canvas canvas, String name, Vector2D point, int color, float posX, float posY) {
return debugDrawPoint(canvas,name+" "+point.toString(),point.x, point.y, color, posX, posY);
}
private float debugDrawPoint(Canvas canvas, String name, float X, float Y, int color, float posX, float posY) {
mTextPaint.setColor(color);
drawTextShadowed(canvas,name,posX , posY, mTextPaint,mTextPaintShadow);
Paint paint = new Paint();
paint.setStrokeWidth(5);
paint.setColor(color);
canvas.drawPoint(X, Y, paint);
return posY+15;
}
}

Categories

Resources