Ändern Sie die Position der Schaltfläche "Mein Standort" der Google Maps-API

84

Ich verwende die Google Maps Android API v2 und brauche eine Möglichkeit, die Position der Schaltfläche "Mein Standort" zu bestimmen.

Ich erhalte die Schaltfläche "Mein Standort" wie folgt:

GooglePlayServicesUtil.isGooglePlayServicesAvailable(getApplicationContext());
final GoogleMap map = ((SupportMapFragment) getSupportFragmentManager()
        .findFragmentById(R.id.map)).getMap();

// This gets the button
map.setMyLocationEnabled(true);
Jakob
quelle
2
AFAIK, das tust du nicht. Sie passen Ihr Layout so an, dass die Anzeige die Karte nicht überlappt.
CommonsWare
5
Haben Sie sich die setPadding () -Methode von GoogleMap angesehen? Siehe: developer.google.com/maps/documentation/android/…
IgorGanapolsky

Antworten:

70

Verwenden Sie einfach GoogleMap.setPadding (links, oben, rechts, unten), mit dem Sie Teile der Karte angeben können, die möglicherweise von anderen Ansichten verdeckt werden. Durch das Einstellen der Auffüllung werden die Standardkartensteuerelemente neu positioniert, und bei Kameraaktualisierungen wird der aufgefüllte Bereich verwendet.

https://developers.google.com/maps/documentation/android/map#map_padding

Ascot Harris
quelle
6
Dies ist die beste Antwort. findById (1) ist eine schreckliche Lösung
pablobaldez
Die absolut klarste und bewährte Antwort. Liebe es.
Josefdlange
3
Funktioniert gut, um die Mylocation-Schaltfläche in der unteren rechten Ecke zu platzieren, aber wie Sie sagen, bringt sie Kamera-Updates durcheinander. Wie kann man das lösen? Ab sofort sieht meine Kamera immer den unteren Bildschirmrand als Mitte. Fügen Sie der Kamera die halbe Bildschirmhöhe hinzu, wenn Sie Dinge berechnen?
Riper
4
Ich bevorzuge das mapView.findViewWithTag ("GoogleMapMyLocationButton"); Lösung unten.
Ayvazj
3
Beachten Sie, dass setPaddinges viele andere Nebenwirkungen gibt, die unerwünscht sein können. Am wichtigsten ist, dass die Bildschirmposition des Kameraziels geändert wird.
Zyamys
87

Sie können die Schaltfläche "Mein Standort" abrufen und wie folgt verschieben:

public class MapFragment extends SupportMapFragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View mapView = super.onCreateView(inflater, container, savedInstanceState);   

    // Get the button view 
    View locationButton = ((View) mapView.findViewById(1).getParent()).findViewById(2);

    // and next place it, for exemple, on bottom right (as Google Maps app)
    RelativeLayout.LayoutParams rlp = (RelativeLayout.LayoutParams) locationButton.getLayoutParams();
    // position on right bottom
    rlp.addRule(RelativeLayout.ALIGN_PARENT_TOP, 0);
    rlp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);
    rlp.setMargins(0, 0, 30, 30);
    }
}
fabLouis
quelle
4
Hallo @fabLouis, zunächst wollte ich mich bei dir bedanken. Ihr Code hat den LocationButton verschoben. Ich bin nur neugierig, wie Sie die ID dieses Buttons herausgefunden haben. Können Sie mehr darüber erklären mapView.findViewById(1).getParent()).findViewById(2);.
Swan
4
über den Android Studio Debugger
fabLouis
1
Wenn Sie dies tun, sagt Android Studio "erwartete Ressource vom Typ id"
inmyth
11
@inmyth Auch ich habe den gleichen Fehler bekommen, aber ich habe 1 und 2 mit der Integer-Klasse analysiert. findViewById (Integer.parseInt ("1")). Wenn Sie eine bessere Lösung gefunden haben, lassen Sie es mich wissen.
Harsha
2
hmm wie geht es RelativeLayout.ALIGN_PARENT_TOPund RelativeLayout.ALIGN_PARENT_BOTTOMgleich unten rechts?
user2968401
15

Dies ist möglicherweise nicht die beste Lösung, aber Sie können Ihre eigene Schaltfläche über der Karte platzieren und selbst damit umgehen. Es würde Folgendes dauern: -

