首页 > 解决方案 > 在 MapsActivity 中使用当前位置填充标记

问题描述

我已经成功开发了一个程序来在用户旅行时更新标记,但是文本只会显示“当前位置”

我还想在单击时向用户填充地址信息的标记。下面是一些强调我的意图的代码片段,任何帮助将不胜感激!谢谢

这是我当前的 MapsActivity.java

 import android.Manifest;
    import android.content.pm.PackageManager;
    import android.graphics.Camera;
    import android.location.Address;
    import android.location.Geocoder;
    import android.location.Location;
    import android.os.Build;
    import android.support.annotation.NonNull;
    import android.support.annotation.Nullable;
    import android.support.v4.app.ActivityCompat;
    import android.support.v4.app.FragmentActivity;
    import android.os.Bundle;
    import android.support.v4.content.ContextCompat;
    import android.view.View;
    import android.widget.EditText;
    import android.widget.TextView;
    import android.widget.Toast;

    import com.google.android.gms.common.ConnectionResult;
    import com.google.android.gms.common.api.GoogleApiClient;
    import com.google.android.gms.location.LocationListener;
    import com.google.android.gms.location.LocationRequest;
    import com.google.android.gms.location.LocationServices;
    import com.google.android.gms.maps.CameraUpdateFactory;
    import com.google.android.gms.maps.GoogleMap;
    import com.google.android.gms.maps.OnMapReadyCallback;
    import com.google.android.gms.maps.SupportMapFragment;
    import com.google.android.gms.maps.model.BitmapDescriptorFactory;
    import com.google.android.gms.maps.model.LatLng;
    import com.google.android.gms.maps.model.Marker;
    import com.google.android.gms.maps.model.MarkerOptions;

    import java.io.IOException;
    import java.util.List;

    public class MapsActivity extends FragmentActivity implements OnMapReadyCallback,
            GoogleApiClient.ConnectionCallbacks,
            GoogleApiClient.OnConnectionFailedListener,
            LocationListener {

        private GoogleMap mMap;
        private GoogleApiClient client;
        private LocationRequest locationRequest;
        private Location lastLocation;
        private Marker currentLocationMarker;
        public static final int REQUEST_LOCATION_CODE = 99;
        TextView textView;
        Geocoder geocoder;
        List<Address> addresses;


        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_maps);

            if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
                checkLocationPermission();
            }

            // Obtain the SupportMapFragment and get notified when the map is ready to be used.
            SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                    .findFragmentById(R.id.map);
            mapFragment.getMapAsync(this);
        }

        @Override
        public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
           switch(requestCode)
           {
               case REQUEST_LOCATION_CODE:
                   if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
                   {
                       //permission is granted
                       if(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
                           if(client == null){
                               buildGoogleApiClient();
                           }
                           mMap.setMyLocationEnabled(true);
                       }
                   }
               else  {
                       Toast.makeText(this, "Permission Denied!", Toast.LENGTH_LONG).show();
                       //Permission is denied
                   }
                   return;
           }
        }

        @Override
        public void onMapReady(GoogleMap googleMap) {
            Toast.makeText(this, "Click Icon in Top right for Current Location", Toast.LENGTH_LONG).show();
            mMap = googleMap;
            LatLng Phoenix = new LatLng(33.6056711, -112.4052378);
            mMap.addMarker(new MarkerOptions().position(Phoenix).title("Default Location: Phoenix, AZ"));
            mMap.moveCamera(CameraUpdateFactory.newLatLng(Phoenix));


           if(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
                buildGoogleApiClient();
                mMap.setMyLocationEnabled(true);

            }
        }

            protected synchronized void buildGoogleApiClient(){
                 client = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();

                 client.connect();
            }


        @Override
public void onLocationChanged(Location location) {
    lastLocation = location;

    if(currentLocationMarker != null){
        currentLocationMarker.remove();
 }

 LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
 MarkerOptions markerOptions = new MarkerOptions();
 markerOptions.position(latLng);
 markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE));


    textView = (TextView) findViewById(R.id.textView);
    geocoder = new Geocoder(this, Locale.getDefault());

    try {
        addresses = geocoder.getFromLocation(location.getLatitude(), location.getLongitude(), 1);

 String address = addresses.get(0).getAddressLine(0);
 String area = addresses.get(0).getLocality();
 String city = addresses.get(0).getAdminArea();
 String country = addresses.get(0).getCountryName();
 String postalcode = addresses.get(0).getPostalCode();

 String fullAddress = address+", "+area+", " +city+", " + country+ "," + postalcode;

        textView.setText(fullAddress);

 } catch (IOException e) {
 e.printStackTrace();
 }


    mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
    mMap.animateCamera(CameraUpdateFactory.zoomBy(10));

    if(client != null){
 LocationServices.FusedLocationApi.removeLocationUpdates(client, this);
 }

}

        @Override
        public void onConnected(@Nullable Bundle bundle) {
            locationRequest = new LocationRequest();
            locationRequest.setInterval(1000);
            locationRequest.setFastestInterval(1000);
            locationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);

            if(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {

                LocationServices.FusedLocationApi.requestLocationUpdates(client, locationRequest, this);
            }
        }

        public boolean checkLocationPermission(){
            if(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                if(ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION))
                {
                    ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_LOCATION_CODE);
                }
                else {
                    ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_LOCATION_CODE);
                }
                return false;
            }
            else
                return true;
        }

        public void onZoom(View view) {
            if (view.getId() == R.id.zoomIn) {
                mMap.animateCamera(CameraUpdateFactory.zoomIn());
            }
            if (view.getId() == R.id.zoomOut) {
                mMap.animateCamera(CameraUpdateFactory.zoomOut());
            }
        }

        public void ChangeType(View view) {
            if (mMap.getMapType() == GoogleMap.MAP_TYPE_NORMAL) {
                mMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
                Toast.makeText(this, "Satellite Map Style", Toast.LENGTH_LONG).show();

            }
            else if (mMap.getMapType() == GoogleMap.MAP_TYPE_SATELLITE) {
                mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
                Toast.makeText(this, "Hybrid Map Style", Toast.LENGTH_LONG).show();
            }
            else if (mMap.getMapType() == GoogleMap.MAP_TYPE_HYBRID) {
                mMap.setMapType(GoogleMap.MAP_TYPE_TERRAIN);
                Toast.makeText(this, "Terrain Map Style", Toast.LENGTH_LONG).show();
            }
            else if (mMap.getMapType() == GoogleMap.MAP_TYPE_TERRAIN) {
                mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
                Toast.makeText(this, "Normal Map Style", Toast.LENGTH_LONG).show();
            }
            }


        @Override
        public void onConnectionSuspended(int i) {

        }

        @Override
        public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {

        }
    }

