Android GoogleMap不完全指南 (三)

Android GoogleMap不完全指南 (一)
Android GoogleMap不完全指南 (二)

在前两篇文章里面,我们做了google map接入和基本的地图加载,地理编码和逆地理编码。

这篇做Map列表。

一、Map列表

前文已经说过,加载google map大概分为fragment和MapView两种方式。
显然,做列表的的话用fragment是不太合适,那么就是MapView了。

但是在前面说到

在完全交互模式下使用该 API 时,MapView 类的用户必须将下列 Activity 生命周期方法转发给 MapView 类中的相应方法:onCreate()、onStart()、onResume()、onPause()、onStop()、onDestroy()、onSaveInstanceState() 和 onLowMemory()。

那么问题来了,如果在adapter里面还要结合以上的生命周期方法,那玩什么呀。
是的,不是这么玩的。

具体做法先看一张图

Android GoogleMap不完全指南 (三)_第1张图片
列表关键.png

MapsInitializer.initialize(Context context);

  • MapsInitializer
Use this class to initialize the Google Maps Android API if features need to be used before obtaining a map. It must be called because some classes such as BitmapDescriptorFactory and CameraUpdateFactory need to be initialized.

两脚猫翻译如下:如果还没获取地图,但是又要使用到地图的特性,可以调用此类初始化地图。它的可以让BitmapDescriptorFactory和CameraUpdateFactory得到初始化。

大概也就说在getMapAsync()之前想使用地图,你就需要用到这个类吧。

initialize(Context context)
传入Context,初始化地图

mapView.onCreate (Bundle savedInstanceState)
使用MapView必须在父Activity/Fragment对应的onCreate方法里面调用mapView.onCreate。没错说的是必须。
.
.

二、ListView 地图列表

老规矩,先上图

LvMap.gif

代码

LvMapAdapter

public class LvMapAdapter extends BaseAdapter {

    private ArrayList mDatas;
    private Context mContext;


    public LvMapAdapter(Context mContext,ArrayList mDatas){
        this.mDatas = mDatas;
        this.mContext = mContext;
    }


    @Override
    public int getCount() {
        return mDatas.size();
    }

    @Override
    public Object getItem(int position) {
        return mDatas.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup viewGroup) {


        ViewHolder viewHolder;
        if (convertView == null){
            viewHolder= new ViewHolder();
            convertView = LayoutInflater.from(mContext).inflate(R.layout.item_lv_map, null);
            viewHolder.tv_title = (TextView) convertView.findViewById(R.id.lite_listrow_text);
            viewHolder.mapView = (MapView) convertView.findViewById(R.id.lite_listrow_map);
            
            // Initialise the MapView
            viewHolder.initializeMapView(); // 第一次加载时先初始化地图
            convertView.setTag(viewHolder);
        }else{
            viewHolder= (ViewHolder) convertView.getTag();
        }
        
        // Get the NamedLocation for this item and attach it to the MapView
        NamedLocation item = mDatas.get(position);
        viewHolder.mapView.setTag(item);  // 给view在单独打一个tag
        
        // Ensure the map has been initialised by the on map ready callback in ViewHolder.
        // If it is not ready yet, it will be initialised with the NamedLocation set as its tag
        // when the callback is received.
        // 这里是复用时的确保地址整错,防止错位
        if (viewHolder.map != null) {
            // The map is already ready to be used
            setMapLocation(viewHolder.map, item);
        }
        // Set the text label for this item
        viewHolder.tv_title.setText(item.name);

        return convertView;
    }

    class ViewHolder implements OnMapReadyCallback {
        TextView tv_title;
        MapView mapView;

        /**
         * ViewHolder多增了一个变量,取自onMapReady的参数,作用是复用的时候有一个已经准备就绪的GoogleMap对象
         */
        GoogleMap map;

        public void initializeMapView() {
            if (mapView != null) {
                mapView.onCreate(null); // MapView对象使用之前调用onCreate必不可少,作用是初始化 MapView
                mapView.getMapAsync(this);
            }
        }

        @Override
        public void onMapReady(GoogleMap googleMap) {
            MapsInitializer.initialize(mContext);
            map = googleMap;
            NamedLocation data = (NamedLocation) mapView.getTag();
            if (data != null) {
                setMapLocation(map, data);
            }
        }
    }

