作为一名有多年移动开发经验的工程师,我发现自助洗车服务正在国内快速普及。车主们急需一款能帮助他们快速找到附近优质洗车点的应用。本文将详细介绍如何使用Flutter框架开发一个功能完善的自助洗车点查询应用,这个方案同样适用于华为鸿蒙系统。
Flutter的跨平台特性使其成为开发此类应用的首选:
提示:虽然本文示例使用模拟数据,但在实际项目中可轻松替换为高德地图或百度地图SDK,完全兼容国内地图服务。
我们的洗车点查询应用包含以下核心功能模块:
| 模块名称 | 功能描述 | 技术实现 |
|---|---|---|
| 地图展示 | 显示附近洗车点分布 | Flutter Map插件 |
| 列表浏览 | 按条件筛选排序洗车点 | ListView.builder |
| 详情页面 | 展示洗车点详细信息 | 自定义ScrollView |
| 预约系统 | 管理用户预约记录 | 状态管理 |
| 收藏功能 | 保存常用洗车点 | 本地存储 |
| 评价系统 | 查看和发布评价 | 数据模型 |
洗车应用的核心是数据模型,我们设计了四个主要模型类:
dart复制class CarWashStation {
final String id; // 唯一标识
final String name; // 洗车点名称
final String address; // 详细地址
final double latitude; // 纬度
final double longitude; // 经度
final double distance; // 距离(公里)
final String phone; // 联系电话
final List<String> services; // 服务类型
final Map<String, double> prices; // 价格表
final double rating; // 平均评分
final int reviewCount; // 评价数量
final String operatingHours; // 营业时间
final StationStatus status; // 营业状态
final int availableSpots; // 可用车位数
final int totalSpots; // 总车位数
bool isFavorite; // 是否收藏
}
dart复制enum StationStatus {
open, // 营业中
closed, // 已关闭
busy, // 繁忙
maintenance, // 维护中
full, // 已满
}
注意:在实际项目中,这些状态数据应该从后端API获取实时信息,确保用户看到的都是最新状态。
地图页面是应用的核心界面,我们采用Stack布局实现多层叠加效果:
dart复制Widget _buildMapPage() {
return Stack(
children: [
// 地图背景层
_buildMapBackground(),
// 顶部搜索栏
Positioned(
top: 16,
left: 16,
right: 16,
child: _buildSearchBar(),
),
// 洗车点标记
..._stations.map((station) => _buildStationMarker(station)),
// 底部信息卡片
if (_selectedStation != null)
Positioned(
bottom: 0,
child: _buildStationCard(_selectedStation!),
),
],
);
}
每个洗车点在地图上显示为一个带状态的标记:
dart复制Widget _buildStationMarker(CarWashStation station) {
final isSelected = _selectedStation?.id == station.id;
final statusColor = _getStatusColor(station.status);
return Positioned(
left: _calculateMarkerX(station.longitude),
top: _calculateMarkerY(station.latitude),
child: GestureDetector(
onTap: () => _handleStationSelect(station),
child: Container(
width: isSelected ? 50 : 36,
height: isSelected ? 50 : 36,
decoration: BoxDecoration(
color: statusColor,
shape: BoxShape.circle,
border: Border.all(color: Colors.white, width: 2),
),
child: Icon(
Icons.local_car_wash,
color: Colors.white,
size: isSelected ? 24 : 18,
),
),
),
);
}
列表页面提供更详细的信息展示和筛选功能:
dart复制Widget _buildListPage() {
return Column(
children: [
// 筛选控制栏
_buildFilterControls(),
// 洗车点列表
Expanded(
child: ListView.builder(
padding: EdgeInsets.all(16),
itemCount: _filteredStations.length,
itemBuilder: (context, index) =>
_buildStationItem(_filteredStations[index]),
),
),
],
);
}
每个列表项包含丰富的信息和操作按钮:
dart复制Widget _buildStationItem(CarWashStation station) {
return Card(
child: Padding(
padding: EdgeInsets.all(12),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// 标题行
Row(
children: [
Expanded(child: Text(station.name, style: TextStyle(fontSize: 18))),
_buildStatusBadge(station.status),
],
),
// 距离和评分
Row(
children: [
Icon(Icons.star, color: Colors.amber, size: 16),
Text('${station.rating} (${station.reviewCount})'),
SizedBox(width: 16),
Icon(Icons.location_on, size: 16),
Text('${station.distance}km'),
],
),
// 服务标签
Wrap(
spacing: 8,
children: station.services.map((service) =>
_buildServiceChip(service)).toList(),
),
// 操作按钮
Row(
children: [
Expanded(
child: OutlinedButton(
onPressed: () => _navigateToStation(station),
child: Text('导航'),
),
),
SizedBox(width: 8),
Expanded(
child: ElevatedButton(
onPressed: () => _makeReservation(station),
child: Text('预约'),
),
),
],
),
],
),
),
);
}
dart复制class Reservation {
final String id;
final String stationId;
final String userId;
final DateTime reservationTime;
final String serviceType;
final double estimatedPrice;
final ReservationStatus status;
// 其他字段...
}
enum ReservationStatus {
pending, // 待确认
confirmed, // 已确认
inProgress, // 进行中
completed, // 已完成
cancelled, // 已取消
}
使用TabBar展示不同状态的预约:
dart复制Widget _buildReservationPage() {
return DefaultTabController(
length: 2,
child: Scaffold(
appBar: TabBar(
tabs: [
Tab(text: '当前预约'),
Tab(text: '历史记录'),
],
),
body: TabBarView(
children: [
_buildActiveReservations(),
_buildHistoryReservations(),
],
),
),
);
}
虽然Flutter应用默认支持Android,但要完美适配鸿蒙系统需要注意:
AndroidManifest.xml中添加必要权限实操心得:测试发现鸿蒙系统对Flutter的支持度很高,大部分功能无需修改即可运行,主要需要替换的是那些依赖GMS的服务。
在开发过程中,我们总结了以下优化经验:
列表性能优化:
ListView.builder而非ListViewconst构造函数itemExtent提高滚动性能图片加载优化:
cached_network_image插件缓存网络图片状态管理优化:
Provider或Riverpod管理全局状态在实际开发中,我们遇到了以下典型问题:
| 问题描述 | 解决方案 | 注意事项 |
|---|---|---|
| 地图标记点击区域太小 | 增加透明点击区域 | 保持视觉大小不变 |
| 列表滚动卡顿 | 使用ListView.builder |
避免直接使用Column+ListView |
| 状态管理混乱 | 采用分层状态管理 | 区分全局和局部状态 |
| 鸿蒙定位不准 | 使用华为定位服务 | 需要申请相应权限 |
这个基础应用还可以进一步扩展:
经过实测,这个Flutter应用在华为鸿蒙设备上运行流畅,性能表现优异。开发过程中最大的收获是理解了如何设计适合国内用户习惯的UI交互模式,以及如何处理位置服务在国内的特殊情况。