1) Legen Sie die Karte in ein FrameLayout und fügen Sie Ihre Schaltfläche oben hinzu. Z.B

<FrameLayout
    android:id="@+id/mapFrame"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >



    <fragment
        xmlns:map="http://schemas.android.com/apk/res-auto"
        android:id="@+id/mapFragment"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        class="com.google.android.gms.maps.MapFragment"
        map:mapType="normal"
        map:uiCompass="true" />

    <ImageButton
        android:id="@+id/myMapLocationButton"
        android:layout_width="36dp"
        android:layout_height="36dp"
        android:layout_gravity="bottom|right"
        android:background="@drawable/myMapLocationDrawable"
        android:contentDescription="My Location" />

</FrameLayout>

2) Bearbeiten Sie die Einstellungen der Karten-Benutzeroberfläche so, dass die Schaltfläche nicht angezeigt wird, wenn Sie setMyLocationEnabled (true) aufrufen. Sie können dies über map.getUiSettings () tun. setMyLocationButtonEnabled (false);

3) Behandeln Sie den Klick Ihrer neuen Schaltfläche, um zu emulieren, was die mitgelieferte Schaltfläche bewirkt. Rufen Sie beispielsweise mMap.setMyLocationEnabled (...) auf; und schwenken Sie die Karte zum aktuellen Standort.

Hoffe das hilft, oder hoffe jemand kommt lange mit einer einfacheren Lösung für dich ;-)

Ryan
quelle
Übrigens für das, was es wert ist Ich stimme CommonsWare zu, bedecke die Karte nicht mit einer Werbung wäre am besten!
Ryan
14

Es wurde bereits oben erklärt. Nur eine kleine Ergänzung zu fabLouis 'Antwort. Sie können Ihre Kartenansicht auch über das SupportMapFragment abrufen.

        /**
         * Move the button
         */
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().
                findFragmentById(R.id.map);
        View mapView = mapFragment.getView();
        if (mapView != null &&
                mapView.findViewById(1) != null) {
            // Get the button view
            View locationButton = ((View) mapView.findViewById(1).getParent()).findViewById(2);
            // and next place it, on bottom right (as Google Maps app)
            RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams)
                    locationButton.getLayoutParams();
            // position on right bottom
            layoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP, 0);
            layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);
            layoutParams.setMargins(0, 0, 30, 30);
        }
Sahil Jain
quelle
3
Diese Zeile - ((View) mapView.findViewById (1) .getParent ()). FindViewById (2); gab mir einen Fehler - "Erwartete Ressource vom Typ ID" für 1 und 2 Ganzzahl, dann löste ich es wie folgt auf ((View) mapView.findViewById (Integer.parseInt ("1")). getParent ()). findViewById (Integer .parseInt ("2"));
Zohab Ali
14

Ich habe keine Lust, diese magischen Ansichts-IDs zu sehen, die andere verwenden. Ich schlage vor, Tags zu verwenden, um MapViews Kinder zu finden .

Hier ist meine Lösung zum Platzieren der Schaltfläche " Mein Standort" über den Zoom- Steuerelementen.

// Get map views
View location_button =_mapView.findViewWithTag("GoogleMapMyLocationButton");
View zoom_in_button = _mapView.findViewWithTag("GoogleMapZoomInButton");
View zoom_layout = (View) zoom_in_button.getParent();

// adjust location button layout params above the zoom layout
RelativeLayout.LayoutParams location_layout = (RelativeLayout.LayoutParams) location_button.getLayoutParams();
location_layout.addRule(RelativeLayout.ALIGN_PARENT_TOP, 0);
location_layout.addRule(RelativeLayout.ABOVE, zoom_layout.getId());
Cord Rehn
quelle
3
Für alle, die sich fragen, wie sie dasselbe für den Kompass tun sollen, ist das Etikett GoogleMapCompass.
Zyamys
1
Hey Cord, ich weiß nicht, ob Sie sich daran erinnern, wie das geht, aber erinnern Sie sich, wo Sie die Liste der Mapview-Tags gefunden haben? Ich möchte ein paar andere Dinge bewegen und mag die anderen Muster, die die Leute verwenden, wirklich nicht.
Randy
2
@Randy Durchlaufen Sie die Unteransichten von MapView (FrameLayout) und protokollieren Sie die Tags, um sie abzurufen. Siehe hier (geschrieben in Kotlin)
ElegyD
@ElegyD Danke !!
Randy
12