    private static void setMapLocation(GoogleMap map, NamedLocation data) {
        map.moveCamera(CameraUpdateFactory.newLatLngZoom(data.location, 13f));
        map.addMarker(new MarkerOptions().position(data.location));
        map.setMapType(GoogleMap.MAP_TYPE_NORMAL);
    }

    /**
     * RecycleListener that completely clears the {@link com.google.android.gms.maps.GoogleMap}
     * attached to a row in the ListView.
     * Sets the map type to {@link com.google.android.gms.maps.GoogleMap#MAP_TYPE_NONE} and clears
     * the map.
     */
    public AbsListView.RecyclerListener mRecycleListener = new AbsListView.RecyclerListener() {

        @Override
        public void onMovedToScrapHeap(View view) {
            ViewHolder holder = (ViewHolder) view.getTag();
            if (holder != null && holder.map != null) {
                // Clear the map and free up resources by changing the map type to none
                holder.map.clear();
                holder.map.setMapType(GoogleMap.MAP_TYPE_NONE);
            }
        }
    };
}

.
.
LvMapActivity

public class LvMapActivity extends AppCompatActivity {

    private ListView mLv;
    private ArrayList mDatas;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_lv_map);
        mLv = (ListView) findViewById(R.id.mLv);
        mDatas = new ArrayList<>();
        fillData();
        LvMapAdapter lvMapAdapter = new LvMapAdapter(LvMapActivity.this, mDatas);
        mLv.setAdapter(lvMapAdapter);
        mLv.setRecyclerListener(lvMapAdapter.mRecycleListener);
    }

    private void fillData() {
        mDatas.add(new NamedLocation("Cape Town", new LatLng(-33.920455, 18.466941)));
        mDatas.add(new NamedLocation("Beijing", new LatLng(39.937795, 116.387224)));
        mDatas.add(new NamedLocation("Bern", new LatLng(46.948020, 7.448206)));
        mDatas.add(new NamedLocation("Breda", new LatLng(51.589256, 4.774396)));
        mDatas.add(new NamedLocation("Brussels", new LatLng(50.854509, 4.376678)));
        mDatas.add(new NamedLocation("Copenhagen", new LatLng(55.679423, 12.577114)));
        mDatas.add(new NamedLocation("Hannover", new LatLng(52.372026, 9.735672)));
        mDatas.add(new NamedLocation("Helsinki", new LatLng(60.169653, 24.939480)));
        mDatas.add(new NamedLocation("Hong Kong", new LatLng(22.325862, 114.165532)));
        mDatas.add(new NamedLocation("Istanbul", new LatLng(41.034435, 28.977556)));
        mDatas.add(new NamedLocation("Johannesburg", new LatLng(-26.202886, 28.039753)));
        mDatas.add(new NamedLocation("Lisbon", new LatLng(38.707163, -9.135517)));
        mDatas.add(new NamedLocation("London", new LatLng(51.500208, -0.126729)));
        mDatas.add(new NamedLocation("Madrid", new LatLng(40.420006, -3.709924)));
        mDatas.add(new NamedLocation("Mexico City", new LatLng(19.427050, -99.127571)));
        mDatas.add(new NamedLocation("Moscow", new LatLng(55.750449, 37.621136)));
        mDatas.add(new NamedLocation("New York", new LatLng(40.750580, -73.993584)));
        mDatas.add(new NamedLocation("Oslo", new LatLng(59.910761, 10.749092)));
        mDatas.add(new NamedLocation("Paris", new LatLng(48.859972, 2.340260)));
        mDatas.add(new NamedLocation("Prague", new LatLng(50.087811, 14.420460)));
        mDatas.add(new NamedLocation("Rio de Janeiro", new LatLng(-22.90187, -43.232437)));
        mDatas.add(new NamedLocation("Rome", new LatLng(41.889998, 12.500162)));
        mDatas.add(new NamedLocation("Sao Paolo", new LatLng(-22.863878, -43.244097)));
        mDatas.add(new NamedLocation("Seoul", new LatLng(37.560908, 126.987705)));
        mDatas.add(new NamedLocation("Stockholm", new LatLng(59.330650, 18.067360)));
        mDatas.add(new NamedLocation("Sydney", new LatLng(-33.873651, 151.2068896)));
        mDatas.add(new NamedLocation("Taipei", new LatLng(25.022112, 121.478019)));
        mDatas.add(new NamedLocation("Tokyo", new LatLng(35.670267, 139.769955)));
        mDatas.add(new NamedLocation("Tulsa Oklahoma", new LatLng(36.149777, -95.993398)));
        mDatas.add(new NamedLocation("Vaduz", new LatLng(47.141076, 9.521482)));
        mDatas.add(new NamedLocation("Vienna", new LatLng(48.209206, 16.372778)));
        mDatas.add(new NamedLocation("Warsaw", new LatLng(52.235474, 21.004057)));
        mDatas.add(new NamedLocation("Wellington", new LatLng(-41.286480, 174.776217)));
        mDatas.add(new NamedLocation("Winnipeg", new LatLng(49.875832, -97.150726)));
    }
}

