import 'dart:ui';
|
|
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/material.dart';
|
import 'package:flutter_baidu_mapapi_base/flutter_baidu_mapapi_base.dart';
|
import 'package:flutter_baidu_mapapi_map/flutter_baidu_mapapi_map.dart';
|
import 'package:flutter_baidu_mapapi_search/flutter_baidu_mapapi_search.dart';
|
import 'package:location/ui/mine/advice.dart';
|
import 'package:location/ui/mine/permission.dart';
|
import 'package:location/ui/mine/settings.dart';
|
import 'package:location/ui/mine/share_to_friends.dart';
|
import 'package:location/ui/mine/try_functions.dart';
|
import 'package:location/ui/widget/button.dart';
|
import 'package:location/utils/pageutils.dart';
|
import 'package:location/utils/ui_constant.dart';
|
|
typedef OnPositionHiidenChange = void Function(bool hidden);
|
|
BMFMapController? _mapController;
|
|
class MyApp extends StatelessWidget {
|
// This widget is the root of your application.
|
@override
|
Widget build(BuildContext context) {
|
return MaterialApp(
|
title: 'Flutter Demo',
|
theme: ThemeData(
|
// This is the theme of your application.
|
//
|
// Try running your application with "flutter run". You'll see the
|
// application has a blue toolbar. Then, without quitting the app, try
|
// changing the primarySwatch below to Colors.green and then invoke
|
// "hot reload" (press "r" in the console where you ran "flutter run",
|
// or simply save your changes to "hot reload" in a Flutter IDE).
|
// Notice that the counter didn't reset back to zero; the application
|
// is not restarted.
|
primaryColor: Color.fromARGB(255, 150, 150, 150)),
|
home: LocationPage(title: ''),
|
);
|
}
|
}
|
|
class LocationPage extends StatefulWidget {
|
LocationPage({Key? key, required this.title}) : super(key: key);
|
|
// This widget is the home page of your application. It is stateful, meaning
|
// that it has a State object (defined below) that contains fields that affect
|
// how it looks.
|
|
// This class is the configuration for the state. It holds the values (in this
|
// case the title) provided by the parent (in this case the App widget) and
|
// used by the build method of the State. Fields in a Widget subclass are
|
// always marked "final".
|
|
final String title;
|
|
@override
|
_LocationPageState createState() => _LocationPageState();
|
}
|
|
class _LocationPageState extends State<LocationPage>
|
with AutomaticKeepAliveClientMixin {
|
BMFMapOptions mapOptions = BMFMapOptions(
|
showMapScaleBar: false,
|
mapType: BMFMapType.Standard,
|
center: BMFCoordinate(39.917215, 116.380341),
|
mapScaleBarPosition: BMFPoint(0, 200),
|
zoomLevel: 12,
|
mapPadding: BMFEdgeInsets(left: 30, top: 0, right: 30, bottom: 200));
|
|
@override
|
void initState() {
|
super.initState();
|
}
|
|
@override
|
Widget build(BuildContext context) {
|
return Scaffold(
|
resizeToAvoidBottomInset: false,
|
backgroundColor: Colors.white,
|
body: Stack(
|
children: [
|
getMapView(),
|
// PositionInfoPage((bool hiiden) {
|
//
|
//
|
// }),
|
LocationSearchPage(),
|
Align(
|
alignment: Alignment.bottomCenter,
|
child: getAddLocationObjectView()),
|
],
|
));
|
}
|
|
//控件阴影
|
List<BoxShadow> getViewShadow() {
|
return [
|
BoxShadow(
|
blurRadius: 6.5,
|
spreadRadius: 1,
|
color: Color(0x4D0E96FF),
|
)
|
];
|
}
|
|
//获取地图视图
|
Widget getMapView() {
|
return Container(
|
child: BMFMapWidget(
|
onBMFMapCreated: (controller) {
|
// onBMFMapCreated(controller);
|
_mapController = controller;
|
},
|
mapOptions: mapOptions,
|
),
|
);
|
}
|
|
//添加想定位的人
|
Widget getAddLocationObjectView() {
|
return Container(
|
alignment: Alignment.topCenter,
|
height: 72,
|
margin: const EdgeInsets.fromLTRB(10, 0, 10, 0),
|
padding: const EdgeInsets.fromLTRB(0, 18, 0, 0),
|
decoration: BoxDecoration(
|
color: Colors.white,
|
borderRadius: BorderRadius.only(
|
topLeft: Radius.circular(10), topRight: Radius.circular(10)),
|
boxShadow: getViewShadow()),
|
child: Flex(
|
direction: Axis.horizontal,
|
mainAxisAlignment: MainAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
children: [
|
Image.asset(
|
"assets/images/common/icon_person.png",
|
height: 17,
|
),
|
Container(
|
width: 11,
|
height: 1,
|
),
|
const Text(
|
"添加想定位的对象",
|
style: TextStyle(color: ColorConstant.theme, fontSize: 15),
|
)
|
],
|
),
|
);
|
}
|
|
@override
|
bool get wantKeepAlive => true;
|
}
|
|
//控件阴影
|
List<BoxShadow> getViewShadow() {
|
return [
|
BoxShadow(
|
blurRadius: 6.5,
|
spreadRadius: 1,
|
color: Color(0x4D0E96FF),
|
)
|
];
|
}
|
|
/*****************定位信息****************/
|
|
class PositionInfoPage extends StatefulWidget {
|
PositionInfoPage({Key? key}) : super(key: key);
|
|
@override
|
_PositionInfoPageState createState() => _PositionInfoPageState();
|
}
|
|
class _PositionInfoPageState extends State<PositionInfoPage>
|
with SingleTickerProviderStateMixin {
|
//位置信息是否隐藏
|
bool locationInfoHidden = true;
|
|
@override
|
Widget build(BuildContext context) {
|
return Container(
|
padding: const EdgeInsets.fromLTRB(10, 35, 10, 0),
|
child: Flex(direction: Axis.vertical, children: [
|
//----------搜索框--------
|
Flex(
|
direction: Axis.horizontal,
|
children: [
|
Expanded(
|
child: InkWell(
|
onTap: () {
|
print("跳转定位");
|
},
|
child: Container(
|
alignment: Alignment.center,
|
padding: EdgeInsets.fromLTRB(13, 0, 13, 0),
|
height: 45,
|
decoration: BoxDecoration(
|
color: Colors.white,
|
borderRadius: BorderRadius.circular(10),
|
boxShadow: getViewShadow()),
|
child: Flex(
|
direction: Axis.horizontal,
|
children: [
|
Image.asset(
|
"assets/images/main/icon_location_search.png",
|
height: 19,
|
),
|
Container(
|
width: 10,
|
),
|
const Expanded(
|
child: Text("地图上找位置",
|
style: TextStyle(
|
fontSize: 14,
|
color: Color(0xFFC4CDD1))))
|
],
|
),
|
))),
|
InkWell(
|
onTap: () {
|
print("sos");
|
},
|
child: Container(
|
width: 45,
|
height: 45,
|
margin: const EdgeInsets.only(left: 8.5),
|
decoration: BoxDecoration(
|
color: Colors.white,
|
boxShadow: getViewShadow(),
|
borderRadius: BorderRadius.circular(23)),
|
alignment: Alignment.center,
|
child: Image.asset(
|
"assets/images/main/icon_location_sos.png",
|
height: 35,
|
),
|
))
|
],
|
),
|
//---------个人信息与定位信息---
|
Container(
|
height: 400,
|
child: Stack(
|
children: [
|
//位置信息
|
getPositionInfoView(context),
|
//个人信息
|
Container(
|
height: 100,
|
margin: EdgeInsets.only(top: 10),
|
padding: EdgeInsets.only(left: 15, top: 8, right: 15),
|
decoration: BoxDecoration(
|
borderRadius: BorderRadius.only(
|
bottomLeft:
|
Radius.circular(locationInfoHidden ? 10 : 0),
|
bottomRight:
|
Radius.circular(locationInfoHidden ? 10 : 0),
|
topLeft: Radius.circular(10),
|
topRight: Radius.circular(10)),
|
color: Colors.white,
|
boxShadow: getViewShadow()),
|
child: Stack(
|
alignment: Alignment.topCenter,
|
children: [
|
Flex(
|
mainAxisAlignment: MainAxisAlignment.center,
|
direction: Axis.horizontal,
|
children: [
|
Image.asset(
|
"assets/images/main/icon_location_change_person.png",
|
width: 13,
|
),
|
Text(
|
" 切换实时定位人",
|
style: TextStyle(
|
color:ColorConstant.theme, fontSize: 15),
|
)
|
],
|
),
|
//个人信息
|
Flex(
|
direction: Axis.horizontal,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
children: [
|
Image.asset(
|
"assets/images/mine/icon_mine_default_portrait.png",
|
height: 33,
|
width: 33,
|
),
|
Container(
|
width: 5,
|
),
|
Expanded(
|
child: Flex(
|
direction: Axis.vertical,
|
mainAxisAlignment: MainAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
children: [
|
Text(
|
"我自己",
|
softWrap: false,
|
overflow: TextOverflow.ellipsis,
|
style: TextStyle(
|
color: Color(0xFFA0A0A0), fontSize: 18),
|
),
|
Container(
|
height: 2,
|
),
|
Text(
|
"ID:128312",
|
style: TextStyle(
|
color: Color(0xFFA0A0A0), fontSize: 12),
|
)
|
],
|
)),
|
Container(
|
width: 5,
|
),
|
Flex(
|
direction: Axis.vertical,
|
mainAxisAlignment: MainAxisAlignment.center,
|
children: [
|
MyOutlineButton(
|
"生成轨迹",
|
13,
|
height: 26,
|
width: 82,
|
fontSize: 12,
|
onClick: () {
|
print("生成轨迹");
|
},
|
),
|
Container(
|
height: 6,
|
),
|
MyOutlineButton(
|
"实时共享",
|
13,
|
height: 26,
|
width: 82,
|
fontSize: 12,
|
onClick: () {
|
print("实时共享");
|
},
|
),
|
])
|
],
|
)
|
],
|
),
|
),
|
|
//更多
|
Positioned(
|
left: MediaQuery.of(context).size.width / 2 - 10 - 70 / 2,
|
top: 80,
|
child: InkWell(
|
onTap: () {
|
setState(() {
|
locationInfoHidden = !locationInfoHidden;
|
});
|
},
|
child: Container(
|
width: 70,
|
height: 40,
|
child: Stack(
|
alignment: Alignment.bottomCenter,
|
children: [
|
Container(
|
height: 30,
|
width: 60,
|
margin: EdgeInsets.only(top: 0),
|
alignment: Alignment.center,
|
decoration: BoxDecoration(
|
color: Colors.white,
|
borderRadius:
|
BorderRadius.circular(15),
|
boxShadow: getViewShadow()),
|
),
|
Positioned(
|
top: 0,
|
child: Container(
|
height: 25,
|
width: 70,
|
alignment: Alignment.bottomCenter,
|
|
decoration: BoxDecoration(
|
color: Colors.white,
|
),
|
// child: Text(
|
// "收起",
|
// style: TextStyle(
|
// color: ColorConstant.theme,
|
// fontSize: 11),
|
// )
|
)),
|
Positioned(
|
bottom: 5,
|
child: Text(
|
locationInfoHidden ? "展开" : "收起",
|
style: TextStyle(
|
color:ColorConstant.theme,
|
fontSize: 11),
|
)),
|
]))))
|
],
|
)),
|
]));
|
}
|
|
Widget getPositionInfoView(BuildContext context) {
|
if (!locationInfoHidden) {
|
return Positioned(
|
top: 110,
|
child: ClipRRect(
|
borderRadius: const BorderRadius.only(
|
bottomLeft: Radius.circular(10),
|
bottomRight: Radius.circular(10)),
|
child: BackdropFilter(
|
filter: ImageFilter.blur(sigmaX: 10, sigmaY: 10),
|
child: Container(
|
padding: const EdgeInsets.all(18),
|
height: 120,
|
width: MediaQuery.of(context).size.width - 10 * 2,
|
color: Colors.white.withAlpha(180),
|
child: Flex(
|
mainAxisAlignment: MainAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
direction: Axis.vertical,
|
children: [
|
Container(
|
padding: const EdgeInsets.fromLTRB(12, 5, 12, 5),
|
decoration: BoxDecoration(
|
color: const Color(0xFFCACDD3),
|
borderRadius: BorderRadius.circular(20)),
|
child: const Text(
|
"2021.08.08 12:00",
|
style: TextStyle(color: Colors.white, fontSize: 10),
|
),
|
),
|
Container(
|
height: 2,
|
),
|
Flex(
|
direction: Axis.horizontal,
|
children: [
|
Image.asset(
|
"assets/images/main/icon_location_position_name.png",
|
height: 16,
|
),
|
Text(
|
" 当前位置:",
|
style: TextStyle(
|
color: Color(0xFF999999), fontSize: 12),
|
),
|
Expanded(
|
child: Text(
|
"重庆市重庆市重庆市重庆市重庆市重庆市重庆市重庆庆市重庆市重庆",
|
softWrap: false,
|
overflow: TextOverflow.ellipsis,
|
style: TextStyle(
|
color: Color(0xFFBABABA), fontSize: 12),
|
))
|
],
|
),
|
Container(
|
height: 4,
|
),
|
Container(
|
child: Flex(
|
direction: Axis.horizontal,
|
children: [
|
Image.asset(
|
"assets/images/main/icon_location_position_location.png",
|
height: 15,
|
),
|
Text(
|
" 经 纬 度:",
|
style: TextStyle(
|
color: Color(0xFF999999), fontSize: 12),
|
),
|
Expanded(
|
child: Text(
|
"N 41141.1233,W 28741.389",
|
softWrap: false,
|
overflow: TextOverflow.ellipsis,
|
style: TextStyle(
|
color: Color(0xFFBABABA), fontSize: 12),
|
))
|
],
|
)),
|
Container(
|
height: 5,
|
),
|
Flex(
|
direction: Axis.horizontal,
|
mainAxisAlignment: MainAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
children: [
|
Text(
|
"查看全部共100次定位 ",
|
style: TextStyle(
|
color: Color(0xFF9DAAB3), fontSize: 10),
|
),
|
Image.asset(
|
"assets/images/main/icon_location_position_more.png",
|
height: 10,
|
),
|
],
|
),
|
],
|
),
|
))));
|
} else {
|
return Container();
|
}
|
}
|
}
|
|
/********************POI搜索********************/
|
class LocationSearchPage extends StatefulWidget {
|
@override
|
_LocationSearchPageState createState() => _LocationSearchPageState();
|
}
|
|
class _LocationSearchPageState extends State<LocationSearchPage>
|
with SingleTickerProviderStateMixin {
|
//1-搜索页面 2-建议搜索页面 3-结果展示页面
|
int state = 1;
|
|
TextEditingController? editingController;
|
|
@override
|
void initState() {
|
super.initState();
|
editingController = TextEditingController();
|
}
|
|
@override
|
Widget build(BuildContext context) {
|
return Flex(direction: Axis.vertical, children: [
|
//搜索框
|
Container(
|
margin: EdgeInsets.fromLTRB(10, 35, 10, 11),
|
alignment: Alignment.center,
|
padding: EdgeInsets.fromLTRB(8, 0, 8, 0),
|
height: 45,
|
decoration: BoxDecoration(
|
color: Colors.white,
|
borderRadius: BorderRadius.circular(10),
|
boxShadow: getViewShadow()),
|
child: Flex(
|
direction: Axis.horizontal,
|
children: [
|
Image.asset(
|
"assets/images/map/icon_location_back.png",
|
height: 30,
|
),
|
Container(
|
width: 10,
|
),
|
Expanded(
|
child: TextField(
|
controller: editingController,
|
onChanged: (text) {
|
print(text);
|
setState(() {
|
if (text.isNotEmpty)
|
state = 2;
|
else
|
state = 1;
|
});
|
},
|
decoration: const InputDecoration(
|
focusedBorder: InputBorder.none,
|
border: InputBorder.none,
|
hintText: "地图上找位置",
|
hintStyle: TextStyle(fontSize: 14, color: Color(0xFFC4CDD1))),
|
)),
|
InkWell(
|
child: Container(
|
padding: EdgeInsets.only(right: 10),
|
child: Text(
|
"搜索",
|
style: TextStyle(color: ColorConstant.theme, fontSize: 15),
|
)),
|
)
|
],
|
),
|
),
|
|
Expanded(child: getContentView())
|
]);
|
}
|
|
Widget getContentView() {
|
if (state == 1)
|
return getNotSearchView();
|
else if (state == 2) {
|
return getSearchSuggestView();
|
} else
|
return Container();
|
}
|
|
Widget getNotSearchView() {
|
return Column(
|
children: [
|
Container(
|
padding: EdgeInsets.only(left: 7, right: 7, bottom: 7, top: 7),
|
decoration: BoxDecoration(
|
color: Colors.white,
|
borderRadius: BorderRadius.only(
|
topRight: Radius.circular(15), topLeft: Radius.circular(15)),
|
boxShadow: getViewShadow(),
|
),
|
child: Column(mainAxisSize: MainAxisSize.min, children: [
|
//分类
|
Container(
|
padding:
|
EdgeInsets.only(left: 20, right: 20, bottom: 15, top: 9),
|
child: Row(
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
children: [
|
getSugguestSearchType(
|
"酒店",
|
Image.asset(
|
"assets/images/map/icon_location_search_type_hotel.png",
|
height: 34,
|
), () {
|
setSearchKey("酒店");
|
}),
|
getSugguestSearchType(
|
"餐馆",
|
Image.asset(
|
"assets/images/map/icon_location_search_type_eat.png",
|
height: 34,
|
), () {
|
setSearchKey("餐馆");
|
}),
|
getSugguestSearchType(
|
"外卖",
|
Image.asset(
|
"assets/images/map/icon_location_search_type_waimai.png",
|
height: 34,
|
), () {
|
setSearchKey("外卖");
|
}),
|
getSugguestSearchType(
|
"电影院",
|
Image.asset(
|
"assets/images/map/icon_location_search_type_movie.png",
|
height: 34,
|
), () {
|
setSearchKey("电影院");
|
}),
|
getSugguestSearchType(
|
"景点",
|
Image.asset(
|
"assets/images/map/icon_location_search_type_sense.png",
|
height: 34,
|
), () {
|
setSearchKey("景点");
|
}),
|
],
|
)),
|
//广告
|
Container(
|
height: 210,
|
),
|
]),
|
),
|
//分隔线
|
Container(
|
height: 10,
|
color: Color(0xFFF0F0F0),
|
),
|
Expanded(
|
child: Container(
|
color: Colors.white,
|
padding: EdgeInsets.only(left: 20, right: 20),
|
child: Column(
|
children: [getHistoryItem("融恒盈嘉中心-西门", "重庆市江北区", 0)],
|
),
|
))
|
],
|
);
|
}
|
|
setSearchKey(String key) {
|
editingController!.text = key;
|
editingController!.selection = TextSelection(
|
baseOffset: key.length, extentOffset: editingController!.text.length);
|
startPOISearch(key);
|
}
|
|
startPOISearch(String key) async {
|
BMFPoiNearbySearchOption poiNearbySearchOption = BMFPoiNearbySearchOption(
|
keywords: <String>[key],
|
location: BMFCoordinate(40.049557, 116.279295),
|
isRadiusLimit: false);
|
// 检索实例
|
BMFPoiNearbySearch nearbySearch = BMFPoiNearbySearch();
|
// 检索回调
|
nearbySearch.onGetPoiNearbySearchResult(
|
callback: (BMFPoiSearchResult result, BMFSearchErrorCode errorCode) {
|
print("poi周边检索回调 errorCode = ${errorCode} result = ${result.toMap()}");
|
// 解析reslut,具体参考demo
|
});
|
// 发起检索
|
bool flag = await nearbySearch.poiNearbySearch(poiNearbySearchOption);
|
}
|
|
//建议搜索视图
|
Widget getSearchSuggestView() {
|
return Container(
|
decoration: BoxDecoration(
|
color: Colors.white,
|
borderRadius: BorderRadius.only(
|
topLeft: Radius.circular(15), topRight: Radius.circular(15)),
|
boxShadow: getViewShadow()),
|
padding: EdgeInsets.fromLTRB(20, 0, 20, 0),
|
child: ListView(
|
padding: const EdgeInsets.all(0),
|
children: [
|
getHistoryItem("标题", "内容", 0),
|
getHistoryItem("标题", "内容", 1),
|
getHistoryItem("标题", "内容", 2),
|
getHistoryItem("标题", "内容", 3),
|
getHistoryItem("标题", "内容", 4),
|
getHistoryItem("标题", "内容", 5),
|
getHistoryItem("标题", "内容", 6),
|
getHistoryItem("标题", "内容", 7),
|
getHistoryItem("标题", "内容", 8),
|
getHistoryItem("标题", "内容", 9),
|
],
|
),
|
);
|
}
|
|
//历史记录项目
|
Widget getHistoryItem(String title, String content, int index) {
|
return InkWell(
|
onTap: () {
|
print("点击:$index");
|
},
|
child: Container(
|
height: 67,
|
decoration: BoxDecoration(
|
color: Colors.white,
|
border: const Border(
|
bottom: BorderSide(
|
// 设置单侧边框的样式
|
color: Color(0xFFF1F2F3),
|
width: 1,
|
style: BorderStyle.solid))),
|
child: Row(
|
crossAxisAlignment: CrossAxisAlignment.center,
|
children: [
|
Container(
|
padding: EdgeInsets.only(top: 12, right: 9),
|
alignment: Alignment.topCenter,
|
child: Image.asset(
|
"assets/images/map/icon_location_location.png",
|
height: 16,
|
)),
|
Expanded(
|
child: Column(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.center,
|
children: [
|
Text(
|
title,
|
softWrap: false,
|
overflow: TextOverflow.ellipsis,
|
style:
|
const TextStyle(color: Color(0xFF333333), fontSize: 13),
|
),
|
Container(
|
height: 5,
|
),
|
Text(
|
content,
|
style:
|
const TextStyle(color: Color(0xFF9DAAB3), fontSize: 11),
|
),
|
],
|
)),
|
Image.asset(
|
"assets/images/map/icon_location_position_input.png",
|
height: 20,
|
)
|
],
|
),
|
));
|
}
|
|
Widget getSugguestSearchType(
|
String title, Image icon, GestureTapCallback _onClick) {
|
return InkWell(
|
onTap: () {
|
_onClick();
|
},
|
child: Flex(
|
direction: Axis.vertical,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
children: [
|
icon,
|
Container(
|
height: 5,
|
),
|
Text(
|
title,
|
style: const TextStyle(color: Color(0xFF333333), fontSize: 11),
|
)
|
],
|
));
|
}
|
}
|
|
/********************位置详情********************/
|
class PositionDetailPage extends StatefulWidget {
|
@override
|
_PositionDetailPageState createState() => _PositionDetailPageState();
|
}
|
|
class _PositionDetailPageState extends State<PositionDetailPage>
|
with SingleTickerProviderStateMixin {
|
@override
|
Widget build(BuildContext context) {
|
return Container();
|
}
|
}
|