Zmień położenie przycisku „Moja lokalizacja” interfejsu API Map Google

84

Korzystam z Google Maps Android API v2 i potrzebuję sposobu, aby określić położenie przycisku „Moja lokalizacja”.

Widzę przycisk „Moja lokalizacja” w ten sposób:

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

// This gets the button
map.setMyLocationEnabled(true);
Jakob
źródło
2
AFAIK, nie masz. Dostosowujesz układ tak, aby reklama nie zachodziła na mapę.
CommonsWare
5
Czy spojrzałeś na metodę setPadding () w GoogleMap? Zobacz: developers.google.com/maps/documentation/android/…
IgorGanapolsky

Odpowiedzi:

70

Po prostu użyj GoogleMap.setPadding (left, top, right, bottom), która pozwala wskazać części mapy, które mogą być zasłonięte przez inne widoki. Ustawienie dopełnienia powoduje zmianę pozycji standardowych elementów sterujących mapy, a aktualizacje kamer będą korzystać z wyściełanego regionu.

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

Ascot Harris
źródło
6
To najlepsza odpowiedź. findById (1) to straszne rozwiązanie
pablobaldez
Absolutnie najjaśniejsza i najlepsza odpowiedź. Kocham to.
josefdlange
3
Działa dobrze w przypadku umieszczenia przycisku mylokacji w prawym dolnym rogu, ale, jak mówisz, psuje aktualizacje kamery. Jak to rozwiązać? Od tej pory mój aparat zawsze widzi dół ekranu jako środek. Czy dodajesz połowę wysokości ekranu do aparatu podczas obliczania rzeczy?
bardziej zaawansowany
4
Wolę mapView.findViewWithTag ("GoogleMapMyLocationButton"); rozwiązanie poniżej.
ayvazj
3
Zauważ, że setPaddingma wiele innych skutków ubocznych, które mogą być niepożądane. Co najważniejsze, zmienia pozycję ekranu celu kamery.
zyamys
87

Możesz pobrać przycisk „Moja lokalizacja” i przenieść go, na przykład:

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
źródło
4
Cześć @fabLouis, Przede wszystkim chciałem ci podziękować. Twój kod spowodował przeniesienie LocationButton. Jestem po prostu ciekawy, jak odkryłeś identyfikator tego przycisku? Czy możesz wyjaśnić więcej na ten temat mapView.findViewById(1).getParent()).findViewById(2);. Jeszcze raz dziękuję, SH
Swan
4
przez debuger Android Studio
fabLouis
1
jeśli to zrobisz, Android Studio powie „oczekiwany zasób o identyfikatorze typu”
piątym
11
@inmyth Nawet mam ten sam błąd, ale przeanalizowałem 1 i 2 przy użyciu klasy Integer. findViewById (Integer.parseInt ("1")). Jeśli znalazłeś lepsze rozwiązanie, daj mi znać.
Harsha
2
hmm, jak się ma RelativeLayout.ALIGN_PARENT_TOPi RelativeLayout.ALIGN_PARENT_BOTTOMrówne prawy dolny?
user2968401
15

To może nie być najlepsze rozwiązanie, ale możesz umieścić własny przycisk nad mapą i sam sobie z tym poradzić. Wymagałoby to: -

1) Umieść mapę w frameLayout i dodaj swój przycisk na górze. Na przykład

<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) Edytuj ustawienia interfejsu map, aby przycisk nie pojawiał się po wywołaniu metody setMyLocationEnabled (true). Możesz to zrobić za pomocą map.getUiSettings (). setMyLocationButtonEnabled (false);

3) Obsługuj kliknięcie nowego przycisku, aby emulować działanie dostarczonego przycisku. Na przykład call mMap.setMyLocationEnabled (...); i przesuń mapę do bieżącej lokalizacji.

Mam nadzieję, że to pomoże, lub mam nadzieję, że ktoś przyjdzie z prostszym rozwiązaniem dla Ciebie ;-)

Ryan
źródło
A tak przy okazji, zgadzam się z CommonsWare, najlepiej nie zakrywać mapy reklamą!
Ryan
14

Zostało to już wyjaśnione powyżej, tylko mały dodatek do odpowiedzi fabLouis. Możesz również uzyskać widok mapy z SupportMapFragment.

        /**
         * 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
źródło
3
Ta linia - ((Zobacz) mapView.findViewById (1) .getParent ()). FindViewById (2); dawał mi błąd - „Oczekiwany zasób typu ID” na liczbach całkowitych 1 i 2, a następnie rozwiązałem to w ten sposób ((Zobacz) mapView.findViewById (Integer.parseInt ("1")). getParent ()). findViewById (Integer .parseInt ("2"));
Zohab Ali
14

Nie mam ochoty zobaczyć tych magicznych identyfikatorów widoków, których używają inni, sugeruję użycie tagów, aby znaleźć MapViewdzieci.

Oto moje rozwiązanie umożliwiające umieszczenie przycisku Moja lokalizacja nad elementami sterującymi powiększeniem .

// 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
źródło
3
Dla każdego, kto zastanawia się, jak zrobić to samo z kompasem, etykieta jest GoogleMapCompass.
zyamys
1
Hej, Cord, nie wiem, czy pamiętasz, jak to zrobić, ale czy pamiętasz, gdzie znalazłeś listę tagów mapview? Chcę poruszyć inne rzeczy i naprawdę nie lubię innych wzorców, których używają ludzie.
Randy
2
@Randy Iteruj przez podglądy widoku MapView (FrameLayout) i rejestruj znaczniki, aby je pobrać. Zobacz tutaj (napisane w Kotlinie)
ElegiaD
@ElegyD Dziękuję !!
Randy,
12

Rozwiązałem ten problem w moim fragmencie mapy, ponownie ustawiając przycisk lokalizacji w prawym dolnym rogu widoku za pomocą poniższego kodu, oto moja Maps Activity.java: -

dodaj te linie kodu w metodzie onCreate (),

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

a oto kod onMapReady (): -

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

        }

Mam nadzieję, że to rozwiąże Twój problem. Dzięki.

Priya Jagtap
źródło
Dzięki pracował dla mnie. Próbowałem tylko z ALIGN_PARENT_BOTTOM, ale nie zadziałało. jak to działa
Sharath Weaver
musisz rzucać (wyświetlać) jak mapView = (Wyświetl) mapFragment.getView ();
Md Shihab Uddin
9

Najpierw uzyskaj Google Map View:

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

Następnie znajdź przycisk MyLocation (id z debugera Android Studio):

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

Na koniec ustaw nowe parametry RelativeLayout dla przycisku MyLocation (w tym przypadku wyrównaj rodzica do prawej + do środka w pionie):

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

Bum! Teraz możesz go przesuwać, jak chcesz;)

rzymski
źródło
3
Ta linia - ((Zobacz) mapView.findViewById (1) .getParent ()). FindViewById (2); wyświetla mi błąd - „Oczekiwany zasób typu ID” na liczbach całkowitych 1 i 2.
zookastos
3
Spróbuj tego - Wyświetl btnMyLocation = ((Zobacz) mapView.findViewById (Integer.parseInt ("1")). GetParent ()). FindViewById (Integer.parseInt ("2"));
Silambarasan Poonguti
@Nalin Istnieje opcja, jeśli naciśniesz Alt-Enter na błędzie, aby wyłączyć sprawdzanie (np. Dla metody).
Richard Le Mesurier
8

Zobacz metodę poniżej. Znajduje się w klasie, która rozszerza SupportMapFragment. Pobiera widok kontenera dla przycisku i wyświetla go na dole, wyśrodkowany w poziomie.

/**
     * 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
źródło
daje mi java.lang.ClassCastException: maps.af.q nie można przesłać do android.view.ViewGroup
Nayanesh Gupte
8

Jeśli chcesz tylko włączyć wskazanie lokalizacji (niebieska kropka), ale nie potrzebujesz domyślnego przycisku Moja lokalizacja:

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

W ten sposób możesz także narysować swój własny przycisk, gdzie chcesz, bez dziwnych rzeczy, takich jak ten mapView.findViewById(1).getParent()).

fraggjkee
źródło
Dziękuję bardzo
Nacho Zullo
2

Miałem ten sam problem. Skończyło się na tym, że użyłem przeglądarki Hierarchy Viewer do zidentyfikowania widoku używanego do wyświetlenia przycisku i manipulowałem nim. Wiem, że to bardzo dziwaczne, ale nie mogłem znaleźć innego sposobu.

oviroa
źródło
1
Czy mógłbyś podzielić się swoim rozwiązaniem?
clauziere
2

To było trochę trudne, aby to zadziałało. Ale udało mi się to zrobić i jednocześnie zacząłem przesuwać przyciski zoomu. Oto mój pełny kod:

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
źródło
2

Jeden ze sposobów rozwiązania tego problemu. Usuń przycisk domyślny i utwórz własny. W instrukcji OnCreate dodaj następną:

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
źródło
2

wypróbuj ten kod

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
źródło
2

Ten przycisk został przeniesiony na lewą stronę mapyWcześniej można było usunąć starą regułę przycisku:

@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
źródło
0

Możesz zastosować następujące podejście:

    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
źródło
skąd wiesz, że ((View) getView (). findViewById (1) .getParent ()); otrzyma widok lokalizacji?
reidisaki
W debugerze Android Studio jest dużo świetnych rzeczy;)
Roman
0

Dodałem linię do mojego fragmentu android: layout_marginTop = "? Attr / actionBarSize" Pomogło mi

Oleg
źródło
0

użyj tego dla lokalizacji w prawym dolnym rogu

map.setMyLocationEnabled(true); 
map.setPadding(0,1600,0,0);
Muazziss ​​Najmi
źródło