Ich habe dieses Problem in meinem Kartenfragment gelöst, indem ich meine Standortschaltfläche mithilfe des folgenden Codes in der rechten unteren Ecke der Ansicht neu positioniert habe. Hier ist meine Maps Activity.java: -

Fügen Sie diese Codezeilen in die onCreate () -Methode ein.

 SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        mapView = mapFragment.getView();
        mapFragment.getMapAsync(this);

und hier ist onMapReady () Code: -

@Override
        public void onMapReady(GoogleMap googleMap) {
            mMap = googleMap;
            mMap.setMyLocationEnabled(true);

            // Add a marker in Sydney and move the camera
            LatLng sydney = new LatLng(-34, 151);
            mMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney"));
            mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney));

            if (mapView != null &&
                    mapView.findViewById(Integer.parseInt("1")) != null) {
                // Get the button view
                View locationButton = ((View) mapView.findViewById(Integer.parseInt("1")).getParent()).findViewById(Integer.parseInt("2"));
                // and next place it, on bottom right (as Google Maps app)
                RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams)
                        locationButton.getLayoutParams();
                // position on right bottom
                layoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP, 0);
                layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);
                layoutParams.setMargins(0, 0, 30, 30);
            }

        }

Ich hoffe, das wird Ihr Problem lösen. Vielen Dank.

Priya Jagtap
quelle
Danke hat für mich funktioniert. Ich habe es nur mit ALIGN_PARENT_BOTTOM versucht, aber nicht für mich gearbeitet. Wie funktioniert das?
Sharath Weaver
Sie müssen wie viewView = (View) mapFragment.getView () umwandeln (anzeigen);
Md Shihab Uddin
9

Erhalten Sie zunächst die Google Map View:

 View mapView = ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getView();

Suchen Sie dann die Schaltfläche "MyLocation" (IDs aus dem Android Studio-Debugger):

 View btnMyLocation = ((View) mapView.findViewById(1).getParent()).findViewById(2);

Zum Schluss legen Sie einfach neue RelativeLayout-Parameter für die MyLocation-Schaltfläche fest (richten Sie in diesem Fall das übergeordnete Recht + die Mitte vertikal aus):

RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(80,80); // size of button in dp
    params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, RelativeLayout.TRUE);
    params.addRule(RelativeLayout.CENTER_VERTICAL, RelativeLayout.TRUE);
    params.setMargins(0, 0, 20, 0);
    btnMyLocation.setLayoutParams(params);

Boom! Jetzt kannst du es bewegen wie du willst;)

römisch
quelle
3
Diese Zeile - ((View) mapView.findViewById (1) .getParent ()). FindViewById (2); gibt mir einen Fehler - "Erwartete Ressource vom Typ ID" auf 1 und 2 Ganzzahl.
Zookastos
3
Versuchen Sie dies - View btnMyLocation = ((View) mapView.findViewById (Integer.parseInt ("1")). GetParent ()). FindViewById (Integer.parseInt ("2"));
Silambarasan Poonguti
@Nalin Wenn Sie den Fehler bei gedrückter Alt-Taste drücken, können Sie die Prüfung deaktivieren (z. B. für die Methode).
Richard Le Mesurier
8

Siehe die Methode unten. Es befindet sich in einer Klasse, die SupportMapFragment erweitert. Es zeigt die Containeransicht für die Schaltfläche an und zeigt sie unten horizontal zentriert an.

/**
     * Move my position button at the bottom of map
     */
    private void resetMyPositionButton()
    {
        //deep paths for map controls
        ViewGroup v1 = (ViewGroup)this.getView();
        ViewGroup v2 = (ViewGroup)v1.getChildAt(0);
        ViewGroup v3 = (ViewGroup)v2.getChildAt(0);
        ViewGroup v4 = (ViewGroup)v3.getChildAt(1);

        //my position button
        View position =  (View)v4.getChildAt(0);

        int positionWidth = position.getLayoutParams().width;
        int positionHeight = position.getLayoutParams().height;

        //lay out position button
        RelativeLayout.LayoutParams positionParams = new RelativeLayout.LayoutParams(positionWidth,positionHeight);
        int margin = positionWidth/5;
        positionParams.setMargins(0, 0, 0, margin);
        positionParams.addRule(RelativeLayout.CENTER_HORIZONTAL, RelativeLayout.TRUE);
        positionParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);
        position.setLayoutParams(positionParams);
    }
