Android Rotating MapView

I am creating an application that traces the path of users on a map. What I want to achieve when the user makes a left turn, for example, the card must rotate it independently so that the head of the card should always point in an upward direction. Hope this makes sense.

I stumbled upon a message from Mr. Romain Guy and he says

I have done this in the past, and it is required to create a custom ViewGroup that rotates the canvas in dispatchDraw (). You also need to increase the size of the MapView (so that it draws enough pixels when rotating.) You also need to rotate the touch events in dispatchTouchEvent (). Or if you are using Android 3.0, you can just call theMapView.rotate ():

Has anyone come up with a solution similar to my question? A working example would be excellent :)

+5
source share
3 answers

Keep in mind that this is not an ideal approach, because the text on the map is a static image and will rotate along with the maps (at some point it will be turned upside down).

Here's an example of how to put a MapView in your own Layout widget and rotate it. I did this using OpenStreetMaps, but for Google Maps it should be exactly the same.

First create a spinning widget. Layout

 package com.eli.util; import android.content.Context; import android.graphics.Canvas; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.widget.LinearLayout; public class RotatingLinearLayout extends LinearLayout { private final int mDiagonal; private float mBearing; public RotatingLinearLayout(final Context pContext, final AttributeSet pAttrs) { super(pContext, pAttrs); final DisplayMetrics dm = pContext.getResources().getDisplayMetrics(); mDiagonal = (int) Math.hypot(dm.widthPixels, dm.heightPixels); } public void setBearing(final float pBearing) { mBearing = pBearing; } @Override protected void dispatchDraw(final Canvas pCanvas) { pCanvas.rotate(-mBearing, getWidth() >> 1, getHeight() >> 1); super.dispatchDraw(pCanvas); } @Override protected void onMeasure(final int pWidthMeasureSpec, final int pHeightMeasureSpec) { final int widthMode = MeasureSpec.getMode(pWidthMeasureSpec); final int heightMode = MeasureSpec.getMode(pHeightMeasureSpec); super.onMeasure(MeasureSpec.makeMeasureSpec(mDiagonal, widthMode), MeasureSpec.makeMeasureSpec(mDiagonal, heightMode)); } } 

Surround it with your MapView in layout.xml

 <com.eli.util.RotatingLinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/rotating_layout"> <org.osmdroid.views.MapView android:id="@+id/map_view" android:layout_width="fill_parent" android:layout_height="fill_parent" android:enabled="true" android:clickable="true"/> </com.eli.util.RotatingLinearLayout> 

Now, every time you get a geo patch, update the bearing of the rotating layout and it should rotate.

+8
source

Here is the code that worked for me to have the correct centering of the view

 @Override protected void dispatchDraw(final Canvas pCanvas) { int translateX = mDiagonal / 2 - screenWidth / 2; int translateY = mDiagonal / 2 - screenHeight / 2; pCanvas.translate(- translateX, - translateY); pCanvas.rotate(-mBearing, mDiagonal / 2, mDiagonal / 2); super.dispatchDraw(pCanvas); } 
+2
source

You can find an example when installing android sdk

 android-sdks/add-ons/addon-google_apis-google_inc_-8/samples/MapDemo 

But maybe you need to change a little two methods to get the correct orientation when touched.

 private class RotateView extends ViewGroup implements SensorListener { /* ... */ private Matrix invertedMatrix = new Matrix(); private float[] tempLocation = new float[2]; @Override protected void dispatchDraw(Canvas canvas) { canvas.save(Canvas.MATRIX_SAVE_FLAG); canvas.rotate(mHeading, getWidth() * 0.5f, getHeight() * 0.5f); canvas.getMatrix().invert(invertedMatrix); mCanvas.delegate = canvas; super.dispatchDraw(mCanvas); canvas.restore(); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { centeringAllowed = false; float[] location = tempLocation; location[0] = ev.getX(); location[1] = ev.getY(); invertedMatrix.mapPoints(location); ev.setLocation(location[0], location[1]); return super.dispatchTouchEvent(ev); } } 

This class is part of the MapDemo project.

0
source

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


All Articles