Solucionado (ver solução)
Solucionado
(ver solução)
8
respostas

Implementar botão para criar marcador no mapa e exibir coordenadas em tempo real em uma TextView

Já fiz todas as etapas do curso, que é muito bom. Gostaria de implementar um botão para criar um marcador no mapa a medida que o usuário clica, pois estou criando um app para marcar pontos no mapa, porém ainda não consegui, quando tento buscar a coordenada o aplicativo dá erro e fecha. Dá o mesmo erro quando tento exibir as coordenadas que são coletadas aqui (public void onLocationChanged(Location location)) em uma TextView por exemplo. Desde já grato pela ajuda.

8 respostas

Olá!

Você pode postar aqui a exception que está sendo exibida quando você tenta buscar a coordenada?

Além disso, pode postar também o código das classes onde o erro está acontecendo pra gente tentar descobrir o problema.

Jeferson, obrigado por responder. Fiz da mesma forma do exemplo e funcionou muito bem até onde você ensinou no vídeo. Eu gostaria de uma implementação, no caso, essa função "public void onLocationChanged(Location location)" que está no "Localizador.class", retorna a coordenada atual. O que eu gostaria era só mostrar essa coordenada numa TextView que inseri no MapaActivity, por exemplo. Outra situação, seria uma botão, também localizado no MapaActivity que quando ao clicar crie um marcador na coordenada atual, por exemplo. Já consegui até fazer com os eventos da própria API, clique curto e longo no mapa e etc. Mas gostaria de saber como fazer com controles externos.

Olá!

Primeiramente imagino que você já deve ter colocado um botão no layout da sua MapaActivity para criar um marcador na posição atual. Para conseguir pegar a localização atual, você vai precisar armazenar a posição no próprio Localizador toda vez que chegar uma atualização do GPS e então criar um getCoordenada(...) para poder recuperar essa informação. Algo assim:

public class Localizador implements GoogleApiClient.ConnectionCallbacks, LocationListener {

    // outros atributos

    private LatLng coordenada;

    // outros métodos

    @Override
    public void onLocationChanged(Location location) {
        this.coordenada = new LatLng(location.getLatitude(), location.getLongitude());
        CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLng(coordenada);
        mapa.moveCamera(cameraUpdate);
    }

    public LatLng getCoordenada() {
        return coordenada;
    }
}

Agora na classe MapaFragment vamos precisar guardar as referências para o GoogleMap e também para o Localizador já que precisaremos invocar o método getCoordenada(...) para saber a posição atual. Você pode criar então um método criaMarcadorNaPosicaoAtual(...) no MapaFragment com a seguinte implementação:

public class MapaFragment extends SupportMapFragment implements OnMapReadyCallback {

    private Localizador localizador;
    private GoogleMap googleMap;

    @Override
    public void onMapReady(GoogleMap googleMap) {
        this.googleMap = googleMap;
        this.localizador = new Localizador(getActivity(), googleMap);

    // resto do código
    }

    public void criaMarcadorNaPosicaoAtual() {
        if (googleMap != null) {
            LatLng posicao = localizador.getCoordenada();
            // cria marcador e adiciona no googleMap
        }
    }
}

Pronto! Agora é só invocar esse método do MapaFragment toda vez que você clicar no botão de marcação que você colocou na sua MapaActivity.

Ainda não deu certo, não sei se estou esquecendo ou fazendo algo errado.

MapaFragment.class

