Android GoogleMap不完全指南 (一)
Android GoogleMap不完全指南 (二)
在前兩篇文章里面相满,我們做了google map接入和基本的地圖加載渴庆,地理編碼和逆地理編碼趴乡。
這篇做Map列表珊豹。
一吭练、Map列表
前文已經(jīng)說(shuō)過(guò)威创,加載google map大概分為fragment和MapView兩種方式落午。
顯然,做列表的的話用fragment是不太合適肚豺,那么就是MapView了溃斋。
但是在前面說(shuō)到
在完全交互模式下使用該 API 時(shí),MapView 類的用戶必須將下列 Activity 生命周期方法轉(zhuǎn)發(fā)給 MapView 類中的相應(yīng)方法:onCreate()吸申、onStart()梗劫、onResume()享甸、onPause()、onStop()梳侨、onDestroy()蛉威、onSaveInstanceState() 和 onLowMemory()。
那么問(wèn)題來(lái)了走哺,如果在adapter里面還要結(jié)合以上的生命周期方法蚯嫌,那玩什么呀。
是的丙躏,不是這么玩的择示。
具體做法先看一張圖
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.
兩腳貓翻譯如下:如果還沒(méi)獲取地圖,但是又要使用到地圖的特性彼哼,可以調(diào)用此類初始化地圖对妄。它的可以讓BitmapDescriptorFactory和CameraUpdateFactory得到初始化湘今。
大概也就說(shuō)在getMapAsync()之前想使用地圖敢朱,你就需要用到這個(gè)類吧。
initialize(Context context)
傳入Context摩瞎,初始化地圖
mapView.onCreate (Bundle savedInstanceState)
使用MapView必須在父Activity/Fragment對(duì)應(yīng)的onCreate方法里面調(diào)用mapView.onCreate拴签。沒(méi)錯(cuò)說(shuō)的是必須。
.
.
二旗们、ListView 地圖列表
老規(guī)矩蚓哩,先上圖
代碼
LvMapAdapter
public class LvMapAdapter extends BaseAdapter {
private ArrayList<NamedLocation> mDatas;
private Context mContext;
public LvMapAdapter(Context mContext,ArrayList<NamedLocation> 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(); // 第一次加載時(shí)先初始化地圖
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在單獨(dú)打一個(gè)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.
// 這里是復(fù)用時(shí)的確保地址整錯(cuò),防止錯(cuò)位
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多增了一個(gè)變量上渴,取自onMapReady的參數(shù)岸梨,作用是復(fù)用的時(shí)候有一個(gè)已經(jīng)準(zhǔn)備就緒的GoogleMap對(duì)象
*/
GoogleMap map;
public void initializeMapView() {
if (mapView != null) {
mapView.onCreate(null); // MapView對(duì)象使用之前調(diào)用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<NamedLocation> 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)));
}
}
.
.
兩個(gè)布局
activity_lv_map
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="ListView Map 列表"
android:textColor="#ff0000"
android:gravity="center"
android:padding="10dp"
android:textSize="24sp"
/>
<ListView
android:id="@+id/mLv"
android:layout_width="match_parent"
android:layout_height="match_parent"></ListView>
</LinearLayout>
.
.
item_lv_map
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="5dp">
<TextView
android:id="@+id/lite_listrow_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge" />
<!-- MapView in lite mode. Note that it needs to be initialised
programmatically before it can be used. -->
<com.google.android.gms.maps.MapView
android:id="@+id/lite_listrow_map"
android:layout_width="match_parent"
android:layout_height="150dp"
map:liteMode="true"
map:mapType="none" />
</LinearLayout>
嗯稠氮,大概就是這樣啦曹阔。
要說(shuō)注意的地方,也就是下面的紅線框出的地方吧
還有就是Listview可以設(shè)置setRecyclerListener
像Map這類耗資源的控件隔披,及時(shí)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<RvLocAdapter.ViewHolder> {
public ArrayList<NamedLocation> mDatas = null;
public static Context mContext;
// 點(diǎn)擊回調(diào)
public interface OnItemClickLitener
{
void onItemClick(View view, int position); // 點(diǎn)擊
void onItemLongClick(View view, int position); // 長(zhǎng)按
}
private OnItemClickLitener mOnItemClickLitener;
public void setOnItemClickLitener(OnItemClickLitener mOnItemClickLitener)
{
this.mOnItemClickLitener = mOnItemClickLitener;
}
public RvLocAdapter(Context context, ArrayList<NamedLocation> 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);
}
//將數(shù)據(jù)與界面進(jìn)行綁定的操作
@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對(duì)象使用之前調(diào)用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<NamedLocation> 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
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="RecyclerView Map 列表"
android:textColor="#ff0000"
android:gravity="center"
android:padding="10dp"
android:textSize="24sp"
/>
<android.support.v7.widget.RecyclerView
android:id="@+id/mRv"
android:layout_width="match_parent"
android:layout_height="match_parent"></android.support.v7.widget.RecyclerView>
</LinearLayout>
本文就到這里吧鬓长,下次有空寫一個(gè)GoogleMap仿造微信發(fā)地址的demo谒拴。
本文完。