[鸿蒙2025领航者闯关]HarmonyOS中开发高德地图第十篇:综合实战案例
本篇教程将整合前面所学的所有功能,实现一个完整的「周边生活服务」应用。我们将实现一个「周边生活服务」应用,包含以下功能:创建文件 :3. 配置路由页面更新 :4. 创建教程首页更新 :5. 最佳实践总结5.1 代码组织将地图相关逻辑封装成独立的Service使用常量管理API Key和配置合理划分页面和组件5.2 性能优化及时清理不需要的覆盖物控制标记数量,避免过多标记影响性能使用异步搜索方法5.
·
第十篇:综合实战案例
本篇教程将整合前面所学的所有功能,实现一个完整的「周边生活服务」应用。
学习目标
- 整合地图显示、定位、搜索、路线规划等功能
- 实现完整的业务流程
- 学习最佳实践和代码组织方式
1. 应用功能概述
我们将实现一个「周边生活服务」应用,包含以下功能:
- 📍 显示当前位置
- 🔍 搜索周边商家(餐厅、超市、银行等)
- 📋 展示搜索结果列表
- 🗺️ 在地图上标记搜索结果
- 🚗 规划到选中商家的路线
- 📝 显示商家详细信息
2. 完整代码实现
创建文件 entry/src/main/ets/pages/Demo09_CompleteApp.ets:
import {
AMap,
MapView,
MapViewComponent,
MapViewManager,
MapViewCreateCallback,
CameraUpdateFactory,
LatLng,
LatLngBounds,
Marker,
MarkerOptions,
Polyline,
PolylineOptions,
BitmapDescriptorFactory,
MyLocationStyle,
OnLocationChangedListener
} from '@amap/amap_lbs_map3d';
import {
PoiSearch,
PoiQuery,
PoiResult,
PoiItem,
OnPoiSearchListener,
PoiSearchBound,
RouteSearch,
DriveRouteQuery,
WalkRouteQuery,
DriveRouteResult,
WalkRouteResult,
BusRouteResult,
RideRouteResult,
FromAndTo,
LatLonPoint,
OnRouteSearchListener,
AMapException,
DrivePath,
WalkPath,
DriveStep,
WalkStep,
GeocodeSearch,
ReGeocodeQuery,
ReGeocodeAddress
} from '@amap/amap_lbs_search';
import { abilityAccessCtrl, bundleManager, common, Permissions } from '@kit.AbilityKit';
import { geoLocationManager } from '@kit.LocationKit';
import { promptAction } from '@kit.ArkUI';
const MAP_VIEW_NAME = 'CompleteApp';
/**
* 商家分类
*/
interface Category {
name: string;
icon: string;
keyword: string;
}
/**
* 路线类型
*/
type RouteMode = 'drive' | 'walk';
@Entry
@Component
struct Demo09_CompleteApp {
private mapView: MapView | undefined = undefined;
private aMap: AMap | undefined = undefined;
private poiSearch: PoiSearch | undefined = undefined;
private routeSearch: RouteSearch | undefined = undefined;
private geocodeSearch: GeocodeSearch | undefined = undefined;
// 覆盖物
private poiMarkers: Marker[] = [];
private myLocationMarker: Marker | undefined = undefined;
private routePolyline: Polyline | undefined = undefined;
// 状态
@State isMapReady: boolean = false;
@State hasPermission: boolean = false;
@State isSearching: boolean = false;
@State isRouting: boolean = false;
// 位置
@State currentLocation: LatLng | undefined = undefined;
@State currentAddress: string = '定位中...';
// 搜索
@State selectedCategory: string = '餐厅';
@State searchRadius: number = 2000;
@State poiList: PoiItem[] = [];
@State selectedPoi: PoiItem | undefined = undefined;
// 路线
@State routeMode: RouteMode = 'drive';
@State routeInfo: string = '';
@State showRoutePanel: boolean = false;
// 商家分类
private categories: Category[] = [
{ name: '餐厅', icon: '🍜', keyword: '餐厅' },
{ name: '超市', icon: '🛒', keyword: '超市' },
{ name: '银行', icon: '🏦', keyword: '银行' },
{ name: '药店', icon: '💊', keyword: '药店' },
{ name: '加油站', icon: '⛽', keyword: '加油站' },
{ name: '停车场', icon: '🅿️', keyword: '停车场' }
];
/**
* POI搜索回调
*/
private poiSearchListener: OnPoiSearchListener = {
onPoiSearched: (result: PoiResult | undefined, errorCode: number) => {
this.isSearching = false;
if (errorCode === AMapException.CODE_AMAP_SUCCESS && result) {
const pois = result.getPois();
if (pois && pois.length > 0) {
this.poiList = pois as PoiItem[];
this.addPoiMarkersToMap();
promptAction.showToast({ message: `找到 ${pois.length} 个${this.selectedCategory}` });
} else {
this.poiList = [];
promptAction.showToast({ message: '附近没有找到相关商家' });
}
} else {
promptAction.showToast({ message: '搜索失败,请重试' });
}
},
onPoiItemSearched: () => {}
};
/**
* 路线搜索回调
*/
private routeSearchListener: OnRouteSearchListener = {
onDriveRouteSearched: (result: DriveRouteResult | undefined, errorCode: number) => {
this.isRouting = false;
if (errorCode === AMapException.CODE_AMAP_SUCCESS && result) {
const paths = result.getPaths();
if (paths && paths.length > 0) {
const path = paths[0] as DrivePath;
this.showRoute(path.getSteps(), path.getDistance(), path.getDuration(), '驾车');
}
} else {
this.routeInfo = '路线规划失败';
}
},
onWalkRouteSearched: (result: WalkRouteResult | undefined, errorCode: number) => {
this.isRouting = false;
if (errorCode === AMapException.CODE_AMAP_SUCCESS && result) {
const paths = result.getPaths();
if (paths && paths.length > 0) {
const path = paths[0] as WalkPath;
this.showRoute(path.getSteps(), path.getDistance(), path.getDuration(), '步行');
}
} else {
this.routeInfo = '路线规划失败';
}
},
onBusRouteSearched: (result: BusRouteResult | undefined, errorCode: number) => {},
onRideRouteSearched: (result: RideRouteResult | undefined, errorCode: number) => {}
};
private mapViewCreateCallback: MapViewCreateCallback =
(mapview: MapView | undefined, mapViewName: string | undefined) => {
if (!mapview || mapViewName !== MAP_VIEW_NAME) return;
this.mapView = mapview;
this.mapView.onCreate();
this.mapView.getMapAsync((map: AMap) => {
this.aMap = map;
this.isMapReady = true;
// 默认位置(北京)
const defaultLocation = new LatLng(39.909187, 116.397451);
map.moveCamera(CameraUpdateFactory.newLatLngZoom(defaultLocation, 15));
// 启用控件
map.getUiSettings()?.setZoomControlsEnabled(true);
map.getUiSettings()?.setScaleControlsEnabled(true);
// 请求定位权限
this.requestLocationPermission();
// 地图点击关闭详情面板
map.setOnMapClickListener(() => {
this.selectedPoi = undefined;
this.showRoutePanel = false;
});
});
};
/**
* 请求定位权限
*/
private async requestLocationPermission(): Promise<void> {
try {
const permissions: Permissions[] = [
'ohos.permission.APPROXIMATELY_LOCATION',
'ohos.permission.LOCATION'
];
const context = getContext(this) as common.UIAbilityContext;
const atManager = abilityAccessCtrl.createAtManager();
const result = await atManager.requestPermissionsFromUser(context, permissions);
if (result.authResults.every(status => status === 0)) {
this.hasPermission = true;
this.startLocation();
} else {
this.currentAddress = '未授权定位';
// 使用默认位置
this.currentLocation = new LatLng(39.909187, 116.397451);
}
} catch (error) {
console.error('[App] Permission request failed:', error);
}
}
/**
* 开始定位
*/
private startLocation(): void {
const request: geoLocationManager.CurrentLocationRequest = {
priority: geoLocationManager.LocationRequestPriority.FIRST_FIX,
scenario: geoLocationManager.LocationRequestScenario.UNSET
};
geoLocationManager.getCurrentLocation(request)
.then((location) => {
this.currentLocation = new LatLng(location.latitude, location.longitude);
// 使用逆地理编码获取城市名称
this.getAddressFromLocation(location.latitude, location.longitude);
// 移动地图到当前位置
if (this.aMap) {
this.aMap.animateCamera(
CameraUpdateFactory.newLatLngZoom(this.currentLocation, 15),
500
);
}
// 添加定位标记
this.addMyLocationMarker();
})
.catch((error) => {
console.error('[App] Location failed:', error);
this.currentAddress = '定位失败';
// 使用默认位置
this.currentLocation = new LatLng(39.909187, 116.397451);
this.getAddressFromLocation(39.909187, 116.397451);
});
}
/**
* 逆地理编码获取地址
* 将坐标转换为城市、区域、街道等地址信息
*/
private async getAddressFromLocation(lat: number, lng: number): Promise<void> {
if (!this.geocodeSearch) return;
try {
const point: LatLonPoint = new LatLonPoint(lat, lng);
const query: ReGeocodeQuery = new ReGeocodeQuery(point, 200, GeocodeSearch.AMAP);
// getFromLocation 直接返回 ReGeocodeAddress
const address: ReGeocodeAddress | undefined = await this.geocodeSearch.getFromLocation(query);
if (address) {
// 获取城市和区域信息
const city: string = address.getCity() || '';
const district: string = address.getDistrict() || '';
const township: string = address.getTownship() || '';
if (city) {
this.currentAddress = `${city} ${district} ${township}`.trim();
} else {
// 如果没有城市信息,使用格式化地址
this.currentAddress = address.getFormatAddress() || '未知位置';
}
}
} catch (error) {
this.currentAddress = '获取地址失败';
}
}
/**
* 添加定位标记
*/
private addMyLocationMarker(): void {
if (!this.aMap || !this.currentLocation) return;
if (this.myLocationMarker) {
this.myLocationMarker.remove();
}
const options = new MarkerOptions();
options.setPosition(this.currentLocation);
options.setTitle('我的位置');
options.setIcon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE));
options.setAnchor(0.5, 1.0);
options.setZIndex(100);
this.myLocationMarker = this.aMap.addMarker(options);
}
/**
* 搜索周边商家
* 使用 PoiSearchBound.createCircleSearchBound 创建圆形搜索范围
*/
private searchNearby(category: Category): void {
if (!this.poiSearch || !this.currentLocation) {
promptAction.showToast({ message: '请先获取位置' });
return;
}
this.selectedCategory = category.name;
this.isSearching = true;
this.selectedPoi = undefined;
this.showRoutePanel = false;
this.clearRoute();
// 创建当前位置的坐标点
const centerPoint: LatLonPoint = new LatLonPoint(
this.currentLocation.latitude,
this.currentLocation.longitude
);
// 使用当前位置进行周边搜索,不限定城市
const query: PoiQuery = new PoiQuery(category.keyword, '', '');
query.setPageSize(20);
query.setPageNum(0);
// 创建圆形搜索范围:以当前位置为中心,半径3000米
const searchBound: PoiSearchBound = PoiSearchBound.createCircleSearchBound(centerPoint, 3000);
this.poiSearch.setQuery(query);
this.poiSearch.setBound(searchBound);
this.poiSearch.searchPOIAsyn();
}
/**
* 添加POI标记到地图
*/
private addPoiMarkersToMap(): void {
if (!this.aMap) return;
// 清除旧标记
this.clearPoiMarkers();
for (let i = 0; i < this.poiList.length; i++) {
const poi = this.poiList[i];
const point = poi.getLatLonPoint();
if (point) {
const options = new MarkerOptions();
options.setPosition(new LatLng(point.getLatitude(), point.getLongitude()));
options.setTitle(poi.getTitle() || '');
options.setSnippet(poi.getSnippet() || '');
// 前3个用红色,其他用蓝色
const hue = i < 3 ? BitmapDescriptorFactory.HUE_RED : BitmapDescriptorFactory.HUE_BLUE;
options.setIcon(BitmapDescriptorFactory.defaultMarker(hue));
options.setAnchor(0.5, 1.0);
options.setZIndex(10);
const marker = this.aMap.addMarker(options);
if (marker) {
this.poiMarkers.push(marker);
}
}
}
// 设置标记点击事件
this.aMap.setOnMarkerClickListener((marker: Marker): boolean => {
const position = marker.getPosition();
// 查找对应的POI
for (const poi of this.poiList) {
const point = poi.getLatLonPoint();
if (point &&
Math.abs(position.latitude - point.getLatitude()) < 0.0001 &&
Math.abs(position.longitude - point.getLongitude()) < 0.0001) {
this.selectPoi(poi);
break;
}
}
return true;
});
}
/**
* 清除POI标记
*/
private clearPoiMarkers(): void {
for (const marker of this.poiMarkers) {
marker.remove();
}
this.poiMarkers = [];
}
/**
* 选择POI
*/
private selectPoi(poi: PoiItem): void {
this.selectedPoi = poi;
this.showRoutePanel = false;
this.clearRoute();
// 移动地图到POI位置
const point = poi.getLatLonPoint();
if (point && this.aMap) {
this.aMap.animateCamera(
CameraUpdateFactory.newLatLng(new LatLng(point.getLatitude(), point.getLongitude())),
300
);
}
}
/**
* 规划路线到选中的POI
*/
private planRoute(): void {
if (!this.routeSearch || !this.currentLocation || !this.selectedPoi) return;
const poiPoint = this.selectedPoi.getLatLonPoint();
if (!poiPoint) return;
this.isRouting = true;
this.showRoutePanel = true;
this.routeInfo = '正在规划路线...';
const fromAndTo = new FromAndTo(
new LatLonPoint(this.currentLocation.latitude, this.currentLocation.longitude),
poiPoint
);
if (this.routeMode === 'drive') {
const query = new DriveRouteQuery(fromAndTo, RouteSearch.DrivingDefault, undefined, undefined, '');
this.routeSearch.calculateDriveRouteAsyn(query);
} else {
const query = new WalkRouteQuery(fromAndTo);
this.routeSearch.calculateWalkRouteAsyn(query);
}
}
/**
* 显示路线
*/
private showRoute(steps: Object[] | undefined, distance: number, duration: number, mode: string): void {
if (!this.aMap || !steps) return;
this.clearRoute();
// 收集坐标点
const points: LatLng[] = [];
for (const step of steps) {
const polyline = (step as DriveStep).getPolyline?.() || (step as WalkStep).getPolyline?.();
if (polyline) {
for (const point of polyline) {
points.push(new LatLng(point.getLatitude(), point.getLongitude()));
}
}
}
if (points.length > 0) {
// 绘制路线
const options = new PolylineOptions();
options.setPoints(points);
options.setWidth(10);
options.setColor(this.routeMode === 'drive' ? 0xFF4CAF50 : 0xFF2196F3);
this.routePolyline = this.aMap.addPolyline(options);
// 更新路线信息
this.routeInfo = `${mode}路线\n距离: ${this.formatDistance(distance)}\n预计: ${this.formatDuration(duration)}`;
// 调整视野
this.fitRouteBounds(points);
}
}
/**
* 清除路线
*/
private clearRoute(): void {
if (this.routePolyline) {
this.routePolyline.remove();
this.routePolyline = undefined;
}
this.routeInfo = '';
}
/**
* 调整视野以显示路线
*/
private fitRouteBounds(points: LatLng[]): void {
if (!this.aMap || points.length === 0) return;
let minLat = 90, maxLat = -90, minLng = 180, maxLng = -180;
for (const point of points) {
minLat = Math.min(minLat, point.latitude);
maxLat = Math.max(maxLat, point.latitude);
minLng = Math.min(minLng, point.longitude);
maxLng = Math.max(maxLng, point.longitude);
}
const bounds = new LatLngBounds(
new LatLng(minLat, minLng),
new LatLng(maxLat, maxLng)
);
this.aMap.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 80), 500);
}
/**
* 格式化距离
*/
private formatDistance(meters: number): string {
return meters < 1000 ? `${meters}米` : `${(meters / 1000).toFixed(1)}公里`;
}
/**
* 格式化时间
*/
private formatDuration(seconds: number): string {
const minutes = Math.floor(seconds / 60);
return minutes < 60 ? `${minutes}分钟` : `${Math.floor(minutes / 60)}小时${minutes % 60}分钟`;
}
aboutToAppear(): void {
MapViewManager.getInstance()
.registerMapViewCreatedCallback(this.mapViewCreateCallback);
const context = getContext(this);
this.poiSearch = new PoiSearch(context, undefined);
this.poiSearch.setOnPoiSearchListener(this.poiSearchListener);
this.routeSearch = new RouteSearch(context);
this.routeSearch.setRouteSearchListener(this.routeSearchListener);
// 初始化逆地理编码
this.geocodeSearch = new GeocodeSearch(context);
}
aboutToDisappear(): void {
this.clearPoiMarkers();
this.clearRoute();
MapViewManager.getInstance()
.unregisterMapViewCreatedCallback(this.mapViewCreateCallback);
if (this.mapView) {
this.mapView.onDestroy();
this.mapView = undefined;
this.aMap = undefined;
}
}
build() {
Stack() {
Column() {
// 顶部搜索栏
Column() {
// 标题和定位信息
Row() {
Text('📍')
.fontSize(18)
Text(this.currentAddress)
.fontSize(14)
.fontColor('#333')
.layoutWeight(1)
.margin({ left: 8 })
.maxLines(1)
Button('重新定位')
.fontSize(12)
.height(30)
.backgroundColor('#2196F3')
.onClick(() => this.startLocation())
}
.width('100%')
.padding({ bottom: 10 })
// 分类按钮
Scroll() {
Row() {
ForEach(this.categories, (cat: Category) => {
Column() {
Text(cat.icon)
.fontSize(24)
Text(cat.name)
.fontSize(11)
.fontColor(this.selectedCategory === cat.name ? '#2196F3' : '#666')
.margin({ top: 4 })
}
.width(60)
.height(60)
.backgroundColor(this.selectedCategory === cat.name ? '#E3F2FD' : '#f5f5f5')
.borderRadius(8)
.justifyContent(FlexAlign.Center)
.margin({ right: 8 })
.onClick(() => this.searchNearby(cat))
})
}
}
.scrollable(ScrollDirection.Horizontal)
.scrollBar(BarState.Off)
}
.width('100%')
.padding(12)
.backgroundColor(Color.White)
// 地图
Stack() {
MapViewComponent({ mapViewName: MAP_VIEW_NAME })
.width('100%')
.height('100%')
// 加载指示器
if (this.isSearching) {
Column() {
LoadingProgress()
.width(40)
.height(40)
Text('搜索中...')
.fontSize(12)
.margin({ top: 8 })
}
.width('100%')
.height('100%')
.backgroundColor('rgba(255,255,255,0.7)')
.justifyContent(FlexAlign.Center)
}
}
.layoutWeight(1)
// 底部结果列表
if (this.poiList.length > 0 && !this.selectedPoi) {
Column() {
Text(`${this.selectedCategory} (${this.poiList.length}个结果)`)
.fontSize(14)
.fontWeight(FontWeight.Bold)
.padding(10)
.width('100%')
.backgroundColor('#f5f5f5')
List() {
ForEach(this.poiList, (poi: PoiItem, index: number) => {
ListItem() {
Row() {
Text(`${index + 1}`)
.fontSize(12)
.fontColor(Color.White)
.width(24)
.height(24)
.textAlign(TextAlign.Center)
.backgroundColor(index < 3 ? '#F44336' : '#2196F3')
.borderRadius(12)
Column() {
Text(poi.getTitle() || '未知商家')
.fontSize(14)
.fontColor('#333')
.maxLines(1)
Row() {
Text(poi.getSnippet() || '')
.fontSize(11)
.fontColor('#999')
.maxLines(1)
.layoutWeight(1)
if (poi.getDistance() > 0) {
Text(this.formatDistance(poi.getDistance()))
.fontSize(11)
.fontColor('#2196F3')
}
}
.width('100%')
.margin({ top: 2 })
}
.layoutWeight(1)
.alignItems(HorizontalAlign.Start)
.margin({ left: 10 })
}
.width('100%')
.padding(12)
}
.onClick(() => this.selectPoi(poi))
})
}
.height(150)
.divider({ strokeWidth: 1, color: '#eee' })
}
.backgroundColor(Color.White)
}
}
.width('100%')
.height('100%')
// 商家详情面板
if (this.selectedPoi) {
Column() {
// 商家信息
Column() {
Row() {
Text(this.selectedPoi.getTitle() || '未知商家')
.fontSize(16)
.fontWeight(FontWeight.Bold)
.layoutWeight(1)
Text('✕')
.fontSize(20)
.fontColor('#999')
.onClick(() => {
this.selectedPoi = undefined;
this.showRoutePanel = false;
this.clearRoute();
})
}
.width('100%')
Text(this.selectedPoi.getSnippet() || '')
.fontSize(13)
.fontColor('#666')
.margin({ top: 8 })
.width('100%')
if (this.selectedPoi.getTel()) {
Text(`📞 ${this.selectedPoi.getTel()}`)
.fontSize(13)
.fontColor('#2196F3')
.margin({ top: 4 })
}
if (this.selectedPoi.getDistance() > 0) {
Text(`📍 距您 ${this.formatDistance(this.selectedPoi.getDistance())}`)
.fontSize(13)
.fontColor('#666')
.margin({ top: 4 })
}
}
.padding(16)
.width('100%')
.alignItems(HorizontalAlign.Start)
// 路线规划
Column() {
Row() {
Button('🚗 驾车')
.fontSize(13)
.height(36)
.layoutWeight(1)
.backgroundColor(this.routeMode === 'drive' ? '#4CAF50' : '#e0e0e0')
.fontColor(this.routeMode === 'drive' ? Color.White : '#333')
.margin({ right: 8 })
.onClick(() => { this.routeMode = 'drive'; })
Button('🚶 步行')
.fontSize(13)
.height(36)
.layoutWeight(1)
.backgroundColor(this.routeMode === 'walk' ? '#2196F3' : '#e0e0e0')
.fontColor(this.routeMode === 'walk' ? Color.White : '#333')
.onClick(() => { this.routeMode = 'walk'; })
}
.width('100%')
Button(this.isRouting ? '规划中...' : '开始导航')
.width('100%')
.height(44)
.margin({ top: 12 })
.backgroundColor('#FF5722')
.enabled(!this.isRouting)
.onClick(() => this.planRoute())
// 路线信息
if (this.showRoutePanel && this.routeInfo) {
Text(this.routeInfo)
.fontSize(13)
.fontColor('#333')
.margin({ top: 12 })
.padding(10)
.width('100%')
.backgroundColor('#f5f5f5')
.borderRadius(8)
}
}
.padding(16)
.width('100%')
.backgroundColor('#fafafa')
}
.width('100%')
.backgroundColor(Color.White)
.borderRadius({ topLeft: 16, topRight: 16 })
.position({ bottom: 0 })
.shadow({ radius: 10, color: 'rgba(0,0,0,0.1)' })
}
}
.width('100%')
.height('100%')
}
}
3. 配置路由页面
更新 entry/src/main/resources/base/profile/main_pages.json:
{
"src": [
"pages/Index",
"pages/Demo01_BasicMap",
"pages/Demo02_MapControl",
"pages/Demo03_Marker",
"pages/Demo04_Location",
"pages/Demo05_PoiSearch",
"pages/Demo06_Geocode",
"pages/Demo07_Route",
"pages/Demo08_Drawing",
"pages/Demo09_CompleteApp"
]
}
4. 创建教程首页
更新 entry/src/main/ets/pages/Index.ets:
import { router } from '@kit.ArkUI';
interface DemoItem {
title: string;
subtitle: string;
page: string;
color: string;
}
@Entry
@Component
struct Index {
private demos: DemoItem[] = [
{ title: '显示地图', subtitle: '第一个地图应用', page: 'pages/Demo01_BasicMap', color: '#4CAF50' },
{ title: '地图控制', subtitle: '类型切换与UI设置', page: 'pages/Demo02_MapControl', color: '#2196F3' },
{ title: '地图标记', subtitle: 'Marker功能演示', page: 'pages/Demo03_Marker', color: '#FF5722' },
{ title: '定位功能', subtitle: '定位蓝点显示', page: 'pages/Demo04_Location', color: '#03A9F4' },
{ title: 'POI搜索', subtitle: '周边商家搜索', page: 'pages/Demo05_PoiSearch', color: '#9C27B0' },
{ title: '地理编码', subtitle: '地址与坐标转换', page: 'pages/Demo06_Geocode', color: '#009688' },
{ title: '路线规划', subtitle: '驾车/步行路线', page: 'pages/Demo07_Route', color: '#673AB7' },
{ title: '绑图测距', subtitle: '绘制与测量', page: 'pages/Demo08_Drawing', color: '#E91E63' },
{ title: '综合案例', subtitle: '周边生活服务', page: 'pages/Demo09_CompleteApp', color: '#FF9800' }
];
build() {
Column() {
// 标题
Text('高德地图开发教程')
.fontSize(24)
.fontWeight(FontWeight.Bold)
.margin({ top: 40, bottom: 20 })
Text('HarmonyOS 实战案例')
.fontSize(14)
.fontColor('#666')
.margin({ bottom: 30 })
// 案例列表
List() {
ForEach(this.demos, (demo: DemoItem, index: number) => {
ListItem() {
Row() {
Column() {
Text(`${index + 1}`)
.fontSize(16)
.fontWeight(FontWeight.Bold)
.fontColor(Color.White)
}
.width(40)
.height(40)
.backgroundColor(demo.color)
.borderRadius(20)
.justifyContent(FlexAlign.Center)
Column() {
Text(demo.title)
.fontSize(16)
.fontWeight(FontWeight.Medium)
.fontColor('#333')
Text(demo.subtitle)
.fontSize(12)
.fontColor('#999')
.margin({ top: 4 })
}
.layoutWeight(1)
.alignItems(HorizontalAlign.Start)
.margin({ left: 16 })
Text('>')
.fontSize(18)
.fontColor('#ccc')
}
.width('100%')
.padding(16)
.backgroundColor(Color.White)
.borderRadius(12)
.shadow({ radius: 4, color: 'rgba(0,0,0,0.05)' })
}
.margin({ bottom: 12 })
.onClick(() => {
router.pushUrl({ url: demo.page });
})
})
}
.layoutWeight(1)
.padding({ left: 16, right: 16 })
}
.width('100%')
.height('100%')
.backgroundColor('#f5f5f5')
}
}
5. 最佳实践总结
5.1 代码组织
- 将地图相关逻辑封装成独立的Service
- 使用常量管理API Key和配置
- 合理划分页面和组件
5.2 性能优化
- 及时清理不需要的覆盖物
- 控制标记数量,避免过多标记影响性能
- 使用异步搜索方法
5.3 用户体验
- 添加加载状态提示
- 合理的错误处理和提示
- 平滑的地图动画
6. 系列教程回顾
通过本系列10篇教程,我们系统学习了:
- SDK集成 - 安装配置、隐私政策
- 地图显示 - MapViewComponent、生命周期
- 地图控制 - 类型切换、UI控件、事件监听
- 地图标记 - Marker添加、自定义样式
- 定位功能 - 权限申请、定位蓝点
- POI搜索 - 关键字搜索、周边搜索
- 地理编码 - 地址坐标互转
- 路线规划 - 驾车、步行、骑行
- 绘图测距 - 折线、多边形、面积计算
- 综合案例 - 完整应用实现
恭喜完成! 🎉
你已经掌握了在鸿蒙应用中使用高德地图SDK的核心技能。现在可以开始构建你自己的地图应用了!
班级
https://developer.huawei.com/consumer/cn/training/classDetail/fd34ff9286174e848d34cde7f512ce22?type=1%3Fha_source%3Dhmosclass&ha_sourceId=89000248
源码地址
https://gitcode.com/daleishen/gaodehmjiaocheng.git
更多推荐



所有评论(0)