Android 百度地图仿饿了么地图定位

今天遇到了一个需求,就是在用户选择地理位置的时候,现在地图上选择一个位置,然后再手动输入具体门牌号信息。和饿了么类似。

想法是 在屏幕中间放一个 ImageView 固定,然后拖动屏幕的话,只有地图在动。因为如果是用 Marker 来绘制的话,有可能会出现重影而且可能会卡。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178

public class MapActivity extends BaseActivity implements View.OnClickListener {

private MapView mapView;
private BaiduMap baiduMap;
public static final int LOADING = 997;
public static final int FINISH = 998;
private String address;
private TextView tvAddress;
private GeoCoder geoCoder;
private TextView tvConfirm;
public LocationClient locationClient = null;
//是否首次定位
boolean isFirstLoc = true;
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case LOADING:
tvAddress.setText("正在获取位置");
break;
case FINISH:
break;
}
}
};

private LocationListener myLitenner = new BDLocationListener {

@Override
public void onReceiveLocation(BDLocation bdLocation) {
//MAP VIEW 销毁后不在处理新接收的位置
if (mapView == null)
return;
MyLocationData locData = new MyLocationData.Builder()
//此处设置开发者获取到的方向信息,顺时针0-360
.accuracy(bdLocation.getRadius())
.direction(100).latitude(bdLocation.getLatitude())
.longitude(bdLocation.getLongitude()).build();
baiduMap.setMyLocationData(locData);
//设置定位数据
if (isFirstLoc) {
isFirstLoc = false;
LatLng ll = new LatLng(bdLocation.getLatitude(), bdLocation.getLongitude());
MapStatusUpdate mapStatusUpdate = MapStatusUpdateFactory.newLatLngZoom(ll, 16);
//设置地图中心点以及缩放级别
baiduMap.animateMapStatus(mapStatusUpdate);
}
}
};

private OnMapStatusChangeListener mapChangeListener = new BaiduMap.OnMapStatusChangeListener() {
@Override
public void onMapStatusChangeStart(MapStatus mapStatus) {
handler.sendEmptyMessage(LOADING);
}

@Override
public void onMapStatusChangeStart(MapStatus mapStatus, int i) {
handler.sendEmptyMessage(LOADING);
}

@Override
public void onMapStatusChange(MapStatus mapStatus) {

}

@Override
public void onMapStatusChangeFinish(MapStatus mapStatus) {
searchAddress(mapStatus.target);
}
};


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

initView();
}

@Override
protected void onResume() {
mapView.onResume();
super.onResume();
}

@Override
protected void onPause() {
mapView.onPause();
super.onPause();
}

private void initView() {
findViewById(R.id.btn_back).setOnClickListener(this);
tvAddress = (TextView) findViewById(R.id.tv_address);
tvAddress.setText("正在获取位置");
tvConfirm = (TextView) findViewById(R.id.tv_confirm);
tvConfirm.setOnClickListener(this);

mapView = (MapView) findViewById(R.id.map_view);
baiduMap = mapView.getMap();
baiduMap.setMapType(BaiduMap.MAP_TYPE_NORMAL);
baiduMap.setMyLocationEnabled(true);

//定位
locationClient = new LocationClient(getApplicationContext());
locationClient.registerLocationListener(myLitenner);//注册监听函数

LocationClientOption option = new LocationClientOption();
option.setOpenGps(true);//打开GPS
option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy);//设置定位模式
option.setCoorType("bd09ll");//返回的定位结果是百度经纬度,默认值是gcj02
option.setScanSpan(5000);//设置发起定位请求的时间间隔为5000ms
option.setIsNeedAddress(true);//返回的定位结果包含地址信息
option.setNeedDeviceDirect(true);// 返回的定位信息包含手机的机头方向
locationClient.setLocOption(option);

baiduMap.setOnMapStatusChangeListener(mapChangeListener);
locationClient.start();
}

