Alterar a posição do botão “Meu local” da API do Google Maps

84

Estou usando a API Android do Google Maps v2 e preciso encontrar uma maneira de alterar a posição do botão "Meu local".

Eu recebo o botão "Meu local" assim:

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

// This gets the button
map.setMyLocationEnabled(true);
Jakob
fonte
2
AFAIK, você não. Você ajusta seu layout de forma que o anúncio não se sobreponha ao mapa.
CommonsWare
5
Você já olhou para o método setPadding () do GoogleMap? Consulte: developers.google.com/maps/documentation/android/…
IgorGanapolsky

Respostas:

70

Basta usar GoogleMap.setPadding (left, top, right, bottom), o que permite indicar partes do mapa que podem ser obscurecidas por outras visualizações. Definir o preenchimento reposiciona os controles de mapa padrão e as atualizações da câmera usarão a região preenchida.

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

Ascot Harris
fonte
6
Esta é a melhor resposta. findById (1) é uma solução terrível
pablobaldez
A resposta mais clara e prática recomendada. Adoro.
josefdlange
3
Funciona bem para colocar o botão mylocation no canto inferior direito, mas como você diz, atrapalha as atualizações da câmera. Como resolver isso? A partir de agora, minha câmera sempre vê a parte inferior da tela como o centro. Você adiciona metade da altura da tela à câmera ao calcular as coisas?
riper
4
Eu prefiro o mapView.findViewWithTag ("GoogleMapMyLocationButton"); solução abaixo.
ayvazj
3
Observe que setPaddingtem muitos outros efeitos colaterais que podem ser indesejados. Mais importante ainda, ele muda a posição da tela do alvo da câmera.
zyamys
87

Você pode obter o botão "Meu local" e movê-lo, 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
fonte
4
Olá @fabLouis, Antes de mais nada, queria agradecer. Seu código moveu o LocationButton. Estou apenas curioso para saber como você descobriu a ID desse botão? Você pode explicar mais sobre isso mapView.findViewById(1).getParent()).findViewById(2);. Obrigado novamente, SH
Swan
4
através do depurador Android Studio
fabLouis
1
se você fizer isso, o Android Studio dirá "recurso esperado do tipo id"
início de
11
@inmyth Mesmo tendo o mesmo erro, mas analisei 1 e 2 usando a classe Integer. findViewById (Integer.parseInt ("1")). Se você encontrou a melhor solução, me avise.
Harsha
2
hmm como é RelativeLayout.ALIGN_PARENT_TOPe RelativeLayout.ALIGN_PARENT_BOTTOMigual inferior direito?
user2968401
15

Esta pode não ser a melhor solução, mas você pode colocar seu próprio botão sobre o mapa e lidar com ele sozinho. Seria necessário o seguinte: -

1) Coloque o mapa em um frameLayout e adicione seu botão no topo. Por exemplo

<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 as configurações de IU dos mapas para que o botão não apareça quando você chamar setMyLocationEnabled (true). Você pode fazer isso por meio de map.getUiSettings (). setMyLocationButtonEnabled (false);

3) Controle o clique de seu novo botão para emular o que o botão fornecido faz. Por exemplo, chame mMap.setMyLocationEnabled (...); e desloque o mapa para a localização atual.

Espero que ajude, ou espero que alguém venha em breve com uma solução mais simples para você ;-)

Ryan
fonte
BTW pelo que vale a pena eu concordo com CommonsWare, não cobrir o mapa com um anúncio seria o melhor!
Ryan
14

Já foi explicado acima. Apenas um pequeno acréscimo à resposta de fabLouis. Você também pode obter a visualização do mapa no 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
fonte
3
Esta linha - ((View) mapView.findViewById (1) .getParent ()). FindViewById (2); estava me dando um erro - "Esperado recurso do tipo ID" em 1 e 2 inteiros, então resolvi assim ((View) mapView.findViewById (Integer.parseInt ("1")). getParent ()). findViewById (Integer .parseInt ("2"));
Zohab Ali
14

Eu não gosto de ver esses IDs de view mágicos que outras pessoas estão usando, sugiro usar tags para encontrar os MapViewfilhos.

