2017-12-28 6 views
1

Ich verwende google maps auf meinem Projekt. Ich möchte den Pfeil auf den Bildschirm setzen, wenn der Marker nicht auf dem Bildschirm angezeigt wird. Wie kann ich den Bildschirm steuern?Google Maps Screen Control

+0

Warum wollen Sie Pfeil hinzufügen? –

+0

Ich möchte die Markierrichtung anzeigen (wenn die Markierung auf dem rechten Pfeil ist, wird sie nach rechts zeigen) –

+1

Holen Sie sich den Lat, lng der Mitte der Kamera und holen Sie sich die Richtung zum Marker. Basierend auf dem Winkel können Sie die Pfeile rechts, links, oben und unten oben auf der Karte einblenden. –

Antwort

0

Eigentlich ist die Antwort für Ihre Frage in lakshman.pasala Kommentar, aber seine Implementierung ist ein bisschen komplex (TLDR).

So ist der beste Weg, Google Maps Screen Control zu bekommen - ist implement custom view, die MapView Klasse erweitert. In diesem Fall haben Sie die volle Kontrolle über das Zeichnen auf der Leinwand. Um dies zu tun, sollten Sie dispatchDraw() Methode überschreiben (weil erweitert FrameLayout, die ViewGroup ist) und implementieren Sie darin Pfeilzeichnung. So etwas Ähnliches:

@Override 
public void dispatchDraw(Canvas canvas) { 
    super.dispatchDraw(canvas); 
    canvas.save(); 
    drawArrowToMarker(canvas); 
    canvas.restore(); 
} 

und Sie müssen es nennen über invalidate() auf jeder Karte verschieben/Zoom/drehen. Zum Erkennen der Karte verschieben/zoomen/drehen benötigen Sie GoogleMap (genau GoogleMap.setOnCameraMoveListener() Methode). Sie können das Objekt GoogleMap in Ihrer benutzerdefinierten MapView-Klasse deklarieren und über Setter festlegen, aber besser, wenn die benutzerdefinierte MapView-Klasse die OnMapReadyCallback-Schnittstelle implementiert und in onMapReady() Callback abgerufen wird. Ihre Notwendigkeit auch mehr Hilfsmethoden für das Hinzufügen/Entfernen Marker bestimmt Segmente Kreuzungen, Richtungen usw. Die vollständige Quellcode von benutzerdefinierter Ansicht (zB EnhanchedMapView) kann wie:

public class EnhanchedMapView extends MapView implements OnMapReadyCallback { 

    private final static int ARROW_PADDING = 50; 
    private final static double ARROW_ANGLE = Math.PI/6; 
    private final static double ARROW_LENGTH = 100; 
    private final static double ARROW_SIZE = 50; 

    private OnMapReadyCallback mMapReadyCallback; 
    private GoogleMap mGoogleMap; 
    private Marker mMarker; 
    private Paint mPaintArrow; 

    public EnhanchedMapView(@NonNull Context context) { 
     super(context); 
     init(); 
    } 

    public EnhanchedMapView(@NonNull Context context, @Nullable AttributeSet attrs) { 
     super(context, attrs); 
     init(); 
    } 

