Flutter地理位置排序插件geo_sort的使用
Flutter地理位置排序插件geo_sort的使用
Geosort 是一个 Dart 包,用于根据距离参考位置来对地理位置列表进行排序。它提供了计算两个地理坐标之间距离的方法(使用逆向半正矢公式),以及对位置列表按距离进行排序的功能。Geosort 对于需要计算和排序地理位置的应用程序非常有用,例如地图应用、地理位置服务和兴趣点管理。
安装
此包旨在支持 Dart 项目的开发。通常将其添加到 dependencies
下,在您的 pubspec.yaml
文件中:
dependencies:
geo_sort: ^0.1.0
您可以通过命令行安装包:
pub get
使用
首先,您需要创建一个实现 HasLocation
接口的类,如下所示:
class TestLocation implements HasLocation {
final int id;
final String city;
[@override](/user/override)
final double latitude;
[@override](/user/override)
final double longitude;
TestLocation({
required this.id,
required this.city,
required this.latitude,
required this.longitude,
});
}
然后,创建一个 TestLocation
对象列表:
final List<TestLocation> locations = [
TestLocation(id: 1, city: 'Rome', latitude: 41.9028, longitude: 12.4964),
TestLocation(id: 2, city: 'Milan', latitude: 45.4642, longitude: 9.1900),
TestLocation(id: 3, city: 'Naples', latitude: 40.8518, longitude: 14.2681),
];
现在,您可以使用 GeoSort
类来根据距离从参考位置对位置列表进行排序。以下是具体方法:
final sortedLocations = GeoSort.sortByLatLong(
items: locations,
latitude: 41.9028,
longitude: 12.4964,
ascending: false,
);
这将按照坐标 (41.9028, 12.4964)
的距离从近到远对位置列表进行排序。
参数解释
items
: 需要排序的位置列表。latitude
和longitude
: 参考位置的坐标。ascending
: 指示是否按升序(默认)或降序进行排序。maxDistance
: 定义在排序列表内包含项的最大距离(以千米为单位)。maxElements
: 指定在排序列表内包含的最大元素数量。
这些参数提供了额外的控制,可以根据用户偏好或特定应用程序需求来选择和排序列表中的项。
完整代码
import 'package:geo_sort/src/extensions/extensions.dart';
import 'package:geo_sort/src/utils/utils.dart';
class TestLocation implements HasLocation {
final int id;
final String city;
[@override](/user/override)
final double latitude;
[@override](/user/override)
final double longitude;
TestLocation({
required this.id,
required this.city,
required this.latitude,
required this.longitude,
});
}
void main() {
// 创建 TestLocation 实例列表
final List<TestLocation> locations = [
TestLocation(id: 1, city: 'Rome', latitude: 41.9028, longitude: 12.4964),
TestLocation(id: 2, city: 'Milan', latitude: 45.4642, longitude: 9.1900),
TestLocation(id: 3, city: 'Naples', latitude: 40.8518, longitude: 14.2681),
];
// 参考坐标
final double referenceLat = 41.9028;
final double referenceLong = 12.4964;
// 按距离排序
final sortedLocations = GeoSort.sortByLatLong<TestLocation>(
items: locations,
latitude: referenceLat,
longitude: referenceLong,
ascending: false,
);
// 打印排序后的列表
print('Sorted Locations:');
sortedLocations.forEach((location) {
print('${location.city}: ${location.latitude}, ${location.longitude}');
});
}
示例应用
以下是一个完整的 Flutter 应用示例,演示如何使用 GeoSort
来对地点列表进行排序:
import 'dart:convert';
/// 一个演示 GeoSort 使用的示例应用,用于根据参考位置的距离对地点列表进行排序。
import 'package:flutter/material.dart';
import 'package:geo_sort/geo_sort.dart';
void main() {
runApp(const SortApp());
}
class SortApp extends StatelessWidget {
const SortApp({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: '地点列表顺序排序',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const LocationListScreen(),
);
}
}
class LocationListScreen extends StatefulWidget {
const LocationListScreen({super.key});
[@override](/user/override)
State<LocationListScreen> createState() => _LocationListScreenState();
}
class _LocationListScreenState extends State<LocationListScreen> {
// 意大利地点列表及其经纬度
List<Location> _italianLocations = [
Location(
id: 1,
name: 'Roma',
city: '罗马',
latitude: 41.9028,
longitude: 12.4964),
Location(
id: 2,
name: 'Milano',
city: '米兰',
latitude: 45.4642,
longitude: 9.1900),
Location(
id: 3,
name: 'Napoli',
city: '那不勒斯',
latitude: 40.8518,
longitude: 14.2681),
Location(
id: 4,
name: 'Torino',
city: '都灵',
latitude: 45.0703,
longitude: 7.6869),
Location(
id: 5,
name: 'Palermo',
city: '巴勒莫',
latitude: 38.1157,
longitude: 13.3615),
Location(
id: 6,
name: 'Genova',
city: '热那亚',
latitude: 44.4056,
longitude: 8.9463),
Location(
id: 7,
name: 'Bologna',
city: '博洛尼亚',
latitude: 44.4949,
longitude: 11.3426),
Location(
id: 8,
name: 'Firenze',
city: '佛罗伦萨',
latitude: 43.7696,
longitude: 11.2558),
Location(
id: 9,
name: 'Bari',
city: '巴里',
latitude: 41.1171,
longitude: 16.8719),
Location(
id: 10,
name: 'Catania',
city: '卡塔尼亚',
latitude: 37.5079,
longitude: 15.0830),
Location(
id: 11,
name: 'Venezia',
city: '威尼斯',
latitude: 45.4408,
longitude: 12.3155),
Location(
id: 12,
name: 'Verona',
city: '维罗纳',
latitude: 45.4384,
longitude: 10.9916),
Location(
id: 13,
name: 'Messina',
city: '墨西拿',
latitude: 38.1938,
longitude: 15.5540),
Location(
id: 14,
name: 'Padova',
city: '帕多瓦',
latitude: 45.4064,
longitude: 11.8768),
Location(
id: 15,
name: 'Trieste',
city: '的里雅斯特',
latitude: 45.6495,
longitude: 13.7768),
Location(
id: 16,
name: 'Taranto',
city: '塔兰托',
latitude: 40.4786,
longitude: 17.2394),
Location(
id: 17,
name: 'Brescia',
city: '布雷西亚',
latitude: 45.5398,
longitude: 10.2227),
Location(
id: 18,
name: 'Reggio di Calabria',
city: '卡拉布里亚雷焦',
latitude: 38.1147,
longitude: 15.6500),
Location(
id: 19,
name: 'Modena',
city: '摩德纳',
latitude: 44.6471,
longitude: 10.9252),
Location(
id: 20,
name: 'Prato',
city: '普拉托',
latitude: 43.8777,
longitude: 11.1027),
];
final TextEditingController _latitudeController = TextEditingController(text: '37.074153');
final TextEditingController _longitudeController = TextEditingController(text: '14.240354');
bool _ascending = true;
void _sortLocations(bool ascending) {
final latitude = _latitudeController.text.isNotEmpty
? double.parse(_latitudeController.text)
: 41.9028;
final longitude = _longitudeController.text.isNotEmpty
? double.parse(_longitudeController.text)
: 12.4964;
setState(() {
_ascending = ascending;
_italianLocations = GeoSort.sortByLatLong<Location>(
items: _italianLocations,
latitude: latitude,
longitude: longitude,
ascending: _ascending,
);
});
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('地点列表'),
),
body: SafeArea(
child: Column(
children: [
Expanded(
child: ListView.builder(
itemCount: _italianLocations.length,
itemBuilder: (context, index) {
final location = _italianLocations[index];
return ListTile(
title: Text(location.name),
subtitle: Text(location.city),
// 如有必要,添加其他信息
);
},
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton(
onPressed: () => _sortLocations(true),
child: const Text('升序排序'),
),
ElevatedButton(
onPressed: () => _sortLocations(false),
child: const Text('降序排序'),
),
],
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Expanded(
child: TextField(
controller: _latitudeController,
decoration: const InputDecoration(labelText: '纬度'),
keyboardType: const TextInputType.numberWithOptions(decimal: true),
),
),
const SizedBox(width: 8.0),
Expanded(
child: TextField(
controller: _longitudeController,
decoration: const InputDecoration(labelText: '经度'),
keyboardType: const TextInputType.numberWithOptions(decimal: true),
),
),
],
),
),
ElevatedButton(
onPressed: () {
// 处理添加新位置的操作
},
child: const Text('添加位置'),
),
],
),
),
);
}
}
/// 表示带有纬度和经度的地点的模型类。
///
/// 此类应实现 [HasLocation] 接口,以确保包含纬度和经度属性。
class Location implements HasLocation {
final int id;
final String name;
final String city;
[@override](/user/override)
final double latitude;
[@override](/user/override)
final double longitude;
Location({
required this.id,
required this.name,
required this.city,
required this.latitude,
required this.longitude,
});
Map<String, dynamic> toMap() {
return {
'id': id,
'name': name,
'city': city,
'latitude': latitude,
'longitude': longitude,
};
}
factory Location.fromMap(Map<String, dynamic> map) {
return Location(
id: map['id']?.toInt() ?? 0,
name: map['name'] ?? '',
city: map['city'] ?? '',
latitude: map['latitude']?.toDouble() ?? 0.0,
longitude: map['longitude']?.toDouble() ?? 0.0,
);
}
String toJson() => json.encode(toMap());
factory Location.fromJson(String source) => Location.fromMap(json.decode(source));
[@override](/user/override)
String toString() {
return 'Location(id: $id, name: $name, city: $city, latitude: $latitude, longitude: $longitude)';
}
}
更多关于Flutter地理位置排序插件geo_sort的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
1 回复