public class MapaFragment extends SupportMapFragment implements OnMapReadyCallback {
    public int i = 0;
    public String id = "";
    public double lat_marker;
    public double long_marker;
    private GoogleMap googleMap;
    private Localizador localizador;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        getMapAsync(this);
    }

    @Override
    public void onMapReady(final GoogleMap googleMap) {

        this.googleMap = googleMap;
        this.localizador = new Localizador(getActivity(), googleMap);

        googleMap.setMyLocationEnabled(true);
        googleMap.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() {
            @Override
            public boolean onMarkerClick(Marker marker) {
                  if (id != marker.getId() && i == 1) {
                    Polyline line = googleMap.addPolyline(new PolylineOptions()
                            .add(new LatLng(lat_marker, long_marker),
                                    new LatLng(marker.getPosition().latitude, marker.getPosition().longitude))
                            .width(5)
                            .color(Color.RED));
                    i = 0;
                } else {
                    i = i + 1;
                }
                id = marker.getId();
                lat_marker = marker.getPosition().latitude;
                long_marker = marker.getPosition().longitude;
                return false;
            }
        });

        googleMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
            @Override
            public void onMapClick(LatLng latLng) {
                i = 0;
                //Toast.makeText(getContext(),latLng.toString(),Toast.LENGTH_SHORT).show();
            }
        });

        googleMap.setOnMapLongClickListener(new GoogleMap.OnMapLongClickListener() {
            @Override
            public void onMapLongClick(LatLng latLng) {
                googleMap.addMarker(new MarkerOptions()
                        .position(new LatLng(googleMap.getMyLocation().getLatitude(),googleMap.getMyLocation().getLongitude()))
                        .title("P1")
                        .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED)));
            }
        });

    }

    public void criaMarcadorNaPosicaoAtual() {      
        if (googleMap != null) {
       LatLng posicao = localizador.getCoordenada();
           googleMap.addMarker(new MarkerOptions()
                    .position(posicao)
                    .title("P2")
                    .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED)));
        }
    }

    private LatLng coordenadas (String endereco){
        try {
            Geocoder geocoder = new Geocoder(getContext());
            List<Address> resultados =
                    geocoder.getFromLocationName(endereco, 1);
            if (resultados != null) {
                LatLng posicao = new LatLng(resultados.get(0).getLatitude(),resultados.get(0).getLongitude());
                return posicao;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}

Localizador.class

public class Localizador implements GoogleApiClient.ConnectionCallbacks,LocationListener {

    private final GoogleApiClient client;
    private final GoogleMap mapa;
    private LatLng coordenada;

    public Localizador(Context context, GoogleMap mapa){
        client = new GoogleApiClient.Builder(context)
                .addApi(LocationServices.API)
                .addConnectionCallbacks(this)
                .build();
        client.connect();
        this.mapa = mapa;
    }

    @Override
    public void onConnected(Bundle bundle) {
        LocationRequest request = new LocationRequest();
        request.setSmallestDisplacement(5);//deslocamento metros
        request.setInterval(1000);//intervalo milisegundos
        request.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        LocationServices.FusedLocationApi.requestLocationUpdates(client,request,this);
    }

    @Override
    public void onConnectionSuspended(int i) {

    }

    @Override
    public void onLocationChanged(Location location) {
        this.coordenada = new LatLng(location.getLatitude(), location.getLongitude());
        CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLng(coordenada);
        mapa.moveCamera(cameraUpdate);
    }

    public LatLng getCoordenada() {
        return coordenada;
    }
}

MapaActivity.class

btnaddmarker.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                MapaFragment marcar = new MapaFragment();
                marcar.criaMarcadorNaPosicaoAtual();
            }
        });

Olá!

Na classe MapaActivity, mais especificamente no ClickListener, você precisa utilizar a mesma referência para o MapaFragment que você utilizou na hora de fazer o replace na transação do fragment. Da forma como está agora, ele está criando um novo fragment e criando o marcador nesse novo fragment, não no que já está na tela.

Jeferson, não entendi muito bem essa parte. Em qual aula posso encontrar uma explicação sobre esse assunto? Obrigado.

solução!

Olá,

No curso em si não há nenhuma aula específica sobre isso mas o que eu quis dizer é que você só precisa reutilizar o Fragment que você já criou anteriormente.

No onCreate(...) da MapaActivity você deve ter um código parecido com o abaixo:

FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.mapa, new MapaFragment());

Antes do replace, vamos criar o MapaFragment e guardá-lo num atributo da classe:

public class MapaActivity extends AppCompatActivity {

    // outros atributos

    private MapaFragment mapaFragment;

    protected void onCreate(Bundle bundle) {

        // código 
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        mapaFragment = new MapaFragment();
        ft.replace(R.id.mapa, mapaFragment);
        ft.commit();
    }

    // outros métodos
}

Agora nesse código:

    btnaddmarker.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                MapaFragment marcar = new MapaFragment();
                marcar.criaMarcadorNaPosicaoAtual();
            }
        });

Você não precisa instanciar mais o MapaFragment, você pode utilizar o atributo que guardamos antes:

    btnaddmarker.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mapaFragment.criaMarcadorNaPosicaoAtual();
            }
        });

Faça o teste e veja se funciona!

Deu certo sim Jerfeson, muito obrigado. Parabéns pelo trabalho!