Aqui está minha solução para colocar o botão Meu local acima dos 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
fonte
3
Para quem está se perguntando como fazer o mesmo com a bússola, a etiqueta é GoogleMapCompass.
zyamys
1
Ei Cord, não sei se você se lembra de como fazer isso, mas você se lembra onde encontrou a lista de tags do mapview? Estou tentando mover algumas outras coisas e realmente não gosto dos outros padrões que as pessoas estão usando.
Randy
2
@Randy Iterar pelas subvisualizações do MapView (FrameLayout) e registrar as tags para obtê-las. Veja aqui (Escrito em Kotlin)
ElegyD
@ElegyD Obrigado !!
Randy
12

Resolvi esse problema em meu fragmento de mapa reposicionando meu botão de localização no canto inferior direito da visualização usando o código abaixo, aqui está meu Maps Activity.java: -

adicione essas linhas de código no método onCreate (),

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

e aqui está o 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 isto resolva o seu problema. Obrigado.

Priya Jagtap
fonte
Obrigado funcionou para mim. Eu estava tentando apenas com ALIGN_PARENT_BOTTOM, mas não funcionou para mim. como isso está funcionando?
Sharath Weaver
você precisa lançar (visualizar) como mapView = (View) mapFragment.getView ();
Md Shihab Uddin
9

Primeiro, obtenha o Google Map View:

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

Em seguida, encontre o botão MyLocation (id's do depurador Android Studio):

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

Finalmente, basta definir os novos parâmetros RelativeLayout para o botão MyLocation (alinhe o pai direita + centro verticalmente neste 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);

Estrondo! Agora você pode movê-lo como quiser;)

romano
fonte
3
Esta linha - ((View) mapView.findViewById (1) .getParent ()). FindViewById (2); está me dando um erro - "recurso esperado do tipo ID" em 1 e 2 inteiros.
zookastos
3
Tente isto - Exibir btnMyLocation = ((View) mapView.findViewById (Integer.parseInt ("1")). GetParent ()). FindViewById (Integer.parseInt ("2"));
Silambarasan Poonguti
@Nalin Existe uma opção se você Alt-Enter no erro para desativar a verificação (por exemplo, para o método).
Richard Le Mesurier
8

Veja o método abaixo. Ele reside dentro de uma classe que estende SupportMapFragment. Ele obtém a visualização do contêiner para o botão e a exibe na parte inferior, centralizada 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
fonte
ele está me fornecendo java.lang.ClassCastException: maps.af.q não pode ser transmitido para android.view.ViewGroup
Nayanesh Gupte
8

Se você deseja apenas ter a indicação de local habilitada (o ponto azul), mas não precisa do botão Meu local padrão:

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

Dessa forma, você também pode desenhar seu próprio botão onde quiser, sem coisas estranhas como essa mapView.findViewById(1).getParent()).

Fraggjkee
fonte
Muito obrigado
Nacho Zullo
2

Eu tive o mesmo problema. Acabei usando o Hierarchy Viewer para identificar a visualização usada para exibir o botão e manipulá-lo. Muito hacky, eu sei, mas não consegui descobrir uma maneira diferente.

Oviroa
fonte
1
Você poderia compartilhar sua solução, por favor.
clauziere de
2

Foi um pouco difícil fazer isso funcionar. Mas eu fiz isso e, no processo, também comecei a mover os botões de zoom. Aqui está meu 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
fonte
2

Uma maneira de lidar com esse problema. Exclua o botão padrão e crie o seu próprio. Na instrução OnCreate, adicione o seguinte:

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

tente 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
fonte
2

Este botão foi movido para o lado esquerdo do mapaAntes, você poderia remover a regra antiga do botão:

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

Você pode usar a seguinte abordagem:

    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
fonte
como você sabia que ((View) getView (). findViewById (1) .getParent ()); obteria a visualização do local?
reidisaki
Há muitas coisas boas no depurador do Android Studio;)
Roman
0

Eu adicionei uma linha ao meu fragmento android: layout_marginTop = "? Attr / actionBarSize" Isso me ajudou

Oleg
fonte
0

use este para localização inferior direita

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