Can some one please help me few things regarding mapview im trying to build. I have a renderer that takes canvas and draws a bitmap in it. I have created a view and in constructor i create:
bitmap = Bitmap.createBitmap(windowWidth, windowHeight, Bitmap.Config.ARGB_8888);
canvas = new Canvas(bitmap);
drawable = new BitmapDrawable(bitmap);
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
this.Render();
In onDraw method i have this:
super.onDraw(canvas);
canvas.save();
canvas.translate(mPosX, mPosY);
canvas.scale(mScaleFactor, mScaleFactor);
drawable.draw(canvas);
canvas.restore();
Now i would like to implement pan and zoom (currently im working without saved tiles) Here is my onTouch:
mScaleDetector.onTouchEvent(ev);
final int action = ev.getAction();
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: {
this.hasPanned = false;
final float x = ev.getX();
final float y = ev.getY();
mLastTouchX = x;
mLastTouchY = y;
mActivePointerId = ev.getPointerId(0);
break;
}
case MotionEvent.ACTION_MOVE: {
开发者_JS百科 final int pointerIndex = ev.findPointerIndex(mActivePointerId);
final float x = ev.getX(pointerIndex);
final float y = ev.getY(pointerIndex);
if (!mScaleDetector.isInProgress()) {
final float dx = x - mLastTouchX;
final float dy = y - mLastTouchY;
mPosX += dx;
mPosY += dy;
invalidate();
}
mLastTouchX = x;
mLastTouchY = y;
break;
}
case MotionEvent.ACTION_UP: {
mActivePointerId = INVALID_POINTER_ID;
if (this.mDownTouchX != this.mLastTouchX && this.mDownTouchY != mLastTouchY)
this.hasPanned = true;
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) {
final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
mLastTouchX = ev.getX(newPointerIndex);
mLastTouchY = ev.getY(newPointerIndex);
mActivePointerId = ev.getPointerId(newPointerIndex);
}
break;
}
}
return true;
Here is what i would like and problems i have:
- When i pan i would like to calculate distance in pixels so i can tell my renderer when it renders the image again. How is this achieved? By remembering coordinates on ACTION_DOWN and comparing with new coordinates in ACTION_UP ?
- When pan is complete (and image is re-rendered) i would like to set the canvas(image) back to its original position. Currently it stays paned (because of canvas.translate?)
- How do i handle zoom gestures? With this code when doing a zoom-out with my fingers the image is "dragged" towards top left corner ...
Im new in android (and java) so any help is preciated.
If your zoom code zooms the Canvas but doesn't move it correctly, I suspect you are calling the wrong Canvas.scale() method. The method you are using seems to be -
scale(float sx, float sy)
and I think you need to use -
scale(float sx, float sy, float px, float py)
sx & sy are obviously the x & y scale factors (I normally set them to the same value). px & py are the centre points for the Zoom operation, e.g. the mid point between the MotionEvent.ACTION_DOWN and MotionEvent.ACTION_POINTER_DOWN event coordinates.
In my MotionEvent.ACTION_POINTER_DOWN handler I call -
midPoint(mid, event);
mid is defined as -
private PointF mid = new PointF();
and the midPoint function is -
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);
}
so in my MotionEvent.ACTION_MOVE handler I would call -
Canvas.scale(sx, sy, mid.x, mid.y);
1) Yes, in the ACTION_DOWN just do
PontF downAt = new PointF(event.getX(), event.getY());
and in ACTION_UP calculate the difference between pixels.
2) The MapView works differently to an ImageView. For a MapView you would use
mapView.getController().animateTo(GeoPoint);
but I think you really want to subclass from an ImageView and override the onDraw(Canvas canvas) method for direct access to the Canvas. Then use a Matrix to handle translation & zooming, e.g.
imageView.setScaleType(ImageView.ScaleType.MATRIX);
Matrix imageMatrix = new Matrix();
imageMatrix.postTranslate(xMove, yMove);
imageMatrix.postScale(scaleX, scaleY, midX, midY);
imageView.setImageMatrix(imageMatrix);
3) To handle ZOOM gestures, you need to handle the ACTION_POINTER_DOWN, ACTION_MOVE & ACTION_POINTER_UP events. There is a really good tutorial here - How to use Multi-touch in Android
Be careful when you ZOOM an imageView, any subsequent drawing on it needs the X,Y co-ordinates also scaled, use the Matrix mapPoints(Pts) method to do this.
精彩评论