Translating and scaling a canvas, then finding bitmaps on touch!

  • Replies:1
  • OpenNot stickiedUnanswered
  • Forum posts: 4

Apr 30, 2013 11:23:58 AM via Website

So I have a canvas that I draw a bitmap onto.. When the scalefactor of the canvas is 1.0f everything works perfectly how I want it to.. However the problem is when I change the scale of the canvas. Either zoomed in or out I run into problems with the coordinates and finding the bitmap so I can move it on touch..

I've tried dividing coordinates by the scalefactor.. multiplying.. I just can't work out the right calculation to get my desired result! Please help!

Here is my code

1public void onDraw(Canvas canvas) {
2 // Log.v(TAG, "onDraw()");
3 clipBounds = canvas.getClipBounds();
4 if (bitmap == null) {
5 Log.w(TAG, "nothing to draw - bitmap is null");
6 super.onDraw(canvas);
7 return;
8 }
9
10 if (firstDraw && (bitmap.getHeight() > 0) && (bitmap.getWidth() > 0)) {
11 // Don't let the user zoom out so much that the image is smaller
12 // than its containing frame
13 float minXScaleFactor = (float) viewWidth
14 / (float) bitmap.getWidth();
15 float minYScaleFactor = (float) viewHeight
16 / (float) bitmap.getHeight();
17 minScaleFactor = Math.max(minXScaleFactor, minYScaleFactor);
18 Log.d(TAG, "minScaleFactor: " + minScaleFactor);
19 // mScaleFactor = minScaleFactor; //start out "zoomed out" all the
20 // way
21
22 mPosX = mPosY = 0;
23 firstDraw = false;
24 }
25 mScaleFactor = Math.max(mScaleFactor, minScaleFactor);
26
27 canvasHeight = canvas.getHeight();
28 canvasWidth = canvas.getWidth();
29 // Log.d(TAG, "canvas density: " + canvas.getDensity() +
30 // " bitmap density: " + bitmap.getDensity());
31
32 // Log.d(TAG, "mScaleFactor: " + mScaleFactor);
33
34 // Save the canvas without translating (panning) or scaling (zooming)
35 // After each change, restore to this state, instead of compounding
36 // changes upon changes
37 canvas.save();
38 int maxX, minX, maxY, minY;
39 // Regardless of the screen density (HDPI, MDPI) or the scale factor,
40 // The image always consists of bitmap width divided by 2 pixels. If an
41 // image
42 // is 200 pixels wide and you scroll right 100 pixels, you just scrolled
43 // the image
44 // off the screen to the left.
45 minX = (int) (((viewWidth / mScaleFactor) - bitmap.getWidth()) / 2);
46 maxX = 0;
47 // How far can we move the image vertically without having a gap between
48 // image and frame?
49 minY = (int) (((viewHeight / mScaleFactor) - bitmap.getHeight()) / 2);
50 maxY = 0;
51 // Log.d(TAG, "minX: " + minX + " maxX: " + maxX + " minY: " + minY
52 // + " maxY: " + maxY);
53 // Do not go beyond the boundaries of the image
54 if (mPosX > maxX) {
55 mPosX = maxX;
56 }
57 if (mPosX < minX) {
58 mPosX = minX;
59 }
60 if (mPosY > maxY) {
61 mPosY = maxY;
62 }
63 if (mPosY < minY) {
64 mPosY = minY;
65 }
66
67 canvas.scale(mScaleFactor, mScaleFactor);
68 // canvas.scale(0.6f, 0.6f);
69 // Log.i("","mPos " + mPosX);
70 canvas.translate(mPosX, mPosY);
71
72 canvas.drawBitmap(bitmap, mPosX, mPosY, null);
73 canvas.drawBitmap(bmp, bPosX + mPosX, bPosY + mPosY, null);
74
75 if (!firstDraw) {
76 bitmapCanvas.drawBitmap(bitmap, mPosX, mPosY, null);
77 bitmapCanvas.drawBitmap(bmp, bPosX + mPosX, bPosY + mPosY, null);
78 }
79
80 super.onDraw(canvas);
81
82 canvas.restore(); // clear translation/scaling
83}
84
85@Override
86public boolean onTouchEvent(MotionEvent ev) {
87 // Let the ScaleGestureDetector inspect all events.
88 if (zoomEnabled) {
89 mScaleDetector.onTouchEvent(ev);
90 }
91
92 if (panEnabled) {
93 final int action = ev.getAction();
94 switch (action & MotionEvent.ACTION_MASK) {
95
96 case MotionEvent.ACTION_DOWN: {
97 final float x = ev.getX();
98 final float y = ev.getY();
99
100 mLastTouchX = x;
101 mLastTouchY = y;
102
103 mActivePointerId = ev.getPointerId(0);
104
105 int mx = (int) mPosX * -1;
106 int my = (int) mPosY * -1;
107
108 // int checkPointX = (int) (x + mx * 2);
109 // int checkPointY = (int) (y + my * 2);
110
111 int checkPointX = (int) (x + mx * 2);
112 int checkPointY = (int) (y + my * 2);
113
114 Log.i("ZOOMS", "ScaleFactor " + mScaleFactor);
115 Log.i("TOUCH COORD", "x " + checkPointX + " y " + checkPointY);
116 Log.i("BMP POS", "x " + bPosX + " bw " + (bPosX + bmp.getWidth()) + " y " + bPosY + " yw " + (bPosY + bmp.getHeight()));
117
118 if (checkPointX > bPosX
119 && checkPointX <= bPosX + bmp.getWidth()
120 && checkPointY >= bPosY
121 && checkPointY <= bPosY + bmp.getHeight())
122 bitmapFound = true;
123 else
124 bitmapFound = false;
125
126 // if(mx > bmp.)
127 break;
128 }
129
130 case MotionEvent.ACTION_MOVE: {
131 final int pointerIndex = ev.findPointerIndex(mActivePointerId);
132 final float x = ev.getX(pointerIndex);
133 final float y = ev.getY(pointerIndex);
134
135 // Only move if the ScaleGestureDetector isn't processing a
136 // gesture.
137 if (!mScaleDetector.isInProgress()) {
138 if (bitmapFound) {
139 int mx = (int) mPosX * -1;
140 int my = (int) mPosY * -1;
141
142 int checkPointX = (int) (x + mx * 2);
143 int checkPointY = (int) (y + my * 2);
144
145 moveBitmap(checkPointX, checkPointY);
146 } else
147 moveCanvas(x, y);
148
149 invalidate();
150 }
151 mLastTouchX = x;
152 mLastTouchY = y;
153
154 break;
155 }
156
157 case MotionEvent.ACTION_UP: {
158 mActivePointerId = INVALID_POINTER_ID;
159 break;
160 }
161
162 case MotionEvent.ACTION_CANCEL: {
163 mActivePointerId = INVALID_POINTER_ID;
164 break;
165 }
166
167 case MotionEvent.ACTION_POINTER_UP: {
168 final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
169 final int pointerId = ev.getPointerId(pointerIndex);
170 if (pointerId == mActivePointerId) {
171 // This was our active pointer going up. Choose a new
172 // active pointer and adjust accordingly.
173 final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
174 mLastTouchX = ev.getX(newPointerIndex);
175 mLastTouchY = ev.getY(newPointerIndex);
176 mActivePointerId = ev.getPointerId(newPointerIndex);
177
178 }
179 break;
180 }
181 }
182 }
183 return true;
184}
185
186public void moveBitmap(float x, float y) {
187
188 // Adjust for zoom factor. Otherwise, the user's finger moving 10 pixels
189 // at 200% zoom causes the image to slide 20 pixels instead of perfectly
190 // following the user's touch
191
192 x = x / mScaleFactor;
193 y = y / mScaleFactor;
194
195 bPosX = x;
196 bPosY = y;
197
198}
199
200public void moveCanvas(float x, float y) {
201 float dx = x - mLastTouchX;
202 float dy = y - mLastTouchY;
203
204 // Adjust for zoom factor. Otherwise, the user's finger moving 10 pixels
205 // at 200% zoom causes the image to slide 20 pixels instead of perfectly
206 // following the user's touch
207 dx /= (mScaleFactor * 2);
208 dy /= (mScaleFactor * 2);
209
210 mPosX += dx;
211 mPosY += dy;
212
213 // Log.v(TAG, "moving by " + dx + "," + dy + " mScaleFactor: " +
214 // mScaleFactor);
215}
216
217private class ScaleListener extends
218 ScaleGestureDetector.SimpleOnScaleGestureListener {
219 @Override
220 public boolean onScale(ScaleGestureDetector detector) {
221 mScaleFactor *= detector.getScaleFactor();
222 // Don't let the object get too small or too large.
223 mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 5.0f));
224 // Log.d(TAG, "detector scale factor: " + detector.getScaleFactor()
225 // + " mscalefactor: " + mScaleFactor);
226
227 invalidate();
228 return true;
229 }
230}
  • Forum posts: 4

May 3, 2013 9:25:09 AM via Website

so many people viewing !!

Is there something I can explain differently? Present the source code in a different way!?