整个页面共使用的插件有
amap_location_fluttify
: 高德定位控件amap_search_fluttify
: 高德搜索控件permission_handler
: 权限请求azlistview
: 城市列表选择shared_preferences
: 保持历史记录(本地存储)lpinyin
: 汉字转拼音provide
: 状态管理rxdart
: 搜索插件用到其中城市列表插件,状态管理,我就不详细介绍了,如果有需要的话,可以自己去Pub上面搜一下,下载个实例工程,就知道怎么用了, 如果有什么问题,请给我留言,我看到后会给立刻您回复
引入的包
:Plugins.dart 是我封装的计算经纬度距离的方法,在下面我会给出代码的
ScreenAdapter.dart 是我之前封装的屏幕适配类,如果有需要可以看我另一篇文章
跳转地址
PublicStorage.dart 是我之前封装的本地存储类,如果有需要可以看我另一篇文章
跳转地址·
rxdart.dart不太重要,是一个函数Dart类,本来想要使用其中的循环呢,后来直接用for循环代替了,可以不用引入
search_model.dart 是我写的一个model类,主要用来转换数据用的,下面会给出代码
页面代码
import 'package:flutter/material.dart';
import 'package:amap_search_fluttify/amap_search_fluttify.dart';
import 'package:project/plugins/Plugins.dart';
import 'package:project/plugins/ScreenAdapter.dart';
import 'package:project/plugins/PublicStorage.dart';
import 'package:rxdart/rxdart.dart';
import 'package:project/pages/model/search_model.dart';
class SearchMap extends StatefulWidget {
@override
_SearchMapState createState() => _SearchMapState();
}
class _SearchMapState extends State<SearchMap> {
var city, address, latlng;
final _addressController = TextEditingController();
List<LocationSearch> _poiTitleList = [];
@override
void initState() {
super.initState();
_getLocation();
}
// 获取本地存储的定位
_getLocation() async {
var a = await PublicStorage.getHistoryList('LocationCity');
var b = await PublicStorage.getHistoryList('LocationAddress');
// var c = await PublicStorage.getHistoryList('LocationLatLng');
setState(() {
city = a[0];
address = b[0];
// latlng = c[0];
});
print(city);
print(address);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('选择地址'),
),
body: ListView(
children: <Widget>[
searchMap(),
searchList()
],
),
);
}
// 选择地址顶部搜索
Widget searchMap() {
return Container(
padding: EdgeInsets.all(ScreenAdapter.setWidth(20)),
child: Row(
children: <Widget>[
InkWell(
child: Padding(
padding: EdgeInsets.all(ScreenAdapter.setWidth(20)),
child: Row(
children: <Widget>[
Text('${city}'),
Icon(Icons.arrow_drop_down)
],
),
),
onTap: () async {
Navigator.pushNamed(context, '/city_select').then((data) {
setState(() {
city = data;
});
});
},
),
Expanded(
flex: 1,
child: Container(
decoration: BoxDecoration(
color: Color.fromRGBO(200, 200, 200, 0.3),
border: Border.all(
width: 1, color: Color.fromRGBO(150, 150, 150, 0.3))),
child: TextField(
controller: _addressController,
decoration: InputDecoration(border: InputBorder.none),
),
),
),
InkWell(
child: Padding(
padding: EdgeInsets.all(ScreenAdapter.setWidth(20)),
child: Text(
'搜索',
style: TextStyle(color: Color.fromRGBO(150, 150, 150, 0.9)),
),
),
onTap: () async {
_poiTitleList = [];
final poiList = await AmapSearch.searchKeyword(
_addressController.text,
city: city,
);
for (int i = 0; i < poiList.length; i++) {
LocationSearch bean = LocationSearch();
bean.title = await poiList[i].title;
bean.address = await poiList[i].address;
bean.latLng = await poiList[i].latLng;
bean.distance = await Plugins.getdistance(context, bean.latLng);
setState(() {
_poiTitleList.add(bean);
});
}
},
)
],
),
);
}
// 周边地理建筑列表
Widget searchList() {
return Container(
padding: EdgeInsets.all(ScreenAdapter.setWidth(20)),
color: Color.fromRGBO(200, 200, 200, 0.3),
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(ScreenAdapter.setWidth(10))),
child: Column(
children: _poiTitleList.map((val) {
return Column(
children: <Widget>[
ListTile(
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(val.title),
Text(
val.distance != null ? val.distance : 0,
// '18千米',
style: TextStyle(
fontSize: ScreenAdapter.size(25),
color: Color.fromRGBO(150, 150, 150, 0.9),
fontWeight: FontWeight.w400),
)
],
),
subtitle: Text(val.address),
),
Divider(
height: ScreenAdapter.setHeight(0.5),
)
],
);
}).toList())),
);
}
}
Plugins.dart
// 公用 的方法
import 'dart:convert';
import 'package:permission_handler/permission_handler.dart'; // 权限申请
import 'package:fluttertoast/fluttertoast.dart';
import 'package:amap_map_fluttify/amap_map_fluttify.dart'; // 获取距离
import 'package:provide/provide.dart';
import 'package:project/provide/userinformation.dart'; // 用户地理信息
import 'package:project/plugins/PublicStorage.dart';
class Plugins {
///大陆手机号码11位数,匹配格式:前三位固定格式+后8位任意数
/// 此方法中前三位格式有:
/// 13+任意数 * 15+除4的任意数 * 18+除1和4的任意数 * 17+除9的任意数 * 147
static bool isChinaPhoneLegal(String str) {
return new RegExp(
'^((13[0-9])|(15[^4])|(166)|(17[0-8])|(18[0-9])|(19[8-9])|(147,145))\\d{8}\$')
.hasMatch(str);
}
static getdistance(context, str) async {
var mylatlng = await PublicStorage.getHistoryList('LocationLatLng');
var city = await PublicStorage.getHistoryList('LocationCity');
List searchList = [];
searchList = str.toString().substring(7, str.toString().lastIndexOf('}')).split(',');
final result = await AmapService.calculateDistance(
LatLng(
double.parse(mylatlng[0][0].toString().substring(5)),
double.parse(mylatlng[0][1].toString().substring(5)),
),
LatLng(
double.parse(searchList[0].toString().substring(5)),
double.parse(searchList[1].toString().substring(5)),
),
);
return result.round().toString()+'米';
}
}
userinformation.dart
import 'package:flutter/material.dart';
import 'package:project/plugins/PublicStorage.dart';
class UserInfomation with ChangeNotifier{
var city = '';
var address = '';
var select_city = ''; // 用户经过城市选择之后选择到的城市
var latlng = null; // 经纬度
setCity(val) async{
print(val);
this.city = val;
notifyListeners();
}
setAddress(val) async {
this.address = val;
notifyListeners();
}
setLatLng(val) async {
this.latlng = val;
notifyListeners();
}
setSelectCity(val) async {
this.select_city = val;
notifyListeners();
}
}
search_model.dart
import 'package:amap_search_fluttify/amap_search_fluttify.dart';
class LocationSearch {
String title;
String address;
LatLng latLng;
String distance;
LocationSearch({this.title, this.address, this.distance, this.latLng});
LocationSearch.fromJson(Map json){
this.title = json['title'];
this.address = json['price'];
this.distance = json['distance'];
this.latLng = json['latLng'];
}
}