I am trying to make real time application based on canvas writing here multiple device will be connected with this application if i write something on canvas it should reflect on other devices which are connected with this app here my issue is i am able to write on canvas and its also writes smooth but when it comes to receiving end its getting disjoint segment not clear path visible on canvas.
I am using thread using moveTo() and quadTo()to and receiving points from server
here images for reference
Source writing
Receiving end
Here is my code which i am trying
onDraw method
#Override
protected void onDraw(final Canvas canvas) {
normal_canvas_draw=true;
bckimage = getBackground();
String col = "#333333".substring(1);
col = col.toLowerCase();
col = "#ff" + col;
mc.setcanvas(canvas);
paint1.setAntiAlias(true);
paint1.setDither(true);
paint1.setStyle(Paint.Style.STROKE);
paint1.setStrokeJoin(Paint.Join.ROUND);
paint1.setStrokeCap(Paint.Cap.ROUND);
paint1.setPathEffect(new CornerPathEffect(30) ); // set the path effect when they join.
paint.setDither(true); // set the dither to true
paint.setStyle(Paint.Style.STROKE); // set to STOKE
paint.setStrokeJoin(Paint.Join.ROUND); // set the join to round you want
paint.setStrokeCap(Paint.Cap.ROUND); // set the paint cap to round too
paint.setPathEffect(new CornerPathEffect(30) ); // set the path effect when they join.
paint.setAntiAlias(true);
mCanvas.drawPath(path, paint);
mCanvas.drawPath(path1, paint1);
/*
for(Path p :paths)
{
mCanvas.drawPath(p, paint1);
}*/
//mCanvas.drawPath(path1, paint1);
//s = paths.size();
s = type.size();
Log.d("BLOCK", s + " , " + leftval.size());
int j = 0, k = 0;
canvas.drawBitmap(img, 0, 0, null);
canvas.drawText(mc.getDisplaymsg(), mCanvas.getWidth()-200, 25, painttext);
r = new Rect(10, 600, 100, 650);
}
onTouchEvent
#Override
public boolean onTouchEvent(MotionEvent event) {
if (mIsScrolling)
sv.requestDisallowInterceptTouchEvent(false);
else
sv.requestDisallowInterceptTouchEvent(true);
float eventX = event.getX();
float eventY = event.getY();
boolean touchcaptured = false;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
path.reset();
// path.moveTo(eventX, eventY);
boolean l = r.contains((int) event.getX(), (int) event.getY());
if (markerMode)
{
isEraserDown="false";
isPenDown="false";
isMarkerDown="true";
path.moveTo(eventX,eventY);
startX=eventX/scalefactor;
startY=eventY/scalefactor;
mX=eventX;
mY=eventY;
MainActivity.super.loadUrl("javascript:eraserfunction(" + eventX / scalefactor + "," + eventY / scalefactor + "," + mc.getdrawAttributes1() + ")");
}
else if (eraseMode)
{
isEraserDown="true";
isPenDown="false";
isMarkerDown="false";
System.out.println("--Eraserfromtouch");
path.moveTo(eventX,eventY);
startX=eventX/scalefactor;
startY=eventY/scalefactor;
mX=eventX;
mY=eventY;
MainActivity.super.loadUrl("javascript:eraserfunction(" + eventX / scalefactor + "," + eventY / scalefactor + "," + mc.getdrawAttributes1() + ")");
}
else if (blockerase) {
// left=(int) event.getX();
// right=left+1;
// top=(int) event.getY();
// bottom=top+1;
rx = (int) event.getX();
ry = (int) event.getY();
}
/*------------------- Pendown when we touch on mobile screen------*/
else if (penmode) {
isPenDown="true";
isEraserDown="false";
isMarkerDown="false";
System.out.println("---pen-down---"+eventX+","+eventY);
int historySize = event.getHistorySize();
if(isPenDown=="true")
{
path.moveTo(eventX,eventY);
mX = eventX;
mY = eventY;
startX=eventX/scalefactor;
startY=eventY/scalefactor;
mc.setXY(eventX / scalefactor, eventY / scalefactor);
MainActivity.super.loadUrl("javascript:penDown(0,0,'pen')");
}
else
{
}
// System.out.println(" Lcal x"+eventX+" y"+eventY+" x2"+eventX+" y2"+eventY);
} else if (rectanglemode) {
rx = (int) event.getX();
ry = (int) event.getY();
} else if (linemode) {
rx = (int) event.getX();
ry = (int) event.getY();
} else if (circlemode) {
cx = (int) event.getX();
cy = (int) event.getY();
MainActivity.super.loadUrl("javascript:circleDown(" + cx / scalefactor + "," + cy / scalefactor + ")");
} else if (textmode) {
cx = (int) event.getX();
cy = (int) event.getY();
//MainActivity.super.loadUrl("javascript:drawtext(" +cx + "," + cy+","+"Hello World"+")");
}
//invalidate();
break;
case MotionEvent.ACTION_MOVE:
if (markerMode) {
if (isMarkerDown.equals("true")) {
System.out.println("Marker Move");
Log.d("MARKER", "Hi im marker");
String col = mc.getdrawAttributes().substring(1);
col = col.toLowerCase();
col = "#ff" + col;
int coll = Color.parseColor(col);
paint.setColor(coll);
paint.setAlpha(10);
paint.setStrokeWidth(20);
if (bckimage == null) {
} else {
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.XOR));
}
MainActivity.super.loadUrl("javascript:marker1(" + eventX / scalefactor + "," + eventY / scalefactor + ")");
}
else{
}
path.quadTo(mX,mY,(mX+event.getX())/2,(mY+event.getY())/2);
mX=event.getX();
mY=event.getY();
}
else if (eraseMode)
{
if(isEraserDown=="true")
{
System.out.println("--Eraserfromtouch--MOVE");
System.out.println("Marker Move");
Log.d("Eraser", "Im eraser");
String thh = mc.getdrawAttributes1();
float f = Float.parseFloat(thh);
paint.setStrokeWidth(f);
if (bckimage == null) {
paint.setColor(Color.WHITE); //Toast.makeText(getContext(),"ERASE",Toast.LENGTH_LONG).show();
} else {
// setLayerType(View.LAYER_TYPE_SOFTWARE, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
MainActivity.super.loadUrl("javascript:eraserfunction1(" + eventX / scalefactor + "," + eventY / scalefactor + "," + mc.getdrawAttributes1() + ")");
}
path.quadTo(mX,mY,(mX+event.getX())/2,(mY+event.getY())/2);
mX=event.getX();
mY=event.getY();
}
else
{
}
}
else if (blockerase) {
qx = (int) event.getX();
qy = (int) event.getY();
}
/*------------------Pen move on the screen following by finger-------------*/
else if (penmode) {
if(isPenDown=="true")
{
String thh1 = mc.getdrawAttributes1();
float width = Float.parseFloat(thh1);
paint.setStrokeWidth(width);
paint.setColor(color);
paint.setDither(true); // set the dither to true
paint.setStyle(Paint.Style.STROKE); // set to STOKE
paint.setStrokeJoin(Paint.Join.ROUND); // set the join to round you want
paint.setStrokeCap(Paint.Cap.ROUND); // set the paint cap to round too
paint.setPathEffect(new CornerPathEffect(30) ); // set the path effect when they join.
paint.setAntiAlias(true);
// Line current = lines.get(lines.size() - 1);
System.out.println("---penmove---");
float dx = Math.abs((int) event.getX() - mX);
float dy = Math.abs((int) event.getY() - mY);
System.out.println("--Value of dx-dy-"+dx+"-"+dy);
if (dx >= 4 || dy >= 4) {
// setXY function set X and Y values to be used in JS File
mc.setXY((int) event.getX() / scalefactor, (int) event.getY() / scalefactor);
MainActivity.super.loadUrl("javascript:penMove(0,0,'pen')");
path.quadTo(mX,mY,(mX+event.getX())/2,(mY+event.getY())/2);
mX=event.getX();
mY=event.getY();
}
else
{
}
}
} else if (rectanglemode) {
qx = (int) event.getX();
qy = (int) event.getY();
} else if (linemode) {
qx = (int) event.getX();
qy = (int) event.getY();
} else if (circlemode) {
//MainActivity.super.loadUrl("javascript:circleDown(" + eventX + "," + eventY + ")");
}
break;
case MotionEvent.ACTION_UP:
boolean ll = r.contains((int) event.getX(), (int) event.getY());
if (markerMode)
MainActivity.super.loadUrl("javascript:marker12()");
else if (eraseMode) {
MainActivity.super.loadUrl("javascript:penUp()");
isEraserDown="false";
isMarkerDown="false";
System.out.println("--Eraserfromtouch---actionup");
path.lineTo(mX,mY);
mCanvas.drawPath(path,paint);
path= new Path();
// path1= new Path();
paths.add(path);
// MainActivity.super.loadUrl("javascript:eraserfunction1(" + eventX / scalefactor + "," + eventY / scalefactor + "," + mc.getdrawAttributes1() + ")");
}else if (blockerase) {
qx = (int) event.getX();
qy = (int) event.getY();
MainActivity.super.loadUrl("javascript:bigeraserfunction1(" + rx / scalefactor + "," + ry / scalefactor + "," + qx / scalefactor + "," + qy / scalefactor + ")");
}
/*---------------------Pen up for writing on canvas------------------*/
else if (penmode) {
MainActivity.super.loadUrl("javascript:penUp()");
isPenDown="false";
System.out.println("---pen--up---");
path.lineTo(mX,mY);
mCanvas.drawPath(path,paint);
path= new Path();
// path1= new Path();
paths.add(path);
} else if (rectanglemode) {
qx = (int) event.getX();
qy = (int) event.getY();
MainActivity.super.loadUrl("javascript:rectangle(" + rx / scalefactor + "," + ry / scalefactor + "," + qx / scalefactor + "," + qy / scalefactor + ",'" + Prefs.getString(Elucido_APP_CONSTANTS.shared_user_name, "") + "')");
} else if (linemode) {
qx = (int) event.getX();
qy = (int) event.getY();
MainActivity.super.loadUrl("javascript:line(" + rx / scalefactor + "," + ry / scalefactor + "," + qx / scalefactor + "," + qy / scalefactor + ",'" + Prefs.getString(Elucido_APP_CONSTANTS.shared_user_name, "") + "')");
} else if (circlemode) {
c1x = (int) event.getX();
c1y = (int) event.getY();
MainActivity.super.loadUrl("javascript:circleup(" + c1x / scalefactor + "," + c1y / scalefactor + ")");
} else if (textmode) {
cx = (int) event.getX();
cy = (int) event.getY();
opentextDialog((int) (cx / scalefactor), (int) (cy / scalefactor));
}
break;
default:
return false;
}
invalidate();
return true;
}
draw() Method is in thread for continuously receiving points path
public boolean draw() {
//------------------------ Starting Reciving points--------------------------
String s1 = mc.getdrawlinesdual();
words1 = s1.split(",");
float xx11 = Float.parseFloat(words1[0].replaceAll("[\\(\\)\\[\\]\\{\\}]", "")) * scalefactor;
float yy11 = Float.parseFloat(words1[1]) * scalefactor;
float xx21 = Float.parseFloat(words1[2]) * scalefactor;
float yy21 = Float.parseFloat(words1[3].replaceAll("[\\(\\)\\[\\]\\{\\}]", "")) * scalefactor;
System.out.println("---------x" + xx11 + " y" + yy11 + " x2" + xx21 + " y2" + yy21);
if (a1 == 0)
{
System.out.println("----paint from pen--a1 == 0");
Log.d("TAGG", "INTEGER value " + mc.getdrawAttributes());
if (mc.getdrawTypeAttributes().toString().compareTo("eraser") == 0) {
System.out.println("Eraser--a1==0---ifllop");
Log.d("Eraser", "Im eraser");
String thh = mc.getdrawThAttributes();
float f = Float.parseFloat(thh);
paint1.setStrokeWidth(f);
if (bckimage == null) {
paint1.setColor(Color.WHITE); //Toast.makeText(getContext(),"ERASE",Toast.LENGTH_LONG).show();
} else {
paint1.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
}
} else {
System.out.println("Eraser--a1==0---elsellop");
String th = mc.getdrawThAttributes();
float f = Float.parseFloat(th);
paint1.setColor(color);
}
String t = mc.getdrawTypeAttributes().trim();
if ((t.compareTo("marker") == 0)) {
Log.d("MARKER", "Hi im marker");
String col = mc.getdrawColorAttributes().substring(1);
col = col.toLowerCase();
col = "#ff" + col.trim();
int coll = Color.parseColor(col);
paint1.setColor(coll);
paint1.setAlpha(10);
paint1.setStrokeWidth(20);
if (bckimage == null) {
} else {
paint1.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.XOR));
}
}
path1.moveTo(xx11, yy11);
// path1.lineTo(xx21, yy21);
path1.quadTo(xx11, yy11, (xx11 + xx21) / 2, (yy11 + yy21) / 2);
// invalidate();
// type.add("Line");
path1 = new Path();
a1 = xx11;
b1 = yy11;
c1 = xx21;
d1 = yy21;
}
else if (a1 == xx11)
{
//il.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
System.out.println("----paint from pen--a1 == xx11");
MainActivity.this.blankwhiteboard = 1;
path1.moveTo(c1, d1);
// float x = c+(xx2-c)/2;
// float y= d+(yy2-d)/2;
path1.quadTo(c1, d1, (c1 + xx21) / 2, (d1 + yy21) / 2);
// path1.lineTo(xx21, yy21);
invalidate();
c1 = xx21;
d1 = yy21;
}
else
{
type.add("Line");
System.out.println("----paint from pen");
path1 = new Path();
paint1 = new Paint();
paint1.setAntiAlias(true);
String th = mc.getdrawThAttributes();
paint1.setStyle(Paint.Style.STROKE);
paint1.setStrokeJoin(Paint.Join.ROUND);
paint1.setStrokeCap(Paint.Cap.ROUND);
paint1.setPathEffect(new CornerPathEffect(30));
paint1.setDither(true);
String t = mc.getdrawTypeAttributes();
if (mc.getdrawTypeAttributes().toString().compareTo("eraser") == 0)
{
System.out.println("Eraser--a1!=0---ifllop");
System.out.println("inside cuming erase");
//float val = 20;
String thh = mc.getdrawThAttributes();
float f = Float.parseFloat(thh);
paint1.setStrokeWidth(f);
Log.d("Eraser", "Im in eraser");
if (bckimage == null) {
paint1.setColor(Color.WHITE); //Toast.makeText(getContext(),"ERASE",Toast.LENGTH_LONG).show();
} else
paint1.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
invalidate();
}
else
{
System.out.println("Eraser--a1!=0---elsellop");
float f = Float.parseFloat(th);
paint1.setStrokeWidth(f);
String col = mc.getdrawColorAttributes().substring(1);
col = col.toLowerCase();
col = "#ff" + col;
int coll = Color.parseColor(col);
paint1.setColor(coll);
if ((t.compareTo("marker") == 0))
{
Log.d("MARKER", "Hi im marker");
paint1.setAlpha(10);
paint1.setStrokeWidth(20);
if (bckimage == null)
{
}
else
{
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.XOR));
}
paint1.setStrokeWidth(f);
mc.getTelephoneNumber(Integer.toHexString(color).substring(2));
MainActivity.super.loadUrl("javascript:colorSelectListener('')");
}
else
{
}
}
path1.moveTo(xx11, yy11);
// path1.lineTo(xx21,yy21);
path1.quadTo(xx11, yy11, (xx11 + xx21) / 2, (yy11 + yy21) / 2);
a1 = xx11;
b1 = yy11;
c1 = xx21;
d1 = yy21;
}
invalidate();
//------------------------ End Reciving points--------------------------
}
Related
I do not speak English well.
We apologize if you do not understand the question.
LinearLayout _Main_Contact_Layout;
FrameLayout _Main_Frame;
ImageView _Main_Background;
private List<string> _DrawerList_Item;
private ListView _DrawerList;
float _X, _Y;
float _XX, _YY;
int offset = 0, duration = 100;
float scaleX = 1.0f, scaleY = 1.0f;
float maxZoomLimit = 2.6f, minZoomLimit = 1.0f;
public bool OnTouch(View v, MotionEvent e)
{
switch (e.Action)
{
case MotionEventActions.Down:
_X = e.GetX();
_Y = e.GetY();
float _Start_X = 760, _Start_Y = 160;
float _End_X = 1150, _End_Y = 490;
WindowManagerLayoutParams _Params = new WindowManagerLayoutParams();
_Params.X = (int)e.RawX;
_Params.Y = (int)e.RawY;
LayoutInflater inflater = (LayoutInflater)this.GetSystemService(Context.LayoutInflaterService);
View _Popup = inflater.Inflate(Resource.Layout.Custom_Popup, null);
PopupWindow _Window = new PopupWindow(_Popup, WindowManagerLayoutParams.WrapContent, WindowManagerLayoutParams.WrapContent);
_Window.SetBackgroundDrawable(new BitmapDrawable());
_Window.OutsideTouchable = true;
TextView _SetupX = (TextView)_Popup.FindViewById(Resource.Id.x_text);
TextView _SetupY = (TextView)_Popup.FindViewById(Resource.Id.y_text);
_SetupX.Text = "X 좌표 : " + _X.ToString("#.##");
_SetupY.Text = "Y 좌표 : " + _Y.ToString("#.##");
DrawerLayout _lstDrawer = (DrawerLayout)v.FindViewById(Resource.Id._DrawerLayout);
if(_Start_X > _X | _Start_Y > _Y | _End_X < _X | _End_Y < _Y )
{
_Window.Focusable = true;
_Window.ShowAsDropDown(_Popup, _Params.X, _Params.Y);
_Window.ShowAtLocation(_Popup, GravityFlags.Left | GravityFlags.Top, 0, 0);
_lstDrawer.CloseDrawer((int)GravityFlags.Left);
}
else if (_Start_X < _X & _Start_Y < _Y & _End_X > _X & _End_Y > _Y & !_lstDrawer.IsDrawerOpen((int)GravityFlags.Left))
{
_lstDrawer.OpenDrawer((int)GravityFlags.Left);
_Window.ShowAsDropDown(_Popup, _Params.X, _Params.Y);
_Window.ShowAtLocation(_Popup, GravityFlags.Left | GravityFlags.Top, 0, 0);
}
else if (_lstDrawer.IsDrawerOpen((int)GravityFlags.Left))
{
_lstDrawer.CloseDrawer((int)GravityFlags.Left);
}
break;
case MotionEventActions.Move:
_XX = e.GetX() - _X;
_YY = e.GetY() - _Y;
//_Main_Background.SetX(_Main_Background.GetX() + _XX);
//_Main_Background.SetY(_Main_Background.GetY() + _YY);
_X = e.GetX();
_Y = e.GetY();
if (scaleX > 1.0f && scaleY > 1.0f)
{
_MoveToX(_XX);
_MoveToY(_YY);
Console.WriteLine("_XX : " + _XX.ToString());
Console.WriteLine("_YY : " + _YY.ToString());
}
break;
}
return true;
}
private void _MoveToX(float xX)
{
float futureX = _Main_Background.GetX() + _XX;
if (futureX > 0 | futureX < 500)
{
_Main_Background.SetX(futureX);
}
}
private void _MoveToY(float yY)
{
float futureY = _Main_Background.GetY() + _YY;
if (futureY > 0 | futureY < 500)
{
_Main_Background.SetY(futureY);
}
}
private void _Zoom_In(View v)
{
if (scaleX < maxZoomLimit && scaleY < maxZoomLimit)
{
Animation animation = new ScaleAnimation(scaleX, (scaleX + 0.2f), scaleY, (scaleY + 0.2f), _X, _Y);
scaleX += 0.2f;
scaleY += 0.2f;
animation.Interpolator = new DecelerateInterpolator();
animation.Duration = duration;
animation.StartOffset = offset;
animation.FillAfter = true;
v.StartAnimation(animation);
}
}
private void _Zoom_Out(View v)
{
if (scaleX > minZoomLimit && scaleY > minZoomLimit)
{
Animation animation = new ScaleAnimation(scaleX, (scaleX - 0.2f), scaleY, (scaleY - 0.2f), _X, _Y);
scaleY -= 0.2f;
scaleX -= 0.2f;
animation.Interpolator = new DecelerateInterpolator();
animation.Duration = duration;
animation.StartOffset = offset;
animation.FillAfter = true;
v.StartAnimation(animation);
}
}
I am worried about this for about a week.
How do I keep from leaving the screen?
Adjusting the scale? How do I touch the scale?
Zoom in and Zoom out using the Button
-> resolution
Moving images with Zoom in using Button
-> resolution
If you move it after Zoom in, start with moving the image to a strange place.
-> resolution
Layout out of range
-> resolution
Move only within layout range (Unresolved)
Modify the if condition in your _MoveTo method. The x, y is the coordinate of the top left corner of your view. Calculate the width and height of the imageview, make sure the x and y value is smaller than 0 and not smaller than the value of screenwidth minus the imageview width.
For example:
private void _MoveToX(float xX)
{
float futureX = _Main_Background.GetX() + xX;
if (futureX <=0 && futureX >=YourScreenWidth -(_Main_Background.Width * scaleX))
{
_Main_Background.SetX(futureX);
Console.WriteLine("futureY : " + (_Main_Background.Height * scaleX).ToString());
Console.WriteLine("futureX : " + futureX.ToString());
}
}
private void _MoveToY(float yY)
{
float futureY = _Main_Background.GetY() + yY;
if (futureY <= 0 && futureY >=YourScreenHeight- (_Main_Background.Height * scaleY))
{
_Main_Background.SetY(futureY);
Console.WriteLine("futureY : " + (_Main_Background.Height * scaleY).ToString());
Console.WriteLine("futureY : " + futureY.ToString());
}
}
i have relative parent layout and adding custom textview dynamically into it. when i drag(move) and scale my current textview it get weird jumps continuously in both pointer index. how can i solve this issue?
my custom textview as given below:
public class VideoTextView extends TextView implements View.OnTouchListener {
private final String TAG = this.getClass().getSimpleName();
private Context context;
private Matrix matrix = new Matrix();
private Matrix savedMatrix = new Matrix();
private PointF start = new PointF();
private PointF mid = new PointF();
private float[] matrixValues = new float[9];
private Paint paint;
private Paint linePaint;
private VideoTextMovement videoTextMovement;
private OperationListener operationListener;
private int widthView, heightView;
private boolean isInEdit;
public VideoTextView(Context context, int widthView, int heightView) {
super(context);
this.context = context;
this.widthView = widthView;
this.heightView = heightView;
videoTextMovement = (VideoTextMovement) context;
init();
}
public void updateViewWidthHeight(int widthView, int heightView) {
this.widthView = widthView;
this.heightView = heightView;
}
private void init() {
paint = new Paint();
paint.setTextSize(8);
paint.setColor(context.getResources().getColor(R.color.white));
linePaint = new Paint();
linePaint.setColor(getResources().getColor(R.color.colorPrimary));
linePaint.setAntiAlias(true);
linePaint.setDither(true);
linePaint.setStyle(Paint.Style.STROKE);
linePaint.setStrokeWidth(3.0f);
// setTextSize(8f);
setTextColor(getResources().getColor(R.color.colorAccent));
setOnTouchListener(this);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int textWidth = getMeasuredWidth();
int textHeight = getMeasuredHeight();
int origWidth = textWidth;
int origHeight = textHeight;
matrix.getValues(matrixValues);
canvas.save();
canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG & Paint.FILTER_BITMAP_FLAG));
float transX = matrixValues[Matrix.MTRANS_X];
float transY = matrixValues[Matrix.MTRANS_Y];
float scaleX = matrixValues[Matrix.MSCALE_X];
float scaleY = matrixValues[Matrix.MSCALE_Y];
float maxScale = widthView / textWidth;
Log.e(TAG + " ====", "matrix scale " + scaleX + " " + scaleY + " max scale " + maxScale);
scaleX = Math.max(0.5f, Math.min(scaleX, maxScale));
scaleY = Math.max(0.5f, Math.min(scaleY, maxScale));
if (scaleX > 1.0f) {
textWidth = (int) (textWidth + (textWidth * (scaleX - 1.0f)));
} else if (scaleX < 1.0f) {
textWidth = (int) (textWidth * scaleX);
}
if (scaleY > 1.0f) {
textHeight = (int) (textHeight + (textHeight * (scaleY - 1.0f)));
} else if (scaleY < 1.0f) {
textHeight = (int) (textHeight * scaleY);
}
Log.e(TAG + " ====", "original Tx-Ty " + transX + " - " + transY);
if (transX < 0) {
transX = 0;
}
if (transY < 0) {
transY = 0;
}
if (transX > (widthView - textWidth)) {
transX = widthView - textWidth;
}
if (transY > (heightView - textHeight)) {
transY = heightView - textHeight;
}
Log.e(TAG + " ====", "original w-h " + origWidth + " - " + origHeight + " " + " increased w-h " + textWidth + " - " + textHeight);
Log.e(TAG + " ====", "diff w-h " + Math.abs(origWidth - textWidth) + " - " + Math.abs(origHeight - textHeight));
matrixValues[Matrix.MTRANS_X] = transX;
matrixValues[Matrix.MTRANS_Y] = transY;
matrixValues[Matrix.MSCALE_X] = scaleX;
matrixValues[Matrix.MSCALE_Y] = scaleY;
matrix.setValues(matrixValues);
setX(transX + (textWidth - origWidth) / 2);
setY(transY + (textHeight - origHeight) / 2);
setScaleX(scaleX);
setScaleY(scaleY);
// setPivotX(mid.x);
// setPivotY(mid.y);
Log.e(TAG + " ====", "translateFactor " + transX + " - " + transY + " scaleFactor " + scaleX + " - " + scaleY);
videoTextMovement.translateText(getId(), transX, transY, textWidth, textHeight, getTextSize());
if (isInEdit) {
canvas.drawLine(0, origHeight, origWidth, origHeight, linePaint);
}
canvas.restore();
Log.e(TAG + " ===", TAG + " onDraw");
}
public void midPoint(MotionEvent event) {
float x = event.getX(0) + event.getX(1);
float y = event.getY(0) + event.getY(1);
Log.e(TAG + " ====", "mid point x-y " + (x / 2) + " " + (y / 2));
mid.set(x / 2, y / 2);
}
private float spacing(MotionEvent event) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
Log.e(TAG + " ====", "spacing x-y " + (x * x + y * y));
return (float) Math.sqrt(x * x + y * y);
}
float rawX0;
float rawY0;
float rawX1;
float rawY1;
private void getOriginalLocation(MotionEvent event) {
int[] location = {0, 0};
getLocationOnScreen(location);
rawX0 = event.getX(0) + location[0];
rawY0 = event.getY(0) + location[1];
float x = event.getRawX();
float y = event.getRawY();
Log.e(TAG + " ===", "actual raw co. " + x + "-" + y);
Log.e(TAG + " ===", "custom raw co. " + rawX0 + "-" + rawY0);
rawX1 = event.getX(1) + location[0];
rawY1 = event.getY(1) + location[1];
}
private float getRawX(MotionEvent event, int pointerIndex) {
float offset = event.getRawX() - event.getX();
return event.getX(pointerIndex) + offset;
}
private float getRawY(MotionEvent event, int pointerIndex) {
float offset = event.getRawY() - event.getY();
return event.getY(pointerIndex) + offset;
}
public void setInEdit(boolean isInEdit) {
this.isInEdit = isInEdit;
invalidate();
}
public void setOperationListener(OperationListener operationListener) {
this.operationListener = operationListener;
}
private float oldDist;
private final int NONE = -1;
private final int DRAG = 1;
private final int ZOOM = 2;
private int mode = NONE;
#Override
public boolean onTouch(View view, MotionEvent event) {
float downX, downY;
float moveX, moveY;
switch (event.getAction() & event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
downX = event.getX();
downY = event.getY();
savedMatrix.set(matrix);
start.set(downX, downY);
mode = DRAG;
Log.e(TAG + " ===", "Action down X=" + downX + " Y=" + downY);
break;
case MotionEvent.ACTION_POINTER_DOWN:
oldDist = spacing(event);
savedMatrix.set(matrix);
midPoint(event);
mode = ZOOM;
Log.e(TAG + " ===", "Pointer down");
break;
case MotionEvent.ACTION_MOVE:
if (mode == DRAG) {
moveX = event.getX();
moveY = event.getY();
float mdX = moveX - start.x;
float mdY = moveY - start.y;
matrix.set(savedMatrix);
matrix.postTranslate(mdX, mdY);
invalidate();
Log.e(TAG + " ===", "draging");
Log.e(TAG + " ===", "draging x-y rawx-rawy " + event.getX() + "-" + event.getY() + " " + event.getRawX() + "-" + event.getRawY());
} else if (mode == ZOOM) {
float newDist = spacing(event);
float scale = (newDist / oldDist);
matrix.set(savedMatrix);
Log.e(TAG + " ====", "Zoom scale " + scale);
matrix.postScale(scale, scale/*, mid.x, mid.y*/);
invalidate();
Log.e(TAG + " ===", "scaling");
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
Log.e(TAG + " ===", "Action up, Pointer up");
break;
}
if (operationListener != null) {
operationListener.onEdit(this);
}
return true;
}
public interface OperationListener {
void onEdit(VideoTextView videoTextview);
}
}
I have added my touch listener and all necessary functions that i have used to perform drag and scale event in my code to solve this issue, but every time i get fail to solve.
My Layout XML:
<FrameLayout
android:id="#+id/videoEditorParent"
android:layout_width="match_parent"
android:layout_height="400dp">
<RelativeLayout
android:id="#+id/vidEditorWrapper"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="#color/colorAccent">
<VideoView
android:id="#+id/vidEditor"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
</FrameLayout>
can somebody help to solve this kind to problem?
Thanks.
I have problem, with rendering blocks after reScalling (zoom in-out) whole thing in my game
(sorry with my eng syntax , cuz Eng not my native language)
first look at my video
>Error Rendering Video
there are problem , When it's rendering blocks after change blocks scale to some specific number
look at my code
GameLoopThread.java
public class GameLoopThread extends Thread {
static long FPS = 20;
private GameView view;
private boolean running = false;
public GameLoopThread ( GameView view ) {
this.view = view;
}
#Override
public void run () {
long ticksPS = 1000 / GameLoopThread.FPS; // 0.05 second (50) ;
long startTime;
long delayDelta = 0;
long tmpDelta = 0;
while (this.running) {
Canvas c = null;
startTime = System.currentTimeMillis();
try {
c = this.view.getHolder().lockCanvas();
synchronized (this.view.getHolder()) {
this.view.onDraw(c);
}
ClientCoreStatic.clientGear.updateWorlds();
}
catch (NullPointerException e) {
e.printStackTrace();
}
finally {
if (c != null) this.view.getHolder().unlockCanvasAndPost(c);
}
// 50
// sleepTime = ticksPS - (System.currentTimeMillis() - startTime);
tmpDelta = (System.currentTimeMillis() - startTime);
// time use Should below than 50
try {
if (tmpDelta > ticksPS) delayDelta += tmpDelta - ticksPS;
// d.pl("gameloop thread + " + delayDelta);
if (delayDelta > 0) {
//Thread.sleep(10);
if (ticksPS >= tmpDelta) {
delayDelta -= ticksPS - tmpDelta;
}
}
else {
delayDelta = 0;
Thread.sleep(ticksPS - tmpDelta);
}
if (this.view.hashCode() != ClientStatic.gameView.hashCode()) {
this.setRunning(false);
GameView.parentActivity.finish();
break;
}
}
catch (Exception e) {
e.printStackTrace();
d.pl("gameloop error");
}
}
}
GameView.java
#Override
public boolean onTouchEvent ( MotionEvent event ) {
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
// true
if (event.getPointerCount() == 1 ) {
if (GameView.spriteKeypadcircle.isCollition(
event.getX(),
event.getY()) == true) // d.pl("true..");
return true;
if (GameView.spriteBlocks.isCollition(event.getX(), event.getY())) {
// check
GameView.spriteBlocks.isCollitionOnBlock(event.getX(),event.getY());
d.pl("touching at "+ event.getX() + "," + event.getY());
return true;
}
}
if (event.getPointerCount() == 2 ) {
d.pl("distance 1 " +
GameView.distance1XY[0][0] +
"," +
GameView.distance1XY[0][1] +
" + " +
GameView.distance1XY[1][0] +
"," +
GameView.distance1XY[1][1] +
" | " +
GameView.distance2XY[0][0] +
"," +
GameView.distance2XY[0][1] +
" + " +
GameView.distance2XY[1][0] +
"," +
GameView.distance2XY[1][1]);
for (int size = event.getPointerCount(), i = 0; i < size; i++) {
// PointF point = mActivePointers.get(event.getPointerId(i));
// if (point != null) {
// point.x = event.getX(i);
// point.y = event.getY(i);
// }
float x = event.getX(i);
float y = event.getY(i);
if (!GameView.spriteBlocks.isCollition(x, y)) break;
GameView.distance2XY[i][0] = x;
GameView.distance2XY[i][1] = y;
} // for
// after get position
// check distance
double tmp1 = Math.sqrt((Math.pow(GameView.distance1XY[0][0] -
GameView.distance1XY[1][0], 2)) +
(Math.pow(GameView.distance1XY[0][1] -
GameView.distance1XY[1][1], 2)));
double tmp2 = Math.sqrt((Math.pow(GameView.distance2XY[0][0] -
GameView.distance2XY[1][0], 2)) +
(Math.pow(GameView.distance2XY[0][1] -
GameView.distance2XY[1][1], 2)));
GameView.newDistance = Math.abs(tmp1 - tmp2);
if (GameView.newDistance > 200) { // change too much
GameView.distance1XY[0][0] = GameView.distance2XY[0][0];
GameView.distance1XY[0][1] = GameView.distance2XY[0][1];
GameView.distance1XY[1][0] = GameView.distance2XY[1][0];
GameView.distance1XY[1][1] = GameView.distance2XY[1][1];
return true;
}
// if (newDistance < 100) break;
// if (newD < 100) break;
if (tmp1 < tmp2)
SpriteBlocks.viewScale += GameView.newDistance / 1000;
else
SpriteBlocks.viewScale -= GameView.newDistance / 1000;
if (SpriteBlocks.viewScale < 0.2) SpriteBlocks.viewScale = 0.2;
if (SpriteBlocks.viewScale > 10) SpriteBlocks.viewScale = 10;
GameView.spriteBlocks.updateScale();
GameView.distance1XY[0][0] = GameView.distance2XY[0][0];
GameView.distance1XY[0][1] = GameView.distance2XY[0][1];
GameView.distance1XY[1][0] = GameView.distance2XY[1][0];
GameView.distance1XY[1][1] = GameView.distance2XY[1][1];
return true;
}
return true;
case MotionEvent.ACTION_DOWN:
return true;
case MotionEvent.ACTION_UP:
return true;
}
return false;
}
#Override
protected void onDraw ( Canvas canvas ) {
canvas.drawColor(Color.GRAY);
GameView.spriteBlocks.onDraw(canvas);
GameView.spriteCharStand.onDraw(canvas);
GameView.spriteKeypadcircle.onDraw(canvas);
}
SpriteBlocks.java
public SpriteBlocks ( GameView gameView, Bitmap bmp ) {
this.bmp = bmp;
SpriteBlocks.width = bmp.getWidth() / SpriteBlocks.BMP_COLUMNS;
SpriteBlocks.height = bmp.getHeight() / SpriteBlocks.BMP_ROWS;
SpriteBlocks.widthPixels = Resources.getSystem().getDisplayMetrics().widthPixels;
SpriteBlocks.heightPixels = Resources.getSystem().getDisplayMetrics().heightPixels;
SpriteBlocks.centerXScreen = SpriteBlocks.widthPixels / 2;
SpriteBlocks.centerYScreen = SpriteBlocks.heightPixels / 2;
// System.out.println("fififi " + this.weightPixels + "," +
// this.heightPixels);
updateScale();
src2 = new Rect(0, 0, 400, 400);
paintTextPlayCur.setColor(Color.BLACK);
paintTextPlayCur.setTextSize(32);
paintTextSelectBlock.setColor(Color.RED);
paintTextSelectBlock.setTextSize(32);
}
public void updateScale () {
// SpriteBlocks.viewScale = 1;
SpriteBlocks.curBlockWidth = SpriteBlocks.viewScale *
SpriteBlocks.width;
SpriteBlocks.xBlockCount = Math.round(SpriteBlocks.widthPixels /
SpriteBlocks.curBlockWidth);
SpriteBlocks.yBlockCount = Math.round(SpriteBlocks.heightPixels /
SpriteBlocks.curBlockWidth);
SpriteCharStand.curPlayerRenderHeight = SpriteCharStand.playerRenderHeight *
SpriteBlocks.viewScale;
SpriteCharStand.curPlayerRenderWidth = SpriteCharStand.playerRenderWidth *
SpriteBlocks.viewScale;
SpriteCharStand.playerLeftTopX = SpriteBlocks.centerXScreen -
(SpriteCharStand.curPlayerRenderWidth / 2);
SpriteCharStand.playerLeftTopY = SpriteBlocks.centerYScreen -
(SpriteCharStand.curPlayerRenderHeight / 2);
SpriteCharStand.playerRightDownX = SpriteBlocks.centerXScreen +
(SpriteCharStand.curPlayerRenderWidth / 2);
SpriteCharStand.playerRightDownY = SpriteBlocks.centerYScreen +
(SpriteCharStand.curPlayerRenderHeight / 2);
d.pl("viewScale = " +
SpriteBlocks.viewScale +
", width = " +
SpriteBlocks.curBlockWidth);
}
#Override
public void onDraw ( Canvas canvas ) {
update();
if (ClientStatic.minePlayer == null) {
ClientStatic.minePlayer = ClientStatic.playerList
.get(ClientStatic.mineID);
if (ClientStatic.playerList.get(ClientStatic.mineID) == null) {
d.pl(" uuuu " + ClientStatic.mineID);
return;
}
}
// center screen point is this location
minePlayerX = ClientStatic.minePlayer.getLocation().getX();// + 0.5;
minePlayerY = ClientStatic.minePlayer.getLocation().getY();// + 1;
double adderPoint = 0.1;
for ( double adder = 0 ; adder <= 1 ; adder += adderPoint) {
minePlayerX += adderPoint;
// left top of screen is this location
bX = ((minePlayerX) - (SpriteBlocks.xBlockCount / 2) - 1);
bY = ((minePlayerY) + (SpriteBlocks.yBlockCount / 2) + 1);
// right down of screen is this position
cX = ((minePlayerX) + (SpriteBlocks.xBlockCount / 2) + 1);
cY = ((minePlayerY) - (SpriteBlocks.yBlockCount / 2) - 1);
// (SpriteCharStand.curPlayerRenderWidth / 2)
Material me;
Block bbo;
leftXdiff = (minePlayerX * 100) % 100;
leftYdiff = (minePlayerY * 100) % 100;
/*
* leftXdiff = Math.abs(leftXdiff);
* leftYdiff = Math.abs(leftYdiff);
*/
// calculating them from scale
leftXdiff = (curBlockWidth * leftXdiff) / 100;
leftYdiff = (curBlockWidth * leftYdiff) / 100;
// d.pl("cur x " + minePlayerX + " |m " + leftXdiff + " |bx " + bX);
for (double xloop = bX; xloop <= cX; xloop++) { // loop all position X
//for (double yloop = bY; yloop >= cY; yloop--) { // loop all position
// Y
for (double yloop = 140.5 ; yloop == 140.5 ; yloop ++) {
// range Y
if ((yloop < 0) || yloop > (FixVariable.CHUNK_HEIGHT - 1)) {
continue;
}
// get block of that location
bbo = ClientStatic.minePlayer
.getLocation()
.getWorld()
.getBlockAt(((xloop)), ((yloop)));
me = Material.getMaterial(bbo.getTypeId());
srcX = me.getX(bbo.getData()) * SpriteBlocks.width;
srcY = me.getY(bbo.getData()) * SpriteBlocks.height;
srcKey = ((double) srcX * 10) + ((double) (srcY));
src = srcList.get(srcKey);
if (src == null) {
src = new Rect(srcX, srcY, srcX + SpriteBlocks.width, srcY +
SpriteBlocks.height);
srcList.put(srcKey, src);
}
// position to drawing
if (xloop == 5 && yloop == 140.5) {
d.pl("SPY!! " + tmpXPosition + " = " + xloop + " - " + bX + " ) * 200 -" + leftXdiff);
}
tmpXPosition = ((xloop - bX) * SpriteBlocks.curBlockWidth) -
(leftXdiff );
if (xloop == 5 && yloop == 140.5) {
if (me != Material.BED){
d.pl("bed is spy");
}
if (Math.abs(lastTmpXPosition- tmpXPosition) < 1 &&
(Math.abs(lastTmpXPosition- tmpXPosition) > 0)) {
System.out.println("WT " + (Math.abs(lastTmpXPosition- tmpXPosition)));
}
d.pl("lastTmpXPos = " + lastTmpXPosition + " | " + tmpXPosition);
if (lastTmpXPosition != tmpXPosition) {
lastTmpXPosition = tmpXPosition;
}
}
tmpYPosition = (((SpriteBlocks.yBlockCount) - (yloop - cY + (10*adder) )) * SpriteBlocks.curBlockWidth) +
(leftYdiff);
if (dst == null) {
dst = new Rect();
}
dst.set(
(int) tmpXPosition,
(int) tmpYPosition,
(int) (tmpXPosition + SpriteBlocks.curBlockWidth),
(int) (tmpYPosition + SpriteBlocks.curBlockWidth));
canvas.drawBitmap(bmp, src, dst, null);
dst2.set(
(int) (tmpXPosition),
(int) (tmpYPosition),
(int) (tmpXPosition + SpriteBlocks.curBlockWidth),
(int) (tmpYPosition + SpriteBlocks.curBlockWidth));
canvas.drawBitmap(GameView.bmpRect, src2, dst2, null);
// break;
}
} // for
bbo = ClientStatic.minePlayer
.getLocation()
.getWorld()
.getBlockAt(
ClientStatic.minePlayer.getLocation().getX(),
ClientStatic.minePlayer.getLocation().getY());
me = Material.getMaterial(bbo.getTypeId());
srcX = me.getX(bbo.getData()) * SpriteBlocks.width;
srcY = me.getY(bbo.getData()) * SpriteBlocks.height;
srcKey = ((double) srcX * 10) + ((double) (srcY));
tmpXPosition = 5;
tmpYPosition = 5;
dst.set(
(int) tmpXPosition,
(int) tmpYPosition,
(int) (tmpXPosition + SpriteBlocks.curBlockWidth),
(int) (tmpYPosition + SpriteBlocks.curBlockWidth));
canvas.drawText(
"playLoc " +
ClientStatic.minePlayer.getLocation().getX() +
"," +
ClientStatic.minePlayer.getLocation().getY(),
200,
200,
paintTextPlayCur);
canvas.drawBitmap(bmp, src, dst, null);
canvas.drawText(
"block " +
ClientStatic.minePlayer
.getLocation()
.getWorld()
.getBlockAt(
ClientStatic.minePlayer
.getLocation()
.getX(),
ClientStatic.minePlayer
.getLocation()
.getY())
.getTypeId() +
" | chunk " +
ClientStatic.minePlayer
.getLocation()
.getWorld()
.getChunkAt(
ClientStatic.minePlayer
.getLocation()
.getX())
.getChunkNumberX() +
" | " +
ClientStatic.minePlayer
.getLocation()
.getWorld()
.getChunkAt(
ClientStatic.minePlayer
.getLocation()
.getX()).getX()
,
200,
300,
paintTextPlayCur);
canvas.drawBitmap(bmp, src, dst, null);
// draw touch block
if (blockTouching != null) {
canvas.drawText("touch " +
blockTouching.getX() +
"," +
blockTouching.getY() +
" = " +
blockTouching.getTypeId() +
":" +
blockTouching.getData()
, 300, 400, paintTextSelectBlock);
}
} // adder
}
I want to calculate the un-scaled absolute position of the image drawn on the canvas based on the position clicked by the user on the scaled canvas.
I used following zoom implementation
Translate/scale bitmap within boundaries?
So far,
public boolean inMe(int x, int y, Region ClickRegion) {
if(mScaleFactor == 0)
mScaleFactor = 1;
float curX = ((x*1.0f)/ mScaleFactor) - (mPosX * mScaleFactor);
float curY = ((y*1.0f) / mScaleFactor) - (mPosY * mScaleFactor);
x = (int)curX;
y = (int)curY;
//ClickRegion is a grapics.Region computed on non-zoomed coordinates
if (ClickRegion.contains(x, y))
return true;
else
return false;
}
This works fine, when there is no zooming, but when its zoomed there are significant issues.
EDIT
This is the algo I used for zooming and panning.
public class PanZoomView extends View {
public static final String TAG = PanZoomView.class.getName();
private static final int INVALID_POINTER_ID = -1;
// The ‘active pointer’ is the one currently moving our object.
private int mActivePointerId = INVALID_POINTER_ID;
private Bitmap bitmap;
private float viewHeight;
private float viewWidth;
float canvasWidth, canvasHeight;
private ScaleGestureDetector mScaleDetector;
private float mScaleFactor = 1.f;
private float minScaleFactor;
private float mPosX;
private float mPosY;
private float mLastTouchX, mLastTouchY;
private boolean firstDraw = true;
private boolean panEnabled = true;
private boolean zoomEnabled = true;
public PanZoomView(Context context) {
super(context);
setup();
}
public PanZoomView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setup();
}
public PanZoomView(Context context, AttributeSet attrs) {
super(context, attrs);
setup();
}
private void setup() {
mScaleDetector = new ScaleGestureDetector(getContext(), new ScaleListener());
}
public void setBitmap(Bitmap bmp) {
setImageBitmap(bmp);
}
public void setImageBitmap(Bitmap bmp) {
bitmap = bmp;
resetZoom();
resetPan();
firstDraw = true;
invalidate();
}
public Bitmap getImageBitmap() {
return bitmap;
}
public Bitmap getBitmap() {
return getImageBitmap();
}
public void resetZoom() {
mScaleFactor = 1.0f;
}
public void resetPan() {
mPosX = 0f;
mPosY = 0f;
}
public void setImageDrawable(Drawable drawable) {
setImageBitmap(((BitmapDrawable) drawable).getBitmap());
}
public BitmapDrawable getImageDrawable() {
BitmapDrawable bd = new BitmapDrawable(getContext().getResources(), bitmap);
return bd;
}
public BitmapDrawable getDrawable() {
return getImageDrawable();
}
public void onDraw(Canvas canvas) {
// Log.v(TAG, "onDraw()");
if (bitmap == null) {
Log.w(TAG, "nothing to draw - bitmap is null");
super.onDraw(canvas);
return;
}
if (firstDraw
&& (bitmap.getHeight() > 0)
&& (bitmap.getWidth() > 0)) {
//Don't let the user zoom out so much that the image is smaller
//than its containing frame
float minXScaleFactor = (float) viewWidth / (float) bitmap.getWidth();
float minYScaleFactor = (float) viewHeight / (float) bitmap.getHeight();
minScaleFactor = Math.max(minXScaleFactor, minYScaleFactor);
Log.d(TAG, "minScaleFactor: " + minScaleFactor);
mScaleFactor = minScaleFactor; //start out "zoomed out" all the way
mPosX = mPosY = 0;
firstDraw = false;
}
mScaleFactor = Math.max(mScaleFactor, minScaleFactor);
canvasHeight = canvas.getHeight();
canvasWidth = canvas.getWidth();
// Log.d(TAG, "canvas density: " + canvas.getDensity() + " bitmap density: " + bitmap.getDensity());
// Log.d(TAG, "mScaleFactor: " + mScaleFactor);
//Save the canvas without translating (panning) or scaling (zooming)
//After each change, restore to this state, instead of compounding
//changes upon changes
canvas.save();
int maxX, minX, maxY, minY;
//Regardless of the screen density (HDPI, MDPI) or the scale factor,
//The image always consists of bitmap width divided by 2 pixels. If an image
//is 200 pixels wide and you scroll right 100 pixels, you just scrolled the image
//off the screen to the left.
minX = (int) (((viewWidth / mScaleFactor) - bitmap.getWidth()) / 2);
maxX = 0;
//How far can we move the image vertically without having a gap between image and frame?
minY = (int) (((viewHeight / mScaleFactor) - bitmap.getHeight()) / 2);
maxY = 0;
Log.d(TAG, "minX: " + minX + " maxX: " + maxX + " minY: " + minY + " maxY: " + maxY);
//Do not go beyond the boundaries of the image
if (mPosX > maxX) {
mPosX = maxX;
}
if (mPosX < minX) {
mPosX = minX;
}
if (mPosY > maxY) {
mPosY = maxY;
}
if (mPosY < minY) {
mPosY = minY;
}
// Log.d(TAG, "view width: " + viewWidth + " view height: "
// + viewHeight);
// Log.d(TAG, "bitmap width: " + bitmap.getWidth() + " height: " + bitmap.getHeight());
// Log.d(TAG, "translating mPosX: " + mPosX + " mPosY: " + mPosY);
// Log.d(TAG, "zooming to scale factor of " + mScaleFactor);
canvas.scale(mScaleFactor, mScaleFactor);
// Log.d(TAG, "panning to " + mPosX + "," + mPosY);
canvas.translate(mPosX, mPosY);
super.onDraw(canvas);
canvas.drawBitmap(bitmap, mPosX, mPosY, null);
canvas.restore(); //clear translation/scaling
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
// Let the ScaleGestureDetector inspect all events.
if (zoomEnabled) {
mScaleDetector.onTouchEvent(ev);
}
if (panEnabled) {
final int action = ev.getAction();
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: {
final float x = ev.getX();
final float y = ev.getY();
mLastTouchX = x;
mLastTouchY = y;
mActivePointerId = ev.getPointerId(0);
break;
}
case MotionEvent.ACTION_MOVE: {
final int pointerIndex = ev.findPointerIndex(mActivePointerId);
final float x = ev.getX(pointerIndex);
final float y = ev.getY(pointerIndex);
// Only move if the ScaleGestureDetector isn't processing a gesture.
if (!mScaleDetector.isInProgress()) {
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);
invalidate();
}
mLastTouchX = x;
mLastTouchY = y;
break;
}
case MotionEvent.ACTION_UP: {
mActivePointerId = INVALID_POINTER_ID;
break;
}
case MotionEvent.ACTION_CANCEL: {
mActivePointerId = INVALID_POINTER_ID;
break;
}
case MotionEvent.ACTION_POINTER_UP: {
final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
final int pointerId = ev.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 = ev.getX(newPointerIndex);
mLastTouchY = ev.getY(newPointerIndex);
mActivePointerId = ev.getPointerId(newPointerIndex);
}
break;
}
}
}
return true;
}
private class ScaleListener extends
ScaleGestureDetector.SimpleOnScaleGestureListener {
#Override
public boolean onScale(ScaleGestureDetector detector) {
mScaleFactor *= detector.getScaleFactor();
// Don't let the object get too small or too large.
mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 5.0f));
// Log.d(TAG, "detector scale factor: " + detector.getScaleFactor() + " mscalefactor: " + mScaleFactor);
invalidate();
return true;
}
}
//Currently zoomEnabled/panEnabled can only be set programmatically, not in XML
public boolean isPanEnabled() {
return panEnabled;
}
public void setPanEnabled(boolean panEnabled) {
this.panEnabled = panEnabled;
}
public boolean isZoomEnabled() {
return zoomEnabled;
}
public void setZoomEnabled(boolean zoomEnabled) {
this.zoomEnabled = zoomEnabled;
}
/**
* Calls getCroppedBitmap(int outputWidth, int outputHeight) without
* scaling the resulting bitmap to any specific size.
* #return
*/
public Bitmap getCroppedBitmap() {
return getCroppedBitmap(0, 0);
}
/**
* Takes the section of the bitmap visible in its View object
* and exports that to a Bitmap object, taking into account both
* the translation (panning) and zoom (scaling).
* WARNING: run this in a separate thread, not on the UI thread!
* If you specify that a 200x200 image should have an outputWidth
* of 400 and an outputHeight of 50, the image will be squished
* and stretched to those dimensions.
* #param outputWidth desired width of output Bitmap in pixels
* #param outputHeight desired height of output Bitmap in pixels
* #return the visible portion of the image in the PanZoomImageView
*/
public Bitmap getCroppedBitmap(int outputWidth, int outputHeight) {
int origX = -1 * (int) mPosX * 2;
int origY = -1 * (int) mPosY * 2;
int width = (int) (viewWidth / mScaleFactor);
int height = (int) (viewHeight / mScaleFactor);
Log.e(TAG, "origX: " + origX + " origY: " + origY + " width: " + width + " height: " + height + " outputWidth: " + outputWidth + " outputHeight: " + outputHeight + "getLayoutParams().width: " + getLayoutParams().width + " getLayoutParams().height: " + getLayoutParams().height);
Bitmap b = Bitmap.createBitmap(bitmap, origX, origY, width, height);
if (outputWidth > 0 && outputWidth > 0) {
//Use the exact dimensions given--chance this won't match the aspect ratio
b = Bitmap.createScaledBitmap(b, outputWidth, outputHeight, true);
}
return b;
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
viewHeight = h;
viewWidth = w;
}
}
Thanks for all comment, but this worked for me.
public boolean inMe(int x, int y, Region ClickRegion) {
float curX = ((x*1.0f)) + (-1*mPosX * 2* mScaleFactor);
float curY = ((y*1.0f)) + (-1*mPosY * 2* mScaleFactor);
x = (int)((curX/ mScaleFactor));
y = (int)((curY/ mScaleFactor));
if (cluster.ClickRegion.contains(x, y))
return true;
else
return false;
}
i want to custom view,it can include some effect:first draw a pic on the view as a background then draw a rectangle on the image,and draw other image named A in the rectangle, we know the rectangle have four fixed point,when i drag one of these,the rectangle can scale,at the same time A also is scale, i have read more link,but not find good example,i have done something,but cannot finish the scale rectangle,my code is:
public class DrawView extends View implements OnTouchListener {
private static final String TAG = "DrawView";
private static final int LineLength = 30;
Paint paint = new Paint();
float locationX, locationY;
private int mLastTouchX;
private int mLastTouchY;
private int mPosX;
private int mPosY;
private int mPosX1;
private int mPosY1;
Bitmap bitmap, bmp, xiao;
int screenWidth, screenHeight;
int xLength;
boolean isFirst = true;
boolean isLeft = false;
Rect r, rBig,outRect;
public DrawView(Context context) {
super(context);
setFocusable(true);
setFocusableInTouchMode(true);
this.setOnTouchListener(this);
WindowManager wm = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
screenHeight = wm.getDefaultDisplay().getHeight();
screenWidth = wm.getDefaultDisplay().getWidth();
mPosX = screenWidth / 2;
mPosY = screenHeight / 2;
paint.setColor(Color.RED);
paint.setAntiAlias(true);
bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.meinv);
bmp = BitmapFactory.decodeResource(getResources(), R.drawable.icon);
xiao = BitmapFactory.decodeResource(getResources(),
R.drawable.msn_protocol);
xLength = (int) Math.hypot(xiao.getWidth(), xiao.getHeight());
r = new Rect();
r.set((int) mPosX - LineLength - xiao.getWidth(), (int) mPosY
- LineLength - xiao.getHeight(), (int) mPosX - LineLength,
(int) mPosY - LineLength);
// Log.i("r", r.left + " " + r.top + " " + r.right + " " + r.bottom);
rBig = new Rect();
rBig.set((int) mPosX - LineLength, (int) mPosY - LineLength,
(int) mPosX + LineLength, (int) mPosY + LineLength);
//Log.i("r", rBig.left + " " + rBig.top + " " + rBig.right + " " + rBig.bottom);
}
#Override
public void onDraw(Canvas canvas) {
canvas.drawBitmap(bitmap, 0, 0, null);
canvas.drawBitmap(xiao, mPosX - LineLength - xiao.getWidth(), mPosY
- LineLength - xiao.getHeight(), null);
canvas.drawLine(mPosX - LineLength,
mPosY - LineLength - xiao.getHeight() / 2, mPosX + LineLength,
mPosY - LineLength - xiao.getHeight() / 2, paint);
canvas.drawLine(mPosX - LineLength - xiao.getWidth() / 2, mPosY
- LineLength, mPosX - LineLength - xiao.getWidth() / 2, mPosY
+ LineLength, paint);
canvas.drawBitmap(xiao, mPosX + LineLength,
mPosY - LineLength - xiao.getHeight(), null);
canvas.drawBitmap(xiao, mPosX - LineLength - xiao.getWidth(), mPosY
+ LineLength, null);
canvas.drawBitmap(xiao, mPosX + LineLength, mPosY + LineLength, null);
canvas.drawLine(mPosX + LineLength + xiao.getWidth() / 2, mPosY
- LineLength, mPosX + LineLength + xiao.getWidth() / 2, mPosY
+ LineLength, paint);
canvas.drawLine(mPosX - LineLength,
mPosY + LineLength + xiao.getHeight() / 2, mPosX + LineLength,
mPosY + LineLength + xiao.getHeight() / 2, paint);
if (isLeft) {
Matrix matrix = new Matrix();
matrix.preScale(0.8f, 0.8f);
Bitmap rotatedBitmap = Bitmap.createBitmap(bmp, 0, 0,
bmp.getWidth(), bmp.getHeight(), matrix, true);
canvas.drawBitmap(rotatedBitmap, mPosX - LineLength, mPosY
- LineLength, null);
}
}
public boolean onTouch(View view, MotionEvent event) {
isFirst = false;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
mPosX1 = (int) event.getX();
mPosY1 = (int) event.getY();
mLastTouchX = mPosX1;
mLastTouchY = mPosX1;
// Log.i("r", r.left + " " + r.top + " " + r.right + " " + r.bottom);
Log.i("ACTION_DOWN", "" + mPosX1 + " " + mPosY1);
if (r.contains(mPosX1, mPosY1)) {
isLeft = true;
invalidate();
}
break;
}
case MotionEvent.ACTION_MOVE: {
int x = (int) event.getX();
int y = (int) event.getY();
Log.i("aa",""+x+""+y);
int dx = x - mLastTouchX;
int dy = y - mLastTouchY;
mLastTouchX = x;
mLastTouchY = y;
mPosX += dx;
mPosY += dy;
r.set((int) mPosX - LineLength - xiao.getWidth(), (int) mPosY
- LineLength - xiao.getHeight(), (int) mPosX - LineLength,
(int) mPosY - LineLength);
rBig.set((int) mPosX - LineLength, (int) mPosY - LineLength,
(int) mPosX + LineLength, (int) mPosY + LineLength);
// Log.i("r", rBig.left + " " + rBig.top + " " + rBig.right + " " + rBig.bottom);
invalidate();
break;
}
case MotionEvent.ACTION_UP: {
break;
}
case MotionEvent.ACTION_CANCEL: {
break;
}
}
return true;
}
}
the pic as :http://i.stack.imgur.com/wxi35.png,the effect have finished by system gallery,but i debug the source ,i failed, as my other question: Imitate crop function of system Gallery
and https://stackoverflow.com/questions/6724218/i-cannot-find-the-initial-value-in-gallery-the-source
I dont know about drawing the Rectangle but, this is how I moved the image
MainPinchView.java
public class MainPinchView extends Activity {
int menuid = 0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MainPinchImageView obj = new MainPinchImageView(this);
Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.my);
obj.setImage(bmp, 100, 100);
setContentView(obj);
}
}
MainPinchImageView.java
public class MainPinchImageView extends ImageView {
private static final String TAG = "Touch";
// These matrices will be used to move and zoom image
Matrix matrix = new Matrix();
Matrix savedMatrix = new Matrix();
int flag = 0;
// 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;
// Remember some things for zooming
PointF start = new PointF();
PointF mid = new PointF();
float oldDist = 1f;
Context context;
public MainPinchImageView(Context context) {
super(context);
super.setClickable(true);
this.context = context;
matrix.setTranslate(1f, 1f);
setImageMatrix(matrix); // sets the default matrix
setScaleType(ScaleType.MATRIX); //Controls how the image should be resized or moved to match the size of this ImageView.
setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
// Handle touch events here...
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
savedMatrix.set(matrix); //
start.set(event.getX(), event.getY());
Log.d(TAG, "mode=DRAG");
mode = DRAG;
break;
case MotionEvent.ACTION_MOVE:
if (mode == DRAG) {
// ...
matrix.set(savedMatrix);
matrix.postTranslate(event.getX() - start.x, event.getY()- start.y);
}
break;
}
setImageMatrix(matrix);
return true; // indicate event was handled
}
});
}
public void setImage(Bitmap bm, int displayWidth, int displayHeight) {
super.setImageBitmap(bm);
int displayheight = (getResources().getDisplayMetrics().heightPixels)/2;
int displaywidth = (getResources().getDisplayMetrics().widthPixels)/2;
int imgw = displayWidth/2;
int imgh = displayHeight/2;
// Fit to screen.
float scale;
if ((displayHeight / bm.getHeight()) >= (displayWidth / bm.getWidth())) {
scale = (float) displayWidth / (float) bm.getWidth();
} else {
scale = (float) displayHeight / (float) bm.getHeight();
}
savedMatrix.set(matrix);
matrix.set(savedMatrix);
matrix.postScale(scale, scale, mid.x, mid.y);
setImageMatrix(matrix);
savedMatrix.set(matrix);
matrix.set(savedMatrix);
matrix.postTranslate(displaywidth - imgw, displayheight - imgh);
setImageMatrix(matrix);
}
}