0

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 .

  • see how simply it can be done in my answer here http://stackoverflow.com/questions/21633545/android-imageview-scaling-and-translating-issue, you would need to use Canvas.concat in onDraw methot instead of drawBitmap(Bitmap, Matrix, Paint) – pskink Jun 28 '14 at 06:12
  • Thanks for the reply.But with Canvas.concat how can I place Canvas at center of Drawing View? – Nimesh Chandramaniya Jun 28 '14 at 11:41
  • there is no such thing like place the Canvas somewhere, Canvas always fill the whole View – pskink Jun 28 '14 at 11:43
  • Actually ,I was talking about how to place Bitmap at center of view, On which user can perform drawing.In my case Bitmap is "RedoIt". – Nimesh Chandramaniya Jun 28 '14 at 11:50
  • you mean Canvas.drawBitmap(Bitmap, float, float, Paint)? – pskink Jun 28 '14 at 11:53
  • Yes. My application does drawing on white Bitmap named RedoIt. So how can I placed that Bitmap at center of Custom View with Canvas.concat ? – Nimesh Chandramaniya Jun 28 '14 at 11:56
  • you have float x and float y params or there is something I'm missing? – pskink Jun 28 '14 at 12:02
  • No.Canvas.concat(matrix) has only matrix as a parameter.
    [check this](http://developer.android.com/reference/android/graphics/Canvas.html#concat(android.graphics.Matrix))
    – Nimesh Chandramaniya Jun 28 '14 at 12:07
  • yes it accepts a Matrix as a parameter, what else would it accept? – pskink Jun 28 '14 at 12:10

0 Answers0