.
.
两个布局
activity_lv_map




    
    
    

.
.
item_lv_map




    

    
    


嗯,大概就是这样啦。

要说注意的地方,也就是下面的红线框出的地方吧

Android GoogleMap不完全指南 (三)_第2张图片
image.png

还有就是Listview可以设置setRecyclerListener

像Map这类耗资源的控件,及时setRecyclerListener还是挺重要的

    mLv.setRecyclerListener(lvMapAdapter.mRecycleListener);

.

    public AbsListView.RecyclerListener mRecycleListener = new AbsListView.RecyclerListener() {

        @Override
        public void onMovedToScrapHeap(View view) {
            ViewHolder holder = (ViewHolder) view.getTag();
            if (holder != null && holder.map != null) {
                // Clear the map and free up resources by changing the map type to none
                holder.map.clear();
                holder.map.setMapType(GoogleMap.MAP_TYPE_NONE);
            }
        }
    };

.
.

三、RecyclerView版

图儿图儿,效果跟Lv版的几乎一致


RvMap.gif

代码

RvLocAdapter

public class RvLocAdapter extends RecyclerView.Adapter {
    public ArrayList mDatas = null;
    public static Context mContext;

    // 点击回调
    public interface OnItemClickLitener
    {
        void onItemClick(View view, int position);  // 点击
        void onItemLongClick(View view, int position); // 长按
    }

    private OnItemClickLitener mOnItemClickLitener;

    public void setOnItemClickLitener(OnItemClickLitener mOnItemClickLitener)
    {
        this.mOnItemClickLitener = mOnItemClickLitener;
    }

    public RvLocAdapter(Context context, ArrayList datas) {
        this.mDatas = datas;
        this.mContext = context;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
        View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_lv_map,viewGroup,false);
        return new ViewHolder(view);
    }
    //将数据与界面进行绑定的操作
    @Override
    public void onBindViewHolder(final ViewHolder viewHolder, int position) {
        final NamedLocation namedLocation = mDatas.get(position);

        viewHolder.tv_location.setText(namedLocation.name);

        NamedLocation item = mDatas.get(position);
        viewHolder.mapView.setTag(item);

        if (viewHolder.map != null) {
            // The map is already ready to be used
            setMapLocation(viewHolder.map, item);
        }
    }

    @Override
    public int getItemCount() {
        return mDatas.size();
    }

    public static class ViewHolder extends RecyclerView.ViewHolder implements OnMapReadyCallback {
        private TextView tv_location;
        private MapView mapView;
        GoogleMap map;

        public ViewHolder(View view){
            super(view);
            tv_location = (TextView) view.findViewById(R.id.lite_listrow_text);
            mapView = (MapView) view.findViewById(R.id.lite_listrow_map);
            initializeMapView();
        }

        public void initializeMapView() {
            if (mapView != null) {
                mapView.onCreate(null); // MapView对象使用之前调用onCreate必不可少,作用是初始化 MapView
                mapView.getMapAsync(this);
            }
        }

        @Override
        public void onMapReady(GoogleMap googleMap) {
            MapsInitializer.initialize(mContext);
            map = googleMap;
            NamedLocation data = (NamedLocation) mapView.getTag();
            if (data != null) {
                setMapLocation(map, data);
            }
        }
    }

    private static void setMapLocation(GoogleMap map, NamedLocation data) {
        map.moveCamera(CameraUpdateFactory.newLatLngZoom(data.location, 13f));
        map.addMarker(new MarkerOptions().position(data.location));
        map.setMapType(GoogleMap.MAP_TYPE_NORMAL);
    }
}

