Повернутое представление OpenStreetMap - как прокрутить карту в направлении движения пальца после поворота в Android? - PullRequest
6 голосов
/ 29 декабря 2011

Я использую OSM для картографического приложения, где я поверните карту в направлении движения, как описано здесь Android Rotating MapView Это хорошо работает.

Однако мне пока не удалось настроить код dispatchTouchEvent. противостоять эффекту поворота карты для касаний пользователя (прямо сейчас когда карта повернута на 90 градусов, горизонтальная развертка пользователя сместится карта по вертикали и т. д.). Пример кода предлагает только тизер:

   public boolean dispatchTouchEvent(MotionEvent ev) {
        // TODO: rotate events too
        return super.dispatchTouchEvent(ev);
    }

Любое руководство будет оценено.

А пока я на это - можно ли еще установить зум контролирует отдельно, чтобы они НЕ вращались при вращении карты? Я прочитал, что getZoomControls () устарела. (Почему?)

1 Ответ

1 голос
/ 26 июня 2012

Я знаю, что уже слишком поздно, но это может кому-то помочь ...

import org.osmdroid.views.overlay.MyLocationOverlay;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Canvas;
import android.graphics.Matrix ;
import android.hardware.Sensor;
import android.os.BatteryManager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.RelativeLayout;
/**
* Rotate the Map in accordance to the movement of user and always point to North
*
*/
public class RotatingRelativeLayout extends RelativeLayout 
{
    private Matrix mMatrix = new Matrix();
    private float[] mTemp = new float[2]; 
private Context  context;
private static final float SQ2 = 1.414213562373095f;
public RotatingRelativeLayout(final Context pContext,
    final AttributeSet pAttrs)
{
super(pContext, pAttrs);

this.context=pContext;

}

@Override
protected void dispatchDraw(Canvas canvas) {

long  rotateTime = MyLocationOverlay.getTimeOfMovement();
float overlayBearing = MyLocationOverlay.getBearing();//this method returns current      bearing from OSM 
long  currentTime = System.currentTimeMillis();
long  diffTime = currentTime-rotateTime;
/*
 * Here we rotate map in accordance with Compass to point always North
     *  
 */

 if(diffTime >= (40*1000 )){

    //isBearing=false;
    overlayBearing=0;
    canvas.rotate(overlayBearing, getWidth() * 0.5f, getHeight() * 0.5f);

}
else 
/*
 * Rotate Map According to the user movement
 */
canvas.rotate(-overlayBearing, getWidth() * 0.5f, getHeight() * 0.5f);
canvas.getMatrix().invert(mMatrix);
final float w = this.getWidth();
    final float h = this.getHeight();

    final float scaleFactor = (float)(Math.sqrt(h * h + w * w) / Math.min(w, h));
    canvas.scale(scaleFactor, scaleFactor, getWidth() * 0.5f, getHeight() * 0.5f);
    super.dispatchDraw(canvas);
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.restore();

}

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {

final int width = getWidth();
final int height = getHeight();
final int count = getChildCount();
for (int i = 0; i < count; i++) {
final View view = getChildAt(i);
final int childWidth = view.getMeasuredWidth();
final int childHeight = view.getMeasuredHeight();
final int childLeft = (width - childWidth) / 2;
final int childTop = (height - childHeight) / 2;

view.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);

}

}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

int w = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
int h = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
int sizeSpec;

if (w > h) {

    sizeSpec = MeasureSpec.makeMeasureSpec((int) (w*SQ2), MeasureSpec.EXACTLY);

} 
else {

    sizeSpec = MeasureSpec.makeMeasureSpec((int) (h*SQ2), MeasureSpec.EXACTLY);

}

final int count = getChildCount();

for (int i = 0; i < count; i++) {
 getChildAt(i).measure(sizeSpec, sizeSpec);

}

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

}

@Override
public boolean dispatchTouchEvent(MotionEvent event) {

final float[] temp = mTemp;
temp[0] = event.getX();
temp[1] = event.getY();
mMatrix.mapPoints(temp);
event.setLocation(temp[0], temp[1]);

return super.dispatchTouchEvent(event);

}


    }

теперь просто используйте эту Относительную компоновку в вашем xml следующим образом: -

<YourPackageName.RotatingRelativeLayout     android:layout_width="fill_parent"  android:layout_height="fill_parent"  android:id="@+id/rotating_layout" android:layout_marginBottom="40dip"/>    

И добавить представление карты программно, как это: -

   // Find target container
    final RelativeLayout rl=(RelativeLayout)mParent.findViewById(R.id.rotating_layout);

    // Create rotator
    mRotator=new RotatingRelativeLayout(mParent, null);

    // Add map to the rotating layout
    // Add rotator to the screen
    rl.addView(mMap,new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT,  LayoutParams.FILL_PARENT));

здесь mParent - это Context. И еще одна вещь, если вы сталкиваетесь с проблемой Pixelation, вам просто нужно использовать ее

    //Paint distortion handling..
p.setFilterBitmap(true);

Надеюсь, я объяснил это так хорошо, как мог бы .... не стесняйтесь спрашивать, если вы обнаружите проблемы с пониманием этого.

Спасибо.

...