private OnGetGeoCoderResultListener geoCodeListener = new OnGetGeoCoderResultListener() {
@Override
public void onGetGeoCodeResult(GeoCodeResult geoCodeResult) {

}

@Override
public void onGetReverseGeoCodeResult(ReverseGeoCodeResult reverseGeoCodeResult) {

if (reverseGeoCodeResult != null) {
tvAddress.setText("当前位置:" + reverseGeoCodeResult.getAddress());
address = reverseGeoCodeResult.getAddress();
} else {
tvAddress.setText("暂无地址");
}
}
};

//根据 Laglng 来获取位置信息
private void searchAddress(LatLng latLng) {
geoCoder = GeoCoder.newInstance();
geoCoder.setOnGetGeoCodeResultListener(geoCodeListener);
ReverseGeoCodeOption codeOption = new ReverseGeoCodeOption();
codeOption.location(latLng);
geoCoder.reverseGeoCode(codeOption);
}

@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_back:
finish();
break;
case R.id.tv_confirm:
if (address != null) {
Intent intent = new Intent();
intent.putExtra("address", address);
setResult(RESULT_OK, intent);
}
finish();
break;
}
}

@Override
protected void onDestroy() {
locationClient.stop();
baiduMap.setMyLocationEnabled(false);
mapView.onDestroy();
if (geoCoder != null) {
geoCoder.destroy();
}
super.onDestroy();
}
}

布局文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:orientation="vertical">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@color/head_bg"
android:gravity="center_horizontal"
android:paddingLeft="10dp"
android:paddingRight="10dp">

<!-- 返回 -->

<LinearLayout
android:id="@+id/btn_back"
android:layout_width="50dp"
android:layout_height="fill_parent"
android:gravity="center">

<ImageView
android:layout_width="20dp"
android:layout_height="20dp"
android:src="@drawable/back" />

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="返回"
android:textColor="@color/white" />
</LinearLayout>
<!-- 页面标题 -->

<LinearLayout
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_gravity="center_vertical"
android:layout_weight="2.5"
android:gravity="center"
android:orientation="horizontal">

<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/map"
android:textColor="@color/white" />

</LinearLayout>
<!-- 小工具 -->

<LinearLayout
android:layout_width="50dp"
android:layout_height="fill_parent"
android:gravity="center">

<TextView
android:id="@+id/tv_confirm"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/border_white_jiaofeijilu"
android:paddingBottom="@dimen/dimen_3_dp"
android:paddingLeft="@dimen/dimen_5_dp"
android:paddingRight="@dimen/dimen_5_dp"
android:paddingTop="@dimen/dimen_3_dp"
android:text="确定"
android:textColor="@color/white"
android:textSize="12sp" />

</LinearLayout>
</LinearLayout>

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">

<com.baidu.mapapi.map.MapView
android:id="@+id/map_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />

<ImageView
android:layout_width="@dimen/dimen_15_dp"
android:layout_height="@dimen/dimen_15_dp"
android:layout_centerInParent="true"
android:src="@drawable/location" />

</RelativeLayout>

<TextView
android:id="@+id/tv_address"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:maxLines="1"
android:padding="10dp"
android:textColor="@color/text_black" />

</LinearLayout>

遇到的几个坑:

  • 百度的 sdk 文档真是垃圾,能不能用点心,好好写行不行。
  • option.setCoorType("bd09ll") 类型一定要写对 是 l 不是 1。因为这个问题,导致定位一直不太准确。
  • 开始想用 POI检索 来通过 Laglng 来获取到位置信息,但是不知道为什么一直获取不到,而且 POI检索 还需要参数 keyword 就是关键词。后来通过查阅发现使用 GeoCoderReverseGeoCodeOption 反向地理编码来获取位置信息。
  • 因为百度地图需要注册时需要用到 SHA1 ,所以每次都要打签名包,然后我并不知道AS要怎么配置才能生成 debug 签名包,很尴尬,所以每次都要生成签名包然后拷到手机上,很麻烦。

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×

keyboard_arrow_up 回到顶端