下面是对应的xml文件:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/layout1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_below="@+id/img_header" >

    <fragment
        android:id="@+id/map"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        class="com.google.android.gms.maps.SupportMapFragment" />
    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:text="Test"
        android:layout_centerHorizontal="true"
        android:textSize="22sp"/>
</RelativeLayout>

堆栈跟踪

05-17 09:15:49.411 15842-15842/edu.phoenix.mbl402.week3apptt2163 E/AndroidRuntime: FATAL EXCEPTION: main
Process: edu.phoenix.mbl402.week3apptt2163, PID: 15842
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
    at java.util.ArrayList.get(ArrayList.java:437)
    at edu.phoenix.mbl402.week3apptt2163.MapsActivity.onLocationChanged(MapsActivity.java:139)
    at com.google.android.gms.internal.location.zzay.notifyListener(Unknown Source:4)
    at com.google.android.gms.common.api.internal.ListenerHolder.notifyListenerInternal(Unknown Source:8)
    at com.google.android.gms.common.api.internal.ListenerHolder$zza.handleMessage(Unknown Source:16)
    at android.os.Handler.dispatchMessage(Handler.java:105)
    at android.os.Looper.loop(Looper.java:164)
    at android.app.ActivityThread.main(ActivityThread.java:6541)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)

最终编辑:

@Override
public void onLocationChanged(Location location) {
    lastLocation = location;

    if(currentLocationMarker != null){
        currentLocationMarker.remove();
    }

    LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
    MarkerOptions markerOptions = new MarkerOptions();
    markerOptions.position(latLng);
    markerOptions.title(getAddressForLatLng());
    markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE));

    currentLocationMarker = mMap.addMarker((markerOptions));

    mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));

}


public static Address getAddressForLatLng(Context context, LatLng location) {
    final int MAX_RESULTS = 1;
    final Geocoder geocoder = new Geocoder(context, Locale.getDefault());
    Address address = new Address(Locale.getDefault());
    try {
        final List<Address> addresses = geocoder.getFromLocation(location.latitude, location.longitude, MAX_RESULTS);
        if (addresses != null && addresses.size() != 0) {
            address = addresses.get(0);
        }
        return address;
    } catch (IOException e) {
        Log.e("Geocoding", "Geocoding was not possible");
    }
    return address;
}

标签: javaandroidgoogle-maps

解决方案


您不必在每次位置更新时从地图上删除标记。重用对它的现有标记存储引用。

Marker mMarker = mMap.addMarker(new MarkerOptions()......)

创建 mMarkerObject 后,在 OnLocationChanged 中刷新其位置

mMarker.setTitle() mMarker.setPosition(latLng);

如果由于某种原因您仍然想实现点击操作添加接口到您的主要活动 OnMarkerClickListener 并覆盖 OnMarkerClick 并使用 showInfoWindow 或其他东西:)

编辑:对于 geocrush 尝试以下 ->

public static Address getAddressForLatLng(final Context context, final LatLng location) {
    final int MAX_RESULTS = 1;
    final Geocoder geocoder = new Geocoder(context, Locale.getDefault());
    Address address = new Address(Locale.getDefault());
    try {
        final List<Address> addresses = geocoder.getFromLocation(location.latitude, location.longitude, MAX_RESULTS);
        if (addresses != null && addresses.size() != 0) {
            address = addresses.get(0);
        }
        return address;
    } catch (IOException e) {
        Log.e("Geocoding", "Geocoding was not possible");
    }
    return address;
}

简化更高效的 onLocationChanged() 版本

@Override
public void onLocationChanged(Location location) {
lastLocation = location;

LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
currentLocationMarker.setPosition(latLng);
// make sure following setTitle gets String from getAddressForLatLng
currentLocationMarker.setTitle(getAddressForLatLng(latLng));

mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
}

推荐阅读