Oviroa
quelle
es gibt mir java.lang.ClassCastException: maps.af.q kann nicht in android.view.ViewGroup
Nayanesh Gupte
7

Wenn Sie nur die Standortanzeige aktivieren möchten (der blaue Punkt), aber nicht die Standardschaltfläche Mein Standort benötigen:

mGoogleMap.setMyLocationEnabled(true);
mGoogleMap.getUiSettings().setMyLocationButtonEnabled(false);

Auf diese Weise können Sie auch Ihren eigenen Knopf zeichnen, wo Sie möchten, ohne solche seltsamen Dinge mapView.findViewById(1).getParent()).

fraggjkee
quelle
2

Ich hatte das gleiche Problem. Am Ende habe ich den Hierarchie-Viewer verwendet, um die Ansicht zu identifizieren, in der die Schaltfläche angezeigt und bearbeitet wurde. Sehr hackig, ich weiß, konnte aber keinen anderen Weg finden.

Oviroa
quelle
1
Könnten Sie bitte Ihre Lösung teilen.
Clauziere
2

Es war ein bisschen schwierig, dies zum Laufen zu bringen. Aber ich habe es geschafft und dabei auch angefangen, die Zoomtasten zu bewegen. Hier mein vollständiger Code:

package com.squirrel.hkairpollution;

import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;

import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.UiSettings;
import com.google.android.gms.maps.model.LatLng;

public class MySupportMapFragment extends SupportMapFragment {

private static final String TAG = HKAirPollution.TAG;

public MySupportMapFragment() {
    return;
}

@Override
public View onCreateView(LayoutInflater arg0, ViewGroup arg1, Bundle arg2) {
    Log.v(TAG, "In overridden onCreateView.");
    View v = super.onCreateView(arg0, arg1, arg2);
    Log.v(TAG, "Initialising map.");
    initMap();
    return v;
}

@Override
 public void onViewCreated (View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    resetButtons();
}

private void initMap(){
    UiSettings settings = getMap().getUiSettings();
    settings.setAllGesturesEnabled(true);
    settings.setMyLocationButtonEnabled(true);
    LatLng latLong = new LatLng(22.320542, 114.185715);
    getMap().moveCamera(CameraUpdateFactory.newLatLngZoom(latLong,11));
}


/**
 * Move my position button at the bottom of map
 */
private void resetButtons()
{
    // Get a reference to the zoom buttons and the position button.
    ViewGroup v1 = (ViewGroup)this.getView();
    ViewGroup v2 = (ViewGroup)v1.getChildAt(0);
    ViewGroup v3 = (ViewGroup)v2.getChildAt(0);
    ViewGroup v4 = (ViewGroup)v3.getChildAt(1);

    // The My Position button
    View position =  (View)v4.getChildAt(0);
    int positionWidth = position.getLayoutParams().width;
    int positionHeight = position.getLayoutParams().height;

    // Lay out the My Position button.
    RelativeLayout.LayoutParams positionParams = new RelativeLayout.LayoutParams(positionWidth,positionHeight);
    int margin = positionWidth/5;
    positionParams.setMargins(0, 0, 0, margin);
    positionParams.addRule(RelativeLayout.CENTER_HORIZONTAL, RelativeLayout.TRUE);
    positionParams.addRule(RelativeLayout.ALIGN_PARENT_TOP, RelativeLayout.TRUE);
    position.setLayoutParams(positionParams);

    // The Zoom buttons
    View zoom = (View)v4.getChildAt(2);
    int zoomWidth = zoom.getLayoutParams().width;
    int zoomHeight = zoom.getLayoutParams().height;

    // Lay out the Zoom buttons.
    RelativeLayout.LayoutParams zoomParams = new RelativeLayout.LayoutParams(zoomWidth, zoomHeight);
    zoomParams.setMargins(0, 0, 0, margin);
    zoomParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, RelativeLayout.TRUE);
    zoomParams.addRule(RelativeLayout.ALIGN_PARENT_TOP, RelativeLayout.TRUE);
    zoom.setLayoutParams(zoomParams);
} 
}
Wouter
quelle
2