    public EnhanchedMapView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 
     super(context, attrs, defStyleAttr); 
     init(); 
    } 

    public EnhanchedMapView(@NonNull Context context, @Nullable GoogleMapOptions options) { 
     super(context, options); 
     init(); 
    } 

    @Override 
    public void dispatchDraw(Canvas canvas) { 
     super.dispatchDraw(canvas); 
     canvas.save(); 
     drawArrowToMarker(canvas); 
     canvas.restore(); 
    } 

    private void drawArrowToMarker(Canvas canvas) { 
     if (mGoogleMap == null || mMarker == null) { 
      return; 
     } 

     VisibleRegion visibleRegion = mGoogleMap.getProjection().getVisibleRegion(); 
     LatLngBounds screenBounds = visibleRegion.latLngBounds; 

     LatLng mapCenter = screenBounds.getCenter(); 
     Projection mapProjection = mGoogleMap.getProjection(); 

     final Point pointMapCenter = mGoogleMap.getProjection().toScreenLocation(mapCenter); 

     final Point pointTopLeft = mapProjection.toScreenLocation(visibleRegion.farLeft); 
     final Point pointTopRight = mapProjection.toScreenLocation(visibleRegion.farRight); 
     final Point pointBottomLeft = mapProjection.toScreenLocation(visibleRegion.nearLeft); 
     final Point pointBottomRight = mapProjection.toScreenLocation(visibleRegion.nearRight); 
     final Point pointMarker = mapProjection.toScreenLocation(mMarker.getPosition()); 

     final Point tl = new Point(pointTopLeft.x + ARROW_PADDING, pointTopLeft.y + ARROW_PADDING); 
     final Point tr = new Point(pointTopRight.x - ARROW_PADDING, pointTopRight.y + ARROW_PADDING); 
     final Point br = new Point(pointBottomRight.x - ARROW_PADDING, pointBottomRight.y - ARROW_PADDING); 
     final Point bl = new Point(pointBottomLeft.x + ARROW_PADDING, pointBottomLeft.y - ARROW_PADDING); 

     final Point pointIntersection = getBoundsIntersection(tl, tr, br, bl, pointMapCenter, pointMarker); 
     if (pointIntersection != null) { 
      double angle = Math.atan2(pointMarker.y - pointMapCenter.y, pointMarker.x - pointMapCenter.x); 

      int arrowX, arrowY; 
      arrowX = (int) (pointIntersection.x - ARROW_LENGTH * Math.cos(angle)); 
      arrowY = (int) (pointIntersection.y - ARROW_LENGTH * Math.sin(angle)); 
      canvas.drawLine(pointIntersection.x, pointIntersection.y, arrowX, arrowY, mPaintArrow); 

      arrowX = (int) (pointIntersection.x - ARROW_SIZE * Math.cos(angle + ARROW_ANGLE)); 
      arrowY = (int) (pointIntersection.y - ARROW_SIZE * Math.sin(angle + ARROW_ANGLE)); 
      canvas.drawLine(pointIntersection.x, pointIntersection.y, arrowX, arrowY, mPaintArrow); 

      arrowX = (int) (pointIntersection.x - ARROW_SIZE * Math.cos(angle - ARROW_ANGLE)); 
      arrowY = (int) (pointIntersection.y - ARROW_SIZE * Math.sin(angle - ARROW_ANGLE)); 
      canvas.drawLine(pointIntersection.x, pointIntersection.y, arrowX, arrowY, mPaintArrow); 
     } 
    } 

    private void init() { 
     setWillNotDraw(false); 

     mPaintArrow = new Paint(); 
     mPaintArrow.setColor(Color.BLUE); 
     mPaintArrow.setStrokeWidth(15); 
    } 

    @Override 
    public void getMapAsync(OnMapReadyCallback callback) { 
     mMapReadyCallback = callback; 
     super.getMapAsync(this); 
    } 

    @Override 
    public void onMapReady(GoogleMap googleMap) { 
     mGoogleMap = googleMap; 
     mGoogleMap.setOnCameraMoveListener(new GoogleMap.OnCameraMoveListener() { 
      @Override 
      public void onCameraMove() { 
       invalidate(); 
      } 
     }); 
     if (mMapReadyCallback != null) { 
      mMapReadyCallback.onMapReady(googleMap); 
     } 
    } 

    public void addMarker(MarkerOptions markerOptions) { 
     removeMarker(); 
     mMarker = mGoogleMap.addMarker(markerOptions); 
    } 

    public void removeMarker() { 
     mGoogleMap.clear(); 
    } 

    private static boolean floatEquals(float f1, float f2) { 
     final double EPS = 1e-6; 
     return (Math.abs(f1 - f2) < EPS); 
    } 

    private static Point getBoundIntersection(Point p11, Point p12, Point p21, Point p22) { 
     double x, y; 
     Point intersectionPoint = null; 

     // test intersection with vertical bound 
     if (floatEquals(p12.x, p11.x) || floatEquals(p22.x, p21.x)) { 
      if (floatEquals(p12.x, p11.x) && floatEquals(p22.x, p21.x) && !floatEquals(p11.x, p21.x)) { 
       return null; 
      } else { 
       if (floatEquals(p12.x, p11.x)) { 
        x = p11.x; 
        y = (x - p21.x)/(p22.x - p21.x) * (p22.y - p21.y) + p21.y; 

        if (x >= Math.min(p21.x, p22.x) && x <= Math.max(p21.x, p22.x) 
          && y >= Math.min(p11.y, p12.y) && y <= Math.max(p11.y, p12.y)) { 
         intersectionPoint = new Point((int) x, (int) y); 
        } 
       } else { 
        x = p21.x; 
        y = (x - p11.x)/(p12.x - p11.x) * (p12.y - p11.y) + p11.y; 

        if (x >= Math.min(p11.x, p12.x) && x <= Math.max(p11.x, p12.x) 
          && y >= Math.min(p21.y, p22.y) && y <= Math.max(p21.y, p22.y)) { 
         intersectionPoint = new Point((int) x, (int) y); 
        } 
       } 
      } 
     } else { 
      // test intersection with horizontal bound 
      if (floatEquals(p12.y, p11.y) || floatEquals(p22.y, p21.y)) { 
       if (floatEquals(p12.y, p11.y) && floatEquals(p22.y, p21.y) && !floatEquals(p11.y, p21.y)) { 
        return null; 
       } else { 
        if (floatEquals(p12.y, p11.y)) { 
         y = p12.y; 
         x = (y - p21.y)/(p22.y - p21.y) * (p22.x - p21.x) + p21.x; 

         if (x >= Math.min(p11.x, p12.x) && x <= Math.max(p11.x, p12.x) 
           && y >= Math.min(p21.y, p22.y) && y <= Math.max(p21.y, p22.y)) { 
          intersectionPoint = new Point((int) x, (int) y); 
         } 
        } else { 
         y = p21.y; 
         x = (y - p11.y)/(p12.y - p11.y) * (p12.x - p11.x) + p11.x; 

         if (x >= Math.min(p21.x, p22.x) && x <= Math.max(p21.x, p22.x) 
           && y >= Math.min(p11.y, p12.y) && y <= Math.max(p11.y, p12.y)) { 
          intersectionPoint = new Point((int) x, (int) y); 
         } 
        } 

       } 
      } 
     } 

     return intersectionPoint; 
    } 

    private static Point getBoundsIntersection(Point tl, Point tr, Point br, Point bl, Point p1, Point p2) { 
     Point intersectionPoint = null; 
     if ((intersectionPoint = getBoundIntersection(tl, tr, p1, p2)) != null) { 
      return intersectionPoint; 
     } else if ((intersectionPoint = getBoundIntersection(tr, br, p1, p2)) != null) { 
      return intersectionPoint; 
     } else if ((intersectionPoint = getBoundIntersection(br, bl, p1, p2)) != null) { 
      return intersectionPoint; 
     } else if ((intersectionPoint = getBoundIntersection(bl, tl, p1, p2)) != null) { 
      return intersectionPoint; 
     } 
     return null; 
    } 

} 

Und Sie können es von MainActivity diese Art und Weise verwenden :

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    tools:context="{YOUR_PACKAGE_NAME}.MainActivity"> 

    <{YOUR_PACKAGE_NAME}.EnhanchedMapView 
     android:id="@+id/mapview" 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent" 
     /> 

</RelativeLayout> 

Als Ergebnis Sie shoul:

public class MainActivity extends AppCompatActivity { 

    private static final String MAP_VIEW_BUNDLE_KEY = "MapViewBundleKey"; 
    static final LatLng KYIV = new LatLng(50.450311, 30.523730); 

    private EnhanchedMapView mMapView; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     Bundle mapViewBundle = null; 
     if (savedInstanceState != null) { 
      mapViewBundle = savedInstanceState.getBundle(MAP_VIEW_BUNDLE_KEY); 
     } 

     mMapView = (EnhanchedMapView) findViewById(R.id.mapview); 
     mMapView.onCreate(mapViewBundle); 
     mMapView.getMapAsync(new OnMapReadyCallback() { 
      @Override 
      public void onMapReady(GoogleMap googleMap) { 
       mMapView.addMarker(new MarkerOptions().position(KYIV).title("Kyiv")); 
      } 
     }); 

    } 

    @Override 
    public void onSaveInstanceState(Bundle outState) { 
     super.onSaveInstanceState(outState); 

     Bundle mapViewBundle = outState.getBundle(MAP_VIEW_BUNDLE_KEY); 
     if (mapViewBundle == null) { 
      mapViewBundle = new Bundle(); 
      outState.putBundle(MAP_VIEW_BUNDLE_KEY, mapViewBundle); 
     } 

     mMapView.onSaveInstanceState(mapViewBundle); 
    } 

    @Override 
    protected void onResume() { 
     super.onResume(); 
     mMapView.onResume(); 
    } 

    @Override 
    protected void onStart() { 
     super.onStart(); 
     mMapView.onStart(); 
    } 

    @Override 
    protected void onStop() { 
     super.onStop(); 
     mMapView.onStop(); 
    } 
    @Override 
    protected void onPause() { 
     mMapView.onPause(); 
     super.onPause(); 
    } 
    @Override 
    protected void onDestroy() { 
     mMapView.onDestroy(); 
     super.onDestroy(); 
    } 
    @Override 
    public void onLowMemory() { 
     super.onLowMemory(); 
     mMapView.onLowMemory(); 
    } 

} 

Wo activity_main.xml können wie sein d so etwas bekommen:

Arrow to marker