.
.
RecyclerViewMapActivity

public class RecyclerViewMapActivity extends AppCompatActivity {
    private RecyclerView mRv;
    private ArrayList mDatas;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_rv_map);

        mRv = (RecyclerView) findViewById(R.id.mRv);
        mRv.setLayoutManager(new LinearLayoutManager(this));

        mDatas = new ArrayList<>();
        fillData();
        mRv.setAdapter(new RvLocAdapter(RecyclerViewMapActivity.this, mDatas));
    }

    private void fillData() {
        mDatas.add(new NamedLocation("Cape Town", new LatLng(-33.920455, 18.466941)));
        mDatas.add(new NamedLocation("Beijing", new LatLng(39.937795, 116.387224)));
        mDatas.add(new NamedLocation("Bern", new LatLng(46.948020, 7.448206)));
        mDatas.add(new NamedLocation("Breda", new LatLng(51.589256, 4.774396)));
        mDatas.add(new NamedLocation("Brussels", new LatLng(50.854509, 4.376678)));
        mDatas.add(new NamedLocation("Copenhagen", new LatLng(55.679423, 12.577114)));
        mDatas.add(new NamedLocation("Hannover", new LatLng(52.372026, 9.735672)));
        mDatas.add(new NamedLocation("Helsinki", new LatLng(60.169653, 24.939480)));
        mDatas.add(new NamedLocation("Hong Kong", new LatLng(22.325862, 114.165532)));
        mDatas.add(new NamedLocation("Istanbul", new LatLng(41.034435, 28.977556)));
        mDatas.add(new NamedLocation("Johannesburg", new LatLng(-26.202886, 28.039753)));
        mDatas.add(new NamedLocation("Lisbon", new LatLng(38.707163, -9.135517)));
        mDatas.add(new NamedLocation("London", new LatLng(51.500208, -0.126729)));
        mDatas.add(new NamedLocation("Madrid", new LatLng(40.420006, -3.709924)));
        mDatas.add(new NamedLocation("Mexico City", new LatLng(19.427050, -99.127571)));
        mDatas.add(new NamedLocation("Moscow", new LatLng(55.750449, 37.621136)));
        mDatas.add(new NamedLocation("New York", new LatLng(40.750580, -73.993584)));
        mDatas.add(new NamedLocation("Oslo", new LatLng(59.910761, 10.749092)));
        mDatas.add(new NamedLocation("Paris", new LatLng(48.859972, 2.340260)));
        mDatas.add(new NamedLocation("Prague", new LatLng(50.087811, 14.420460)));
        mDatas.add(new NamedLocation("Rio de Janeiro", new LatLng(-22.90187, -43.232437)));
        mDatas.add(new NamedLocation("Rome", new LatLng(41.889998, 12.500162)));
        mDatas.add(new NamedLocation("Sao Paolo", new LatLng(-22.863878, -43.244097)));
        mDatas.add(new NamedLocation("Seoul", new LatLng(37.560908, 126.987705)));
        mDatas.add(new NamedLocation("Stockholm", new LatLng(59.330650, 18.067360)));
        mDatas.add(new NamedLocation("Sydney", new LatLng(-33.873651, 151.2068896)));
        mDatas.add(new NamedLocation("Taipei", new LatLng(25.022112, 121.478019)));
        mDatas.add(new NamedLocation("Tokyo", new LatLng(35.670267, 139.769955)));
        mDatas.add(new NamedLocation("Tulsa Oklahoma", new LatLng(36.149777, -95.993398)));
        mDatas.add(new NamedLocation("Vaduz", new LatLng(47.141076, 9.521482)));
        mDatas.add(new NamedLocation("Vienna", new LatLng(48.209206, 16.372778)));
        mDatas.add(new NamedLocation("Warsaw", new LatLng(52.235474, 21.004057)));
        mDatas.add(new NamedLocation("Wellington", new LatLng(-41.286480, 174.776217)));
        mDatas.add(new NamedLocation("Winnipeg", new LatLng(49.875832, -97.150726)));
    }
}

附上布局Activity布局,其中adapter的布局和LvAdapter一致。
activity_rv_map




    


    

本文就到这里吧,下次有空写一个GoogleMap仿造微信发地址的demo。

本文完。


git 传送

你可能感兴趣的:(Android GoogleMap不完全指南 (三))