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里面还要结合以上的生命周期方法,那玩什么呀。
是的,不是这么玩的。
具体做法先看一张图
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 地图列表
老规矩,先上图
代码
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
嗯,大概就是这样啦。
要说注意的地方,也就是下面的红线框出的地方吧
还有就是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版的几乎一致
代码
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 传送