Ein Weg, um mit diesem Problem umzugehen. Löschen Sie die Standardschaltfläche und erstellen Sie Ihre eigene. Fügen Sie in der OnCreate-Anweisung Folgendes hinzu:

GoogleMap mMap = ((MapView) inflatedView.findViewById(R.id.mapview)).getMap();
LocationManager locationManager =    
(LocationManager)getActivity().getSystemService(Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
String provider = locationManager.getBestProvider(criteria, false);
Location location = locationManager.getLastKnownLocation(provider);
locationManager.requestLocationUpdates(provider, 2000, 1,  this);

mMap.setMyLocationEnabled(true);
mMap.getUiSettings().setMyLocationButtonEnabled(false); // delete default button

Imagebutton imgbtn = (ImageButton) view.findViewById(R.id.imgbutton); //your button
imgbtn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new    
LatLng(location.getLatitude(),     
location.getLongitude()), 15));
        }
    });
Daryn
quelle
2

Versuchen Sie diesen Code

private void resetMyPositionButton()
{
    Fragment fragment = ( (SupportMapFragment) getSupportFragmentManager().findFragmentById( R.id.map ) );
    ViewGroup v1 = (ViewGroup) fragment.getView();
    ViewGroup v2 = (ViewGroup)v1.getChildAt(0);
    ViewGroup v3 = (ViewGroup)v2.getChildAt(2);
    View position =  (View)v3.getChildAt(0);
    int positionWidth = position.getLayoutParams().width;
    int positionHeight = position.getLayoutParams().height;

    //lay out position button
    RelativeLayout.LayoutParams positionParams = new RelativeLayout.LayoutParams(positionWidth,positionHeight);
    int margin = positionWidth/5;
    positionParams.setMargins(margin, 0, 0, margin);
    positionParams.addRule(RelativeLayout.CENTER_VERTICAL, RelativeLayout.TRUE);
    positionParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT, RelativeLayout.TRUE);
    position.setLayoutParams(positionParams);
}
Metro Polinet
quelle
2

Diese Schaltfläche wurde auf die linke Seite der Karte verschobenZuvor konnten Sie die alte Regel der Schaltfläche entfernen:

@Override
public void onMapReady(final GoogleMap googleMap) {
    this.map = googleMap;
    // Show location button
    View locationButton = ((View) mapView.findViewById(Integer.parseInt("1")).getParent()).findViewById(Integer.parseInt("2"));
    RelativeLayout.LayoutParams rlp = (RelativeLayout.LayoutParams) locationButton.getLayoutParams();
    // position on right bottom
    Log.l(Arrays.toString(rlp.getRules()), L.getLogInfo());
    int[] ruleList = rlp.getRules();
    for (int i = 0; i < ruleList.length; i ++) {
        rlp.removeRule(i);
    }
    Log.l(Arrays.toString(rlp.getRules()), L.getLogInfo());
    //Do what you want to move this location button:
    rlp.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);
    rlp.addRule(RelativeLayout.ALIGN_PARENT_LEFT, RelativeLayout.TRUE);
}
nobjta_9x_tq
quelle
0

Sie können folgenden Ansatz verwenden:

    View myLocationParent = ((View) getView().findViewById(1).getParent());
    View myLocationParentParent = ((View) myLocationParent.getParent());

    // my position button

    int positionWidth = myLocationParent.getLayoutParams().width;
    int positionHeight = myLocationParent.getLayoutParams().height;

    // lay out position button
    FrameLayout.LayoutParams positionParams = new FrameLayout.LayoutParams(
            positionWidth, positionHeight);
    positionParams.setMargins(0, 100, 0, 0);

    myLocationParent.setLayoutParams(positionParams);
Nayanesh Gupte
quelle
Woher wusstest du, dass ((View) getView (). findViewById (1) .getParent ()); würde die Standortansicht bekommen?
Reidisaki
Es gibt eine Menge großartiger Dinge im Android Studio-Debugger;)
Roman
0

Ich habe meinem Fragment android eine Zeile hinzugefügt : layout_marginTop = "? Attr / actionBarSize" Es hat mir geholfen

Oleg
quelle
0

Verwenden Sie diese für die Position unten rechts

map.setMyLocationEnabled(true); 
map.setPadding(0,1600,0,0);
Muazziss ​​Najmi
quelle