Google 地图 - 在地图中显示多个标记

Google Maps - Show many markers in a map

我已经尝试了一段时间在地图中显示多个标记,但我一直 运行 出错。
我设法想出了这段代码,但我遇到了崩溃。

这是我的 mapsActivity.java

package com.example.moses.ngongapp;

import android.app.Dialog;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.FragmentActivity;
import android.view.ViewTreeObserver;
import android.widget.RelativeLayout;
import android.widget.Toast;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
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.LatLngBounds;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;


import java.util.ArrayList;
import java.util.HashMap;



    public class MapsActivity extends FragmentActivity {

        private GoogleMap googleMap;
        private ArrayList<LatLng> listLatLng;
        private RelativeLayout rlMapLayout;
        HashMap<Marker, LatLngBean> hashMapMarker = new HashMap<Marker, LatLngBean>();

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

            rlMapLayout = (RelativeLayout) findViewById(R.id.rlMapLayout);

            setUpMapIfNeeded();
            setData();

        }

        private void setData() {
            ArrayList<LatLngBean> arrayList = new ArrayList<LatLngBean>();
            LatLngBean bean = new LatLngBean();
            bean.setTitle("Ahmedabad");
            bean.setSnippet("Hello,Ahmedabad");
            bean.setLatitude("23.0300");
            bean.setLongitude("72.5800");
            arrayList.add(bean);

            LatLngBean bean1 = new LatLngBean();
            bean1.setTitle("Surat");
            bean1.setSnippet("Hello,Surat");
            bean1.setLatitude("21.1700");
            bean1.setLongitude("72.8300");
            arrayList.add(bean1);

            LatLngBean bean2 = new LatLngBean();
            bean2.setTitle("Vadodara");
            bean2.setSnippet("Hello,Vadodara");
            bean2.setLatitude("22.3000");
            bean2.setLongitude("73.2000");
            arrayList.add(bean2);

            LoadingGoogleMap(arrayList);
        }

        /**
         * @author Hasmukh Bhadani
         * Set googleMap if require
         */
        private void setUpMapIfNeeded() {
            int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(getBaseContext());

            // Google Play Services are not available
            if (status != ConnectionResult.SUCCESS) {
                int requestCode = 10;
                Dialog dialog = GooglePlayServicesUtil.getErrorDialog(status, this, requestCode);
                dialog.show();

            } else if (googleMap == null) {
                ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getMapAsync((OnMapReadyCallback) this);
                if (googleMap != null) {
                    googleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
                    if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                        // TODO: Consider calling
                        //    ActivityCompat#requestPermissions
                        // here to request the missing permissions, and then overriding
                        //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
                        //                                          int[] grantResults)
                        // to handle the case where the user grants the permission. See the documentation
                        // for ActivityCompat#requestPermissions for more details.
                        return;
                    }
                    googleMap.setMyLocationEnabled(true);
                    googleMap.getUiSettings().setMyLocationButtonEnabled(true);
                    googleMap.getUiSettings().setZoomControlsEnabled(true);
                }
            }
        }

        /**
         * @author Hasmukh Bhadani
         * Loading Data to the GoogleMap
         */
// -------------------------Google Map
        void LoadingGoogleMap(ArrayList<LatLngBean> arrayList) {
            if (googleMap != null) {
                googleMap.clear();
                googleMap.getUiSettings().setMyLocationButtonEnabled(true);
                if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                    // TODO: Consider calling
                    //    ActivityCompat#requestPermissions
                    // here to request the missing permissions, and then overriding
                    //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
                    //                                          int[] grantResults)
                    // to handle the case where the user grants the permission. See the documentation
                    // for ActivityCompat#requestPermissions for more details.
                    return;
                }
                googleMap.setMyLocationEnabled(true);
                googleMap.getUiSettings().setZoomControlsEnabled(true);

                if (arrayList.size() > 0) {
                    try {
                        listLatLng = new ArrayList<LatLng>();
                        for (int i = 0; i < arrayList.size(); i++) {
                            LatLngBean bean = arrayList.get(i);
                            if (bean.getLatitude().length() > 0 && bean.getLongitude().length() > 0) {
                                double lat = Double.parseDouble(bean.getLatitude());
                                double lon = Double.parseDouble(bean.getLongitude());

                                Marker marker = googleMap.addMarker(new MarkerOptions()
                                        .position(new LatLng(lat, lon))
                                        .title(bean.getTitle())
                                        .snippet(bean.getSnippet())
                                        .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED)));

                                //Add Marker to Hashmap
                                hashMapMarker.put(marker, bean);

                                //Set Zoom Level of Map pin
                                LatLng object = new LatLng(lat, lon);
                                listLatLng.add(object);
                            }
                        }
                        SetZoomlevel(listLatLng);
                    } catch (NumberFormatException e) {
                        e.printStackTrace();
                    }

                    googleMap.setOnInfoWindowClickListener(new GoogleMap.OnInfoWindowClickListener() {

                        @Override
                        public void onInfoWindowClick(Marker position) {
                            LatLngBean bean = hashMapMarker.get(position);
                            Toast.makeText(getApplicationContext(), bean.getTitle(), Toast.LENGTH_SHORT).show();

                        }
                    });
                }
            } else {
                Toast.makeText(getApplicationContext(), "Sorry! unable to create maps", Toast.LENGTH_SHORT).show();
            }
        }

        /**
         * @author Hasmukh Bhadani
         * Set Zoom level all pin withing screen on GoogleMap
         */
        public void SetZoomlevel(ArrayList<LatLng> listLatLng) {
            if (listLatLng != null && listLatLng.size() == 1) {
                googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(listLatLng.get(0), 10));
            } else if (listLatLng != null && listLatLng.size() > 1) {
                final LatLngBounds.Builder builder = LatLngBounds.builder();
                for (int i = 0; i < listLatLng.size(); i++) {
                    builder.include(listLatLng.get(i));
                }

                final ViewTreeObserver treeObserver = rlMapLayout.getViewTreeObserver();
                treeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                    @SuppressWarnings("deprecation")
                    @Override
                    public void onGlobalLayout() {
                        if (googleMap != null) {
                            googleMap.moveCamera(CameraUpdateFactory.newLatLngBounds(builder.build(), findViewById(R.id.map)
                                    .getWidth(), findViewById(R.id.map).getHeight(), 80));
                            rlMapLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                        }
                    }
                });

            }
        }
    }

我的logcat在这里

FATAL EXCEPTION: main
Process: com.example.moses.ngongapp, PID: 28132
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.moses.ngongapp/com.example.moses.ngongapp.MapsActivity}: java.lang.ClassCastException: com.example.moses.ngongapp.MapsActivity cannot be cast to com.google.android.gms.maps.OnMapReadyCallback
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2379)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2442)
    at android.app.ActivityThread.access0(ActivityThread.java:156)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1351)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:211)
    at android.app.ActivityThread.main(ActivityThread.java:5371)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:945)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:740)
 Caused by: java.lang.ClassCastException: com.example.moses.ngongapp.MapsActivity cannot be cast to com.google.android.gms.maps.OnMapReadyCallback
    at com.example.moses.ngongapp.MapsActivity.setUpMapIfNeeded(MapsActivity.java:90)
    at com.example.moses.ngongapp.MapsActivity.onCreate(MapsActivity.java:44)
@Override
public void onMapReady(GoogleMap map) {
    this.googleMap = map;

    setUpMapIfNeeded();
    setData()
}

onMapReady()中做地图相关的事情。

此处出错

((SupportMapFragment) getSupportFragmentManager()
    .findFragmentById(R.id.map)).getMapAsync((OnMapReadyCallback) this);

错误清楚地写着“MapsActivity cannot be cast to com.google.android.gms.maps.OnMapReadyCallback”。

所以,只需实现该接口

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {

并从该接口实现相应的 onMapReady 方法。

那你就不用施法了。只是 getMapAsync(MapsActivity.this)

在该方法之内或之后之前,也不要执行任何 GoogleMap 相关功能。

关于您的评论,您必须跟踪您的代码以确切说明 if (googleMap != null) { 未被输入的原因。因为地图是空的 - 显然。但为什么?因为 getMapAsync 将 "wait" 直到地图准备就绪,此时 getMapAsync 在未来某个不确定的点被调用(因此异步,它在后台运行)。

换句话说,不要在onCreate中调用setUpMapIfNeeded或setData方法,而是仅在地图可用时调用(从参数到onMapReady方法)

@Override
public void onMapReady(GoogleMap map) {
    this.googleMap = map;

    setUpMapIfNeeded();
    setData(); // this calls LoadingGoogleMap() 
}

如果标记仍然不可见,请继续调试您的代码。该答案仅用于解决问题中提到的错误。


顺便说一句,your previous question was already implementing the interface

您可以实施 onMapReady 等新方法以及有关该方法的其余工作。

((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).
    getMapAsync(new OnMapReadyCallback()

            @Override
          public void onMapReady(GoogleMap map) {
          this.googleMap = map;
          setUpMapIfNeeded();
          setData()
      });