ANDROID - MapView - PullRequest
       20

ANDROID - MapView

2 голосов
/ 11 мая 2011

Может кто-нибудь, пожалуйста, помогите мне несколько вещей относительно mapview, который я пытаюсь построить. У меня есть рендер, который берет холст и рисует в нем растровое изображение. Я создал вид и в конструкторе я создаю:

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();

В методе onDraw у меня есть это:

super.onDraw(canvas);
canvas.save();
canvas.translate(mPosX, mPosY);
canvas.scale(mScaleFactor, mScaleFactor);
drawable.draw(canvas);
canvas.restore();

Теперь я хотел бы реализовать панорамирование и масштабирование (в настоящее время я работаю без сохраненных плиток) Вот мое прикосновение:

mScaleDetector.onTouchEvent (эв);

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: {
    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;

Вот то, что я хотел бы, и проблемы, которые у меня есть:

  1. Когда я выполняю панорамирование, я хотел бы рассчитать расстояние в пикселях, чтобы я мог сказать своему рендереру, когда он снова отрисовывает изображение. Как это достигается? Запоминание координат в ACTION_DOWN и сравнение с новыми координатами в ACTION_UP?
  2. Когда панорамирование завершено (и изображение перерисовано), я бы хотел вернуть холст (изображение) в исходное положение. В настоящее время он остается панорамированным (из-за canvas.translate?)
  3. Как мне управлять жестами зума? С помощью этого кода при масштабировании пальцами изображение «перетаскивается» в верхний левый угол ...

Я новичок в Android (и Java), поэтому любая помощь является приоритетной.

Ответы [ 2 ]

2 голосов
/ 31 мая 2011

Если ваш код масштабирования увеличивает Canvas, но не перемещает его правильно, я подозреваю, что вы вызываете неправильный метод Canvas.scale ().Кажется, вы используете метод -

scale(float sx, float sy)

, и я думаю, что вам нужно использовать -

scale(float sx, float sy, float px, float py)

sx & sy, очевидно, являются масштабными коэффициентами x & y (я обычно устанавливаюих к тому же значению).px & py - это центральные точки для операции Zoom, например, средняя точка между координатами события MotionEvent.ACTION_DOWN и MotionEvent.ACTION_POINTER_DOWN.

В моем обработчике MotionEvent.ACTION_POINTER_DOWN я вызываю -

midPoint(mid, event);

mid определяется как -

private PointF mid = new PointF();

, а функция midPoint - -

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);
}

, поэтому в моем обработчике MotionEvent.ACTION_MOVE я бы назвал -

Canvas.scale(sx, sy, mid.x, mid.y);
1 голос
/ 28 мая 2011

1) Да, в ACTION_DOWN просто выполните

PontF downAt = new PointF(event.getX(), event.getY());

и в ACTION_UP рассчитайте разницу между пикселями.

2) MapView работает иначе, чем ImageView.Для MapView вы бы использовали

mapView.getController().animateTo(GeoPoint);

, но я думаю, что вы действительно хотите создать подкласс из ImageView и переопределить метод onDraw (Canvas canvas) для прямого доступа к Canvas.Затем используйте матрицу для обработки перевода и масштабирования, например,

imageView.setScaleType(ImageView.ScaleType.MATRIX);
Matrix imageMatrix = new Matrix();
imageMatrix.postTranslate(xMove, yMove);
imageMatrix.postScale(scaleX, scaleY, midX, midY);
imageView.setImageMatrix(imageMatrix);

3) Для обработки жестов ZOOM необходимо обрабатывать события ACTION_POINTER_DOWN, ACTION_MOVE & ACTION_POINTER_UP.Здесь есть действительно хорошее руководство - Как использовать Multi-touch в Android

Будьте осторожны, когда вы увеличиваете изображение, любое последующее рисование на нем требует также координат X, Yмасштабировать, используйте метод Matrix mapPoints (Pts) для этого.

...