I am trying to develop drawing application with large Canvas(size is 1440*2560). I have implemented Multi touch(two-finger) Pinch Zoom and Panning on it.
Problem:
After performing Zoom-in on Canvas when
I try to Zoom-out or Pan this Canvas,first Canvas is shifted by certain distance(either left of right) and then Scrolling or Pinch Zoom happens.
Implementation:
To implement this application, I have created custom view of size 3180*5420 .I have placed Canvas at center of this Custom view.To implement Pinch-Zoom I am using ScaleGestureDetector. For panning I am using ScrollView.
Code:
Custom View
public class DrawingView extends View {
private ScaleGestureDetector mScaleDetector;
private float mScaleFactor = 1.f;
private static Bitmap RedoIt= Bitmap.createBitmap(1440,2560, Config.ARGB_8888);;
private static Canvas mcanvas=new Canvas(RedoIt);
DrawingView drawview=(DrawingView)findViewById(R.id.single_touch_view);
@SuppressLint("NewApi")
public DrawingView(Context context, AttributeSet attrs) {
super(context, attrs);
paint.setAntiAlias(true);
paint.setStrokeWidth(5f);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
} }
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.save();
pathCounter++;
g.setFlag(false);
canvas.scale(mScaleFactor, mScaleFactor,scalePointX,scalePointY);
canvas.drawBitmap(RedoIt,870,1430, null); // to place canvas at center
if(g.getstr().equals("OLIVE"))
setColorint(128,128,0);
else if(g.getstr().equals("ORANGE"))
setColorint(255,153,0);
else if(g.getstr().equals("BROWN"))
setColorint(165,42,42);
else
setColor(g.getstr());
paths.add(path);
colorsMap.put(path,paint.getColor());
canvas.restore();
}
public boolean onTouchEvent(MotionEvent event) {
// Get the coordinates of the touch event.
float eventX = event.getX()-870;
float eventY = event.getY()-1430;
**// for Pinch Zoom and panning**
mode=1;
switch (event.getAction()& MotionEvent.ACTION_MASK) {
case Mot
ionEvent.ACTION_DOWN:
x1=event.getX(pointerIndex)-870;
y1=event.getY(pointerIndex)-1430;
return true;
case MotionEvent.ACTION_POINTER_DOWN:
mSecondPointerId = event.getPointerId(1);
counter=0;
pointerIndex2 = event.findPointerIndex(mSecondPointerId);
x2=event.getX(pointerIndex2)-870;
y2=event.getY(pointerIndex2)-1430;
mScaleDetector = new ScaleGestureDetector(DrawingView.this.getContext() , new ScaleListener());
dist1=(float) Math.sqrt(Math.pow(x1-x2,2)+Math.pow(y1-y2,2));
case MotionEvent.ACTION_MOVE:
{
x3=event.getX(pointerIndex)-870;
y3=event.getY(pointerIndex)-1430;
x4=event.getX(pointerIndex2)-870;
y4=event.getY(pointerIndex2)-1430;
dist2=(float) Math.sqrt(Math.pow(x3-x4,2)+Math.pow(y3-y4,2));
counter++;
if(counter==4){
**//To detect two finger Panning action**
if(Math.abs(dist1-dist2)<5){
flag=true; // Enable panning
getParent().requestDisallowInterceptTouchEvent(false);
}
}}
break;
case MotionEvent.ACTION_POINTER_UP:
mode =1;
flag2=false;
getParent().requestDisallowInterceptTouchEvent(true);
return true;
default:
return false;
}
invalidate();
if(flag==false)// no panning action detected
{
flagZoom=true;
mScaleDetector.onTouchEvent(event);
getParent().requestDisallowInterceptTouchEvent(true);
}
return true;
}
}
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
public boolean onScaleBegin(ScaleGestureDetector detector) {
getParent().requestDisallowInterceptTouchEvent(true);
super.onScaleBegin(detector);
return true;
}
public boolean onScale(ScaleGestureDetector detector) {
scalePointX = detector.getFocusX();
scalePointY = detector.getFocusY();
getParent().requestDisallowInterceptTouchEvent(true);
mScaleFactor *= detector.getScaleFactor();
mScaleFactor = Math.max(0.25f, Math.min(mScaleFactor, 2.0f));
invalidate();
return true;
}
public void onScaleEnd(ScaleGestureDetector detector1) {
getParent().requestDisallowInterceptTouchEvent(false);
super.onScaleEnd(detector1);
}
}
Custom View Layout File:
<HorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:fadeScrollbars="false"
android:id="@+id/horizontalscrollview"
>
<ScrollView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:fadeScrollbars="false"
android:id="@+id/scrollview">
<AbsoluteLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<!-- This is the view on which we will draw. -->
<view
android:layout_width="3180px"
android:layout_height="5420px"
android:scaleType="matrix"
android:layout_x="0px"
android:layout_y="0px"
class="com.example.DrawingView"
android:id="@+id/single_touch_view"
android:scrollbars="horizontal|vertical"
android:background="@drawable/brown_wood" />
</AbsoluteLayout>
</ScrollView>
</HorizontalScrollView>
As I am keeping ScaleGesturedetector always active, That may be the possible reason for this issue.Is there any way to disable ScaleGesturedetector ? or any other modification in code is required .
[check this](http://developer.android.com/reference/android/graphics/Canvas.html#concat(android.graphics.Matrix)) – Nimesh Chandramaniya Jun 28 '14 at 12:07