Cambiar la posición del botón "Mi ubicación" de la API de Google Maps

84

Estoy usando la API de Android de Google Maps v2 y necesito una forma de cambiar la posición del botón "Mi ubicación".

Aparece el botón "Mi ubicación" así:

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

// This gets the button
map.setMyLocationEnabled(true);
Jakob
fuente
2
AFAIK, no lo haces. Ajusta su diseño de manera que el anuncio no se superponga al mapa.
CommonsWare
5
¿Ha mirado el método setPadding () de GoogleMap? Ver: developers.google.com/maps/documentation/android/…
IgorGanapolsky

Respuestas:

70

Simplemente use GoogleMap.setPadding (izquierda, arriba, derecha, abajo), que le permite indicar partes del mapa que pueden estar oscurecidas por otras vistas. La configuración del relleno reposiciona los controles de mapa estándar y las actualizaciones de la cámara utilizarán la región rellenada.

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

Ascot Harris
fuente
6
Esta es la mejor respuesta. findById (1) es una solución terrible
pablobaldez
La respuesta más clara y con las mejores prácticas. Quiéralo.
josefdlange
3
Funciona bien para colocar el botón mylocation en la esquina inferior derecha, pero como dices, estropea las actualizaciones de la cámara. ¿Cómo solucionar eso? A partir de ahora, mi cámara siempre ve la parte inferior de la pantalla como el centro. ¿Agrega la mitad de la altura de la pantalla a la cámara cuando calcula cosas?
riper
4
Prefiero el mapView.findViewWithTag ("GoogleMapMyLocationButton"); solución a continuación.
ayvazj
3
Tenga en cuenta que setPaddingtiene muchos otros efectos secundarios que pueden no ser deseados. Lo más importante es que cambia la posición de la pantalla del objetivo de la cámara.
zyamys
87

Puede obtener el botón "Mi ubicación" y moverlo, como:

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
fuente
4
Hola @fabLouis, En primer lugar, quería agradecerte. Su código movió el LocationButton. Solo tengo curiosidad por saber cómo averiguaste la identificación de ese botón. ¿Puedes explicar más sobre esto mapView.findViewById(1).getParent()).findViewById(2);? Gracias de nuevo, SH
Swan
4
a través del depurador de Android Studio
fabLouis
1
Si hace esto, Android Studio dirá "recurso esperado de tipo id"
inmyth
11
@inmyth Incluso obtuve el mismo error, pero analicé 1 y 2 usando la clase Integer. findViewById (Integer.parseInt ("1")). Si ha encontrado una mejor solución, hágamelo saber.
Harsha
2
hmm ¿cómo es la parte inferior derecha RelativeLayout.ALIGN_PARENT_TOPe RelativeLayout.ALIGN_PARENT_BOTTOMigual?
user2968401
15

Puede que esta no sea la mejor solución, pero puede colocar su propio botón sobre el mapa y manejarlo usted mismo. Se necesitaría lo siguiente: -

1) Coloque el mapa en un frameLayout y agregue su botón en la parte superior. P.ej

<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) Edite la configuración de la interfaz de usuario de mapas para que el botón no aparezca cuando llame a setMyLocationEnabled (true). Puede hacerlo a través de map.getUiSettings (). setMyLocationButtonEnabled (falso);

3) Maneje el clic de su nuevo botón para emular lo que hace el botón proporcionado. Por ejemplo, llamar a mMap.setMyLocationEnabled (...); y desplaza el mapa hasta la ubicación actual.

Espero que eso ayude, o espero que alguien venga con una solución más simple para ti ;-)

Ryan
fuente
Por cierto, por lo que vale, estoy de acuerdo con CommonsWare, ¡no cubrir el mapa con un anuncio sería lo mejor!
Ryan
14

Ya se explicó anteriormente, solo una pequeña adición a la respuesta de fabLouis. También puede obtener su vista de mapa desde 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
fuente
3
Esta línea - ((Ver) mapView.findViewById (1) .getParent ()). FindViewById (2); me estaba dando un error: "Recurso esperado de tipo ID" en el entero 1 y 2, luego lo resolví así ((Ver) mapView.findViewById (Integer.parseInt ("1")). getParent ()). findViewById (Integer .parseInt ("2"));
Zohab Ali
14

No me gusta ver estos identificadores de vista mágica que otros están usando, sugiero usar etiquetas para encontrar MapViews niños.

Aquí está mi solución para colocar el botón Mi ubicación encima de los controles de zoom .

// 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
fuente
3
Para cualquiera que se pregunte cómo hacer lo mismo con la brújula, la etiqueta es GoogleMapCompass.
zyamys
1
Hola Cordón, no sé si recuerdas cómo hacer esto, pero ¿recuerdas dónde encontraste la lista de etiquetas de mapview? Estoy buscando mover otras cosas y realmente no me gustan los otros patrones que la gente está usando.
Randy
2
@Randy Itere las subvistas de MapView (FrameLayout) y registre las etiquetas para obtenerlas. Ver aquí (Escrito en Kotlin)
ElegyD
@ElegyD ¡¡Gracias !!
Randy
12

Resolví este problema en el fragmento de mi mapa volviendo a colocar el botón de ubicación en la esquina inferior derecha de la vista usando el código a continuación, aquí está mi Actividad de mapas.java: -

agregue estas líneas de código en el método onCreate (),

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

y aquí está el código 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);
            }

        }

Espero que esto resuelva tu problema. Gracias.

Priya Jagtap
fuente
Gracias funcionó para mí. Intenté solo con ALIGN_PARENT_BOTTOM pero no funcionó para mí. ¿cómo está funcionando esto?
Sharath Weaver
necesita emitir (ver) como mapView = (Ver) mapFragment.getView ();
Md Shihab Uddin
9

Primero, obtenga Google Map View:

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

Luego busque el botón MyLocation (ID del depurador de Android Studio):

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

Finalmente, simplemente configure nuevos parámetros RelativeLayout para el botón MyLocation (alinee el padre derecho + centro verticalmente en este caso):

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

¡Auge! Ahora puedes moverlo como quieras;)

romano
fuente
3
Esta línea - ((Ver) mapView.findViewById (1) .getParent ()). FindViewById (2); me está dando un error - "Recurso esperado de tipo ID" en enteros 1 y 2.
zookastos
3
Pruebe esto - Ver btnMyLocation = ((Ver) mapView.findViewById (Integer.parseInt ("1")). GetParent ()). FindViewById (Integer.parseInt ("2"));
Silambarasan Poonguti
@Nalin Hay una opción si Alt-Enter en el error para deshabilitar la verificación (por ejemplo, para el método).
Richard Le Mesurier
8

Vea el método a continuación. Vive dentro de una clase que extiende SupportMapFragment. Obtiene la vista de contenedor para el botón y la muestra en la parte inferior, centrada horizontalmente.

/**
     * 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
fuente
me está dando java.lang.ClassCastException: maps.af.q no se puede convertir en android.view.ViewGroup
Nayanesh Gupte
8

Si solo desea tener habilitada la indicación de ubicación (el punto azul) pero no necesita el botón predeterminado Mi ubicación:

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

De esta forma también puedes dibujar tu propio botón donde quieras sin cosas extrañas como esta mapView.findViewById(1).getParent()).

fraggjkee
fuente
Muchas gracias
Nacho Zullo
2

Yo tuve el mismo problema. Terminé usando el Visor de jerarquía para identificar la vista utilizada para mostrar el botón y lo manipulé. Muy hacky, lo sé, pero no pude encontrar una manera diferente.

oviroa
fuente
1
¿Podría compartir su solución por favor?
clauziere
2

Fue un poco difícil conseguir que esto funcionara. Pero lo hice, y en el proceso también comencé a mover los botones de zoom. Aquí mi código completo:

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
fuente
2

Una forma de lidiar con este problema. Eliminar el botón predeterminado y crear el suyo propio. En la declaración OnCreate agregue lo siguiente:

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
fuente
2

prueba este código

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
fuente
2

Este botón se movió al lado izquierdo del mapaAntes, podía eliminar la antigua regla del botón:

@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
fuente
0

Puede utilizar el siguiente enfoque:

    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
fuente
¿cómo supo que ((Ver) getView (). findViewById (1) .getParent ()); obtendría la vista de ubicación?
reidisaki
Hay muchas cosas excelentes en el depurador de Android Studio;)
Roman
0

Agregué una línea a mi fragmento de android: layout_marginTop = "? Attr / actionBarSize" Me ayudó

Oleg
fuente
0

use este para la ubicación inferior derecha

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