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
Antwort
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:
- 1. Splash Screen wie Google
- 2. Google Maps Android LatLngBounds
- 3. Google Maps Clustering - JavaScript
- 4. angular-google-maps Aktualisierungsmodell
- 5. Angular Google Maps fitBounds
- 6. Responsive Google Maps
- 7. Google Maps Entfernungsmatrix API-Header
- 8. AngularUI - Google Maps - Marker entfernen
- 9. Google Maps Autocomplete Variablen Problem
- 10. Google Maps von Razor
- 11. Google Maps API Fehler: RefererNotAllowedMapError
- 12. Android Google maps api vs JavaScript Google maps api
- 13. Google Maps-API-Fehler: Google Maps API-Fehler: RefererNotAllowedMapError
- 14. Google Maps API directionsService.route unterscheidet sich von Google Maps Wegbeschreibung
- 15. Google Maps: Wie man mehrere Markierungen zu Google Maps hinzufügt
- 16. Google Maps API im Vergleich zu Google Maps Engine?
- 17. Google Maps Fehler: Google Maps API Fehler: MissingKeyMapError
- 18. RangeError, Google Maps Wegbeschreibungen Dienst. angular2, SebastianM/angular2-google-maps
- 19. Google Maps Distance Matrix Sprachspezifikation für Google Maps JavaScript API
- 20. Google Maps Wird nicht Medien auf Phonegap
- 21. Google Cloud-Speicher, Cache-Control
- 22. react-native-maps Unterstützung offline google maps
- 23. Google Maps Verkehr vs Bing Maps Verkehr
- 24. Google Maps - Vollbild auf Änderungsereignis?
- 25. Google Maps Mehrere Kreise
- 26. Places Suchfeld | Google Maps
- 27. Google Maps API RefererNotAllowedError
- 28. Google Maps Infowindow Position
- 29. Shadow google maps marker
- 30. Xcode Google Maps Suchleiste
Warum wollen Sie Pfeil hinzufügen? –
Ich möchte die Markierrichtung anzeigen (wenn die Markierung auf dem rechten Pfeil ist, wird sie nach rechts zeigen) –
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. –