Rotational view of OpenStreetMap - how to lay a map in the direction of finger movement after rotation in Android?

I use OSM for the display application, where I rotate the map in the direction of movement, as described here Android Rotating MapView . It works well.

However, I have not yet been able to configure the dispatchTouchEvent code to counter the effect of map rotation for touching the user (right now when the map rotates 90 degrees, the horizontal scan of the user will move the map vertically, etc.). Sample code only offers a teaser:

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

Any guidance would be appreciated.

And while I'm in it - is it possible to put the scale controls separately so that they do not rotate when the map rotates? I read that getZoomControls () is deprecated. (Why?)

+6
source share
1 answer

I know this is too late, but it may help someone ...

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

now just use this relative layout in your xml like this: -

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

And add Map View Programatially as follows: -

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

here mParent is the context. And one more thing, if you come across Image Pixelation prob, you just have to use it

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

Hopefully I explained it as best I could .... feel free to ask if you have found a problem understanding this.

Thanks.

+1
source

Source: https://habr.com/ru/post/904669/


All Articles