重构example项目结构
This commit is contained in:
parent
f8e58fcb35
commit
5abe4d7f6d
|
@ -0,0 +1,39 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class AnimatedCategoryItem extends StatelessWidget {
|
||||
AnimatedCategoryItem({
|
||||
required double startDelayFraction,
|
||||
required this.controller,
|
||||
required this.child,
|
||||
}) : topPaddingAnimation = Tween(
|
||||
begin: 0.0,
|
||||
end: 16.0,
|
||||
).animate(
|
||||
CurvedAnimation(
|
||||
parent: controller,
|
||||
curve: Interval(
|
||||
0.000 + startDelayFraction,
|
||||
0.400 + startDelayFraction,
|
||||
curve: Curves.ease,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
final Widget child;
|
||||
final AnimationController controller;
|
||||
final Animation<double> topPaddingAnimation;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AnimatedBuilder(
|
||||
animation: controller,
|
||||
builder: (context, child) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(top: topPaddingAnimation.value),
|
||||
child: child,
|
||||
);
|
||||
},
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
import 'package:flutter/cupertino.dart';
|
||||
|
||||
///demo的模板类
|
||||
abstract class BasePage extends StatelessWidget {
|
||||
final String title;
|
||||
final String subTitle;
|
||||
|
||||
const BasePage(this.title, this.subTitle);
|
||||
}
|
|
@ -0,0 +1,319 @@
|
|||
import 'package:amap_map_example/main.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
typedef CategoryHeaderTapCallback = Function(bool shouldOpenList);
|
||||
|
||||
class CategoryListItem extends StatefulWidget {
|
||||
const CategoryListItem({
|
||||
super.key,
|
||||
this.restorationId,
|
||||
required this.category,
|
||||
this.demos = const [],
|
||||
this.initiallyExpanded = false,
|
||||
this.onTap,
|
||||
});
|
||||
|
||||
final DemoCategory category;
|
||||
final String? restorationId;
|
||||
final List<Demo> demos;
|
||||
final bool initiallyExpanded;
|
||||
final CategoryHeaderTapCallback? onTap;
|
||||
|
||||
@override
|
||||
State<CategoryListItem> createState() => _CategoryListItemState();
|
||||
}
|
||||
|
||||
class _CategoryListItemState extends State<CategoryListItem>
|
||||
with SingleTickerProviderStateMixin {
|
||||
static final Animatable<double> _easeInTween =
|
||||
CurveTween(curve: Curves.easeIn);
|
||||
static const _expandDuration = Duration(milliseconds: 200);
|
||||
late AnimationController _controller;
|
||||
late Animation<double> _childrenHeightFactor;
|
||||
late Animation<double> _headerChevronOpacity;
|
||||
late Animation<double> _headerHeight;
|
||||
late Animation<EdgeInsetsGeometry> _headerMargin;
|
||||
late Animation<EdgeInsetsGeometry> _headerImagePadding;
|
||||
late Animation<EdgeInsetsGeometry> _childrenPadding;
|
||||
late Animation<BorderRadius?> _headerBorderRadius;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
_controller = AnimationController(duration: _expandDuration, vsync: this);
|
||||
_controller.addStatusListener((status) {
|
||||
setState(() {});
|
||||
});
|
||||
|
||||
_childrenHeightFactor = _controller.drive(_easeInTween);
|
||||
_headerChevronOpacity = _controller.drive(_easeInTween);
|
||||
_headerHeight = Tween<double>(
|
||||
begin: 80,
|
||||
end: 96,
|
||||
).animate(_controller);
|
||||
_headerMargin = EdgeInsetsGeometryTween(
|
||||
begin: const EdgeInsets.fromLTRB(32, 8, 32, 8),
|
||||
end: EdgeInsets.zero,
|
||||
).animate(_controller);
|
||||
_headerImagePadding = EdgeInsetsGeometryTween(
|
||||
begin: const EdgeInsets.all(8),
|
||||
end: const EdgeInsetsDirectional.fromSTEB(16, 8, 8, 8),
|
||||
).animate(_controller);
|
||||
_childrenPadding = EdgeInsetsGeometryTween(
|
||||
begin: const EdgeInsets.symmetric(horizontal: 32),
|
||||
end: EdgeInsets.zero,
|
||||
).animate(_controller);
|
||||
_headerBorderRadius = BorderRadiusTween(
|
||||
begin: BorderRadius.circular(10),
|
||||
end: BorderRadius.zero,
|
||||
).animate(_controller);
|
||||
|
||||
if (widget.initiallyExpanded) {
|
||||
_controller.value = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
bool _shouldOpenList() {
|
||||
switch (_controller.status) {
|
||||
case AnimationStatus.completed:
|
||||
case AnimationStatus.forward:
|
||||
return false;
|
||||
case AnimationStatus.dismissed:
|
||||
case AnimationStatus.reverse:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void _handleTap() {
|
||||
if (_shouldOpenList()) {
|
||||
_controller.forward();
|
||||
if (widget.onTap != null) {
|
||||
widget.onTap!(true);
|
||||
}
|
||||
} else {
|
||||
_controller.reverse();
|
||||
if (widget.onTap != null) {
|
||||
widget.onTap!(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildHeaderWithChildren(BuildContext context, Widget? child) {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
_CategoryHeader(
|
||||
margin: _headerMargin.value,
|
||||
imagePadding: _headerImagePadding.value,
|
||||
borderRadius: _headerBorderRadius.value!,
|
||||
height: _headerHeight.value,
|
||||
chevronOpacity: _headerChevronOpacity.value,
|
||||
category: widget.category,
|
||||
onTap: _handleTap,
|
||||
),
|
||||
Padding(
|
||||
padding: _childrenPadding.value,
|
||||
child: ClipRect(
|
||||
child: Align(
|
||||
heightFactor: _childrenHeightFactor.value,
|
||||
child: child,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AnimatedBuilder(
|
||||
animation: _controller.view,
|
||||
builder: _buildHeaderWithChildren,
|
||||
child: _shouldOpenList()
|
||||
? null
|
||||
: _ExpandedCategoryDemos(
|
||||
category: widget.category,
|
||||
demos: widget.demos,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _CategoryHeader extends StatelessWidget {
|
||||
const _CategoryHeader({
|
||||
this.margin,
|
||||
required this.imagePadding,
|
||||
required this.borderRadius,
|
||||
this.height,
|
||||
required this.chevronOpacity,
|
||||
required this.category,
|
||||
this.onTap,
|
||||
});
|
||||
|
||||
final EdgeInsetsGeometry? margin;
|
||||
final EdgeInsetsGeometry imagePadding;
|
||||
final double? height;
|
||||
final BorderRadiusGeometry borderRadius;
|
||||
final DemoCategory category;
|
||||
final double chevronOpacity;
|
||||
final GestureTapCallback? onTap;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
return Container(
|
||||
margin: margin,
|
||||
child: Material(
|
||||
shape: RoundedRectangleBorder(borderRadius: borderRadius),
|
||||
color: colorScheme.onBackground,
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: SizedBox(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
child: InkWell(
|
||||
// Makes integration tests possible.
|
||||
key: ValueKey('${category.name}CategoryHeader'),
|
||||
onTap: onTap,
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Wrap(
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
children: [
|
||||
Padding(
|
||||
padding: imagePadding,
|
||||
child: ExcludeSemantics(
|
||||
child: SizedBox(
|
||||
height: 48, // icon placeholder
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsetsDirectional.only(start: 8),
|
||||
child: Text(
|
||||
category.toDisplayTitle(),
|
||||
style: Theme.of(context).textTheme.headline5!.apply(
|
||||
color: colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Opacity(
|
||||
opacity: chevronOpacity,
|
||||
child: chevronOpacity != 0
|
||||
? Padding(
|
||||
padding: const EdgeInsetsDirectional.only(
|
||||
start: 8,
|
||||
end: 32,
|
||||
),
|
||||
child: Icon(
|
||||
Icons.keyboard_arrow_up,
|
||||
color: colorScheme.onSurface,
|
||||
),
|
||||
)
|
||||
: null,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _ExpandedCategoryDemos extends StatelessWidget {
|
||||
const _ExpandedCategoryDemos({
|
||||
required this.category,
|
||||
required this.demos,
|
||||
});
|
||||
|
||||
final DemoCategory category;
|
||||
final List<Demo> demos;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
// Makes integration tests possible.
|
||||
key: ValueKey('${category.name}DemoList'),
|
||||
children: [
|
||||
for (final demo in demos)
|
||||
CategoryDemoItem(
|
||||
demo: demo,
|
||||
),
|
||||
const SizedBox(height: 12), // Extra space below.
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class CategoryDemoItem extends StatelessWidget {
|
||||
const CategoryDemoItem({super.key, required this.demo});
|
||||
|
||||
final Demo demo;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final textTheme = Theme.of(context).textTheme;
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
return Material(
|
||||
// Makes integration tests possible.
|
||||
key: ValueKey(demo.describe),
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
child: MergeSemantics(
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
Navigator.of(context).restorablePushNamed(
|
||||
'/${demo.slug}',
|
||||
);
|
||||
},
|
||||
child: Padding(
|
||||
padding: EdgeInsetsDirectional.only(
|
||||
start: 32,
|
||||
top: 20,
|
||||
end: 8,
|
||||
),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(width: 40),
|
||||
Flexible(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
demo.title,
|
||||
style: textTheme.subtitle1!
|
||||
.apply(color: colorScheme.onSurface),
|
||||
),
|
||||
Text(
|
||||
demo.subtitle,
|
||||
style: textTheme.overline!.apply(
|
||||
color: colorScheme.onSurface.withOpacity(0.5),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
Divider(
|
||||
thickness: 1,
|
||||
height: 1,
|
||||
color: Theme.of(context).colorScheme.background,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
import 'dart:collection';
|
||||
|
||||
import 'package:amap_map_example/main.dart';
|
||||
import 'package:amap_map_example/pages/interactive/map_ui_options.dart';
|
||||
import 'package:amap_map_example/pages/map/limit_map_bounds.dart';
|
||||
import 'package:amap_map_example/pages/map/map_my_location.dart';
|
||||
import 'package:amap_map_example/pages/map/show_map_page.dart';
|
||||
import 'package:amap_map_example/pages/overlays/marker_config.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class DemoConfiguration {
|
||||
const DemoConfiguration({
|
||||
required this.buildRoute,
|
||||
});
|
||||
|
||||
final WidgetBuilder buildRoute;
|
||||
}
|
||||
|
||||
List<Demo> allDemos() => mapDemos() + interactiveDemos() + overlayDemos();
|
||||
|
||||
List<Demo> mapDemos() {
|
||||
return [
|
||||
Demo(
|
||||
title: '显示地图',
|
||||
category: DemoCategory.basic,
|
||||
subtitle: '基本地图显示',
|
||||
slug: 'show-map',
|
||||
configurations: [
|
||||
DemoConfiguration(buildRoute: (context) => ShowMapPage())
|
||||
]),
|
||||
Demo(
|
||||
title: '显示定位蓝点',
|
||||
category: DemoCategory.basic,
|
||||
subtitle: '定位蓝点指的是进入地图后显示当前位置点的功能',
|
||||
slug: 'my-location',
|
||||
configurations: [
|
||||
DemoConfiguration(buildRoute: (context) => LimitMapBoundsPage())
|
||||
]),
|
||||
Demo(
|
||||
title: '限制地图显示范围',
|
||||
category: DemoCategory.basic,
|
||||
subtitle: '演示限定手机屏幕显示地图的范围',
|
||||
slug: 'limit-map-bounds',
|
||||
configurations: [
|
||||
DemoConfiguration(buildRoute: (context) => MyLocationPage())
|
||||
]),
|
||||
];
|
||||
}
|
||||
|
||||
List<Demo> interactiveDemos() {
|
||||
return [
|
||||
Demo(
|
||||
title: 'UI控制',
|
||||
category: DemoCategory.interactive,
|
||||
subtitle: '浮在地图图面上用于操作地图的组件,例如缩放按钮、指南针、定位按钮、比例尺等。',
|
||||
slug: 'map-ui',
|
||||
configurations: [
|
||||
DemoConfiguration(buildRoute: (context) => MapUIDemoPage())
|
||||
])
|
||||
];
|
||||
}
|
||||
|
||||
List<Demo> overlayDemos() {
|
||||
return [
|
||||
Demo(
|
||||
title: '绘制点标记',
|
||||
category: DemoCategory.overlay,
|
||||
subtitle: '演示Marker的相关属性的操作',
|
||||
slug: 'marker-config',
|
||||
configurations: [
|
||||
DemoConfiguration(buildRoute: (context) => MarkerConfigDemoPage())
|
||||
])
|
||||
];
|
||||
}
|
||||
|
||||
Map<String?, Demo> slugToDemo(BuildContext context) {
|
||||
return LinkedHashMap<String?, Demo>.fromIterable(
|
||||
allDemos(),
|
||||
key: (dynamic demo) => demo.slug as String?,
|
||||
);
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
import 'package:amap_map_example/data/demos.dart';
|
||||
import 'package:amap_map_example/main.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class DemoPage extends StatefulWidget {
|
||||
const DemoPage({
|
||||
super.key,
|
||||
required this.slug,
|
||||
});
|
||||
|
||||
final String? slug;
|
||||
|
||||
@override
|
||||
State<DemoPage> createState() => _DemoPageState();
|
||||
}
|
||||
|
||||
class _DemoPageState extends State<DemoPage> {
|
||||
late Map<String?, Demo> slugToDemoMap;
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
slugToDemoMap = slugToDemo(context);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (widget.slug == null || !slugToDemoMap.containsKey(widget.slug)) {
|
||||
// Return to root if invalid slug.
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
return ScaffoldMessenger(
|
||||
child: AMapDemoPage(
|
||||
restorationId: widget.slug!,
|
||||
demo: slugToDemoMap[widget.slug]!,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
class AMapDemoPage extends StatefulWidget {
|
||||
const AMapDemoPage({
|
||||
super.key,
|
||||
required this.restorationId,
|
||||
required this.demo,
|
||||
});
|
||||
|
||||
final String restorationId;
|
||||
final Demo demo;
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _AMapDemoPageState(demo);
|
||||
}
|
||||
|
||||
class _AMapDemoPageState extends State<AMapDemoPage> {
|
||||
_AMapDemoPageState(this.demo);
|
||||
|
||||
final Demo demo;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text(demo.title)),
|
||||
body: SafeArea(
|
||||
child: Builder(builder: demo.configurations.first.buildRoute),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,64 +1,42 @@
|
|||
import 'package:amap_map/amap_map.dart';
|
||||
import 'package:amap_map_example/animated_category_item.dart';
|
||||
import 'package:amap_map_example/category_list_item.dart';
|
||||
import 'package:amap_map_example/const_config.dart';
|
||||
import 'package:amap_map_example/pages/overlays/marker_add_after_map.dart';
|
||||
import 'package:amap_map_example/pages/overlays/marker_add_with_map.dart';
|
||||
import 'package:amap_map_example/pages/overlays/marker_config.dart';
|
||||
import 'package:amap_map_example/pages/overlays/marker_custom_icon.dart';
|
||||
import 'package:amap_map_example/pages/overlays/place_polygon.dart';
|
||||
import 'package:amap_map_example/pages/overlays/place_polyline.dart';
|
||||
import 'package:amap_map_example/pages/interactive/map_gestures_options.dart';
|
||||
import 'package:amap_map_example/pages/interactive/map_ui_options.dart';
|
||||
import 'package:amap_map_example/pages/interactive/move_camera_demo.dart';
|
||||
import 'package:amap_map_example/pages/interactive/poi_click_demo.dart';
|
||||
import 'package:amap_map_example/pages/interactive/snapshot_demo.dart';
|
||||
import 'package:amap_map_example/pages/map/change_map_type.dart';
|
||||
import 'package:amap_map_example/pages/map/custom_map_style.dart';
|
||||
import 'package:amap_map_example/pages/map/limit_map_bounds.dart';
|
||||
import 'package:amap_map_example/pages/map/map_all_config.dart';
|
||||
import 'package:amap_map_example/pages/map/map_my_location.dart';
|
||||
import 'package:amap_map_example/pages/map/min_max_zoom.dart';
|
||||
import 'package:amap_map_example/pages/map/multi_map.dart';
|
||||
import 'package:amap_map_example/pages/map/show_map_page.dart';
|
||||
import 'package:amap_map_example/pages/overlays/polyline_geodesic.dart';
|
||||
import 'package:amap_map_example/pages/overlays/polyline_texture.dart';
|
||||
import 'package:amap_map_example/widgets/demo_group.dart';
|
||||
import 'package:amap_map_example/data/demos.dart';
|
||||
import 'package:amap_map_example/routes.dart';
|
||||
import 'package:amap_map_example/theme.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
|
||||
import 'base_page.dart';
|
||||
// final List<BasePage> _mapDemoPages = <BasePage>[
|
||||
// AllMapConfigDemoPage('总体演示', '演示AMapWidget的所有配置项'),
|
||||
|
||||
final List<BasePage> _mapDemoPages = <BasePage>[
|
||||
AllMapConfigDemoPage('总体演示', '演示AMapWidget的所有配置项'),
|
||||
ShowMapPage('显示地图', '基本地图显示'),
|
||||
LimitMapBoundsPage('限制地图显示范围', '演示限定手机屏幕显示地图的范围'),
|
||||
MinMaxZoomDemoPage('指定显示级别范围', '演示指定最小最大级别功能'),
|
||||
ChangeMapTypePage('切换地图图层', '演示内置的地图图层'),
|
||||
CustomMapStylePage('自定义地图', '根据自定义的地图样式文件显示地图'),
|
||||
MultiMapDemoPage('地图多实例', '同时显示多个地图'),
|
||||
];
|
||||
// MinMaxZoomDemoPage('指定显示级别范围', '演示指定最小最大级别功能'),
|
||||
// ChangeMapTypePage('切换地图图层', '演示内置的地图图层'),
|
||||
// CustomMapStylePage('自定义地图', '根据自定义的地图样式文件显示地图'),
|
||||
// MultiMapDemoPage('地图多实例', '同时显示多个地图'),
|
||||
// ];
|
||||
|
||||
final List<BasePage> _interactiveDemoPages = <BasePage>[
|
||||
MapUIDemoPage('UI控制', 'ui开关演示'),
|
||||
GesturesDemoPage('手势交互', '手势交互'),
|
||||
PoiClickDemoPage('点击poi功能', '演示点击poi之后的回调和信息透出'),
|
||||
MoveCameraDemoPage('改变地图视角', '演示改变地图的中心点、可视区域、缩放级别等功能'),
|
||||
SnapshotPage('地图截屏', '地图截屏示例'),
|
||||
MyLocationPage('显示我的位置', '在地图上显示我的位置'),
|
||||
];
|
||||
// final List<BasePage> _interactiveDemoPages = <BasePage>[
|
||||
// MapUIDemoPage('UI控制', 'ui开关演示'),
|
||||
// GesturesDemoPage('手势交互', '手势交互'),
|
||||
// PoiClickDemoPage('点击poi功能', '演示点击poi之后的回调和信息透出'),
|
||||
// MoveCameraDemoPage('改变地图视角', '演示改变地图的中心点、可视区域、缩放级别等功能'),
|
||||
// SnapshotPage('地图截屏', '地图截屏示例'),
|
||||
// ];
|
||||
|
||||
final List<BasePage> _markerPages = <BasePage>[
|
||||
MarkerConfigDemoPage('Marker操作', '演示Marker的相关属性的操作'),
|
||||
MarkerAddWithMapPage("随地图添加", "演示初始化地图时直接添加marker"),
|
||||
MarkerAddAfterMapPage("单独添加", "演示地图初始化之后单独添加marker功能"),
|
||||
MarkerCustomIconPage('自定义图标', '演示marker使用自定义图标功能'),
|
||||
];
|
||||
// final List<BasePage> _markerPages = <BasePage>[
|
||||
// MarkerAddWithMapPage("随地图添加", "演示初始化地图时直接添加marker"),
|
||||
// MarkerAddAfterMapPage("单独添加", "演示地图初始化之后单独添加marker功能"),
|
||||
// MarkerCustomIconPage('自定义图标', '演示marker使用自定义图标功能'),
|
||||
// ];
|
||||
|
||||
final List<BasePage> _overlayPages = <BasePage>[
|
||||
PolylineDemoPage('Polyline操作', '演示Polyline的相关属性的操作'),
|
||||
PolylineGeodesicDemoPage('Polyline大地曲线', '演示大地曲线的添加'),
|
||||
PolylineTextureDemoPage('Polyline纹理线', '演示纹理线的添加'),
|
||||
PolygonDemoPage('Polygon操作', '演示Polygon的相关属性的操作'),
|
||||
];
|
||||
// final List<BasePage> _overlayPages = <BasePage>[
|
||||
// PolylineDemoPage('Polyline操作', '演示Polyline的相关属性的操作'),
|
||||
// PolylineGeodesicDemoPage('Polyline大地曲线', '演示大地曲线的添加'),
|
||||
// PolylineTextureDemoPage('Polyline纹理线', '演示纹理线的添加'),
|
||||
// PolygonDemoPage('Polygon操作', '演示Polygon的相关属性的操作'),
|
||||
// ];
|
||||
|
||||
final List<Permission> needPermissionList = [
|
||||
Permission.location,
|
||||
|
@ -68,17 +46,24 @@ final List<Permission> needPermissionList = [
|
|||
|
||||
class AMapDemo extends StatefulWidget {
|
||||
@override
|
||||
State<StatefulWidget> createState() {
|
||||
return DemoWidget();
|
||||
}
|
||||
State<StatefulWidget> createState() => _AMapDemoState();
|
||||
}
|
||||
|
||||
class DemoWidget extends State<AMapDemo> {
|
||||
class _AMapDemoState extends State<AMapDemo>
|
||||
with RestorationMixin, SingleTickerProviderStateMixin {
|
||||
late AnimationController _animationController;
|
||||
final RestorableBool _isMapListExpanded = RestorableBool(false);
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
_checkPermissions();
|
||||
|
||||
_animationController = AnimationController(
|
||||
vsync: this,
|
||||
duration: const Duration(milliseconds: 800),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -101,41 +86,83 @@ class DemoWidget extends State<AMapDemo> {
|
|||
AMapInitializer.updatePrivacyAgree(ConstConfig.amapPrivacyStatement);
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('高德地图示例')),
|
||||
body: Container(
|
||||
height: MediaQuery.of(context).size.height,
|
||||
width: MediaQuery.of(context).size.width,
|
||||
child: SingleChildScrollView(
|
||||
child: Container(
|
||||
child: Column(
|
||||
children: [
|
||||
DemoGroupWidget(
|
||||
groupLabel: '创建地图',
|
||||
itemPages: _mapDemoPages,
|
||||
),
|
||||
DemoGroupWidget(
|
||||
groupLabel: '地图交互',
|
||||
itemPages: _interactiveDemoPages,
|
||||
),
|
||||
DemoGroupWidget(
|
||||
groupLabel: '绘制点标记',
|
||||
itemPages: _markerPages,
|
||||
),
|
||||
DemoGroupWidget(
|
||||
groupLabel: '绘制线和面',
|
||||
itemPages: _overlayPages,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
body: ListView(
|
||||
children: [
|
||||
AnimatedCategoryItem(
|
||||
startDelayFraction: 0,
|
||||
controller: _animationController,
|
||||
child: CategoryListItem(
|
||||
category: DemoCategory.basic,
|
||||
demos: mapDemos(),
|
||||
)),
|
||||
AnimatedCategoryItem(
|
||||
startDelayFraction: 0.05,
|
||||
controller: _animationController,
|
||||
child: CategoryListItem(
|
||||
category: DemoCategory.interactive,
|
||||
demos: interactiveDemos(),
|
||||
)),
|
||||
AnimatedCategoryItem(
|
||||
startDelayFraction: 0.1,
|
||||
controller: _animationController,
|
||||
child: CategoryListItem(
|
||||
category: DemoCategory.overlay,
|
||||
demos: overlayDemos(),
|
||||
)),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
String? get restorationId => 'demos';
|
||||
|
||||
@override
|
||||
void restoreState(RestorationBucket? oldBucket, bool initialRestore) {
|
||||
registerForRestoration(_isMapListExpanded, 'map_list');
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
// debugProfileBuildsEnabled = true;
|
||||
// debugProfilePaintsEnabled = true;
|
||||
// debugPaintLayerBordersEnabled = true;
|
||||
runApp(MaterialApp(home: AMapDemo()));
|
||||
runApp(MaterialApp(
|
||||
theme: ThemeData(colorScheme: DemoThemeData.lightColorScheme),
|
||||
themeMode: ThemeMode.light,
|
||||
onGenerateRoute: RouteConfig.onGenerateRoute,
|
||||
home: AMapDemo()));
|
||||
}
|
||||
|
||||
enum DemoCategory {
|
||||
basic,
|
||||
interactive,
|
||||
overlay;
|
||||
|
||||
String toDisplayTitle() {
|
||||
switch (this) {
|
||||
case basic:
|
||||
return '创建地图';
|
||||
case interactive:
|
||||
return '与地图交互';
|
||||
case overlay:
|
||||
return '在地图上绘制';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Demo {
|
||||
const Demo({
|
||||
required this.title,
|
||||
required this.category,
|
||||
required this.subtitle,
|
||||
// Parameters below are required for non-study demos.
|
||||
this.slug,
|
||||
this.configurations = const [],
|
||||
}) : assert(slug != null);
|
||||
|
||||
final String title;
|
||||
final DemoCategory category;
|
||||
final String subtitle;
|
||||
final String? slug;
|
||||
final List<DemoConfiguration> configurations;
|
||||
|
||||
String get describe => '$slug@${category.name}';
|
||||
}
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
// Copyright 2018 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// ignore_for_file: public_member_api_docs
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
abstract class AMapExampleAppPage extends StatelessWidget {
|
||||
const AMapExampleAppPage(this.leading, this.title);
|
||||
|
||||
final Widget leading;
|
||||
final String title;
|
||||
}
|
|
@ -1,24 +1,16 @@
|
|||
import 'package:amap_map/amap_map.dart';
|
||||
import 'package:amap_map_example/base_page.dart';
|
||||
import 'package:amap_map_example/const_config.dart';
|
||||
import 'package:amap_map_example/widgets/amap_gridview.dart';
|
||||
import 'package:amap_map_example/widgets/amap_switch_button.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class GesturesDemoPage extends BasePage {
|
||||
GesturesDemoPage(String title, String subTitle) : super(title, subTitle);
|
||||
@override
|
||||
Widget build(BuildContext context) => _Body();
|
||||
}
|
||||
|
||||
class _Body extends StatefulWidget {
|
||||
_Body({Key? key}) : super(key: key);
|
||||
class GesturesDemoPage extends StatefulWidget {
|
||||
GesturesDemoPage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_BodyState createState() => _BodyState();
|
||||
}
|
||||
|
||||
class _BodyState extends State<_Body> {
|
||||
class _BodyState extends State<GesturesDemoPage> {
|
||||
///是否支持缩放手势
|
||||
bool _zoomGesturesEnabled = true;
|
||||
|
||||
|
|
|
@ -1,25 +1,16 @@
|
|||
import 'package:amap_map/amap_map.dart';
|
||||
import 'package:amap_map_example/base_page.dart';
|
||||
import 'package:amap_map_example/const_config.dart';
|
||||
import 'package:amap_map_example/widgets/amap_gridview.dart';
|
||||
import 'package:amap_map_example/widgets/amap_switch_button.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class MapUIDemoPage extends BasePage {
|
||||
MapUIDemoPage(String title, String subTitle) : super(title, subTitle);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => _Body();
|
||||
}
|
||||
|
||||
class _Body extends StatefulWidget {
|
||||
_Body({Key? key}) : super(key: key);
|
||||
class MapUIDemoPage extends StatefulWidget {
|
||||
MapUIDemoPage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_BodyState createState() => _BodyState();
|
||||
}
|
||||
|
||||
class _BodyState extends State<_Body> {
|
||||
class _BodyState extends State<MapUIDemoPage> {
|
||||
///显示路况开关
|
||||
bool _trafficEnabled = false;
|
||||
|
||||
|
|
|
@ -1,24 +1,14 @@
|
|||
import 'dart:typed_data';
|
||||
|
||||
import 'package:amap_map/amap_map.dart';
|
||||
import 'package:amap_map_example/base_page.dart';
|
||||
import 'package:amap_map_example/const_config.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class SnapshotPage extends BasePage {
|
||||
SnapshotPage(String title, String subTitle) : super(title, subTitle);
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return _SnapShotBody();
|
||||
}
|
||||
}
|
||||
|
||||
class _SnapShotBody extends StatefulWidget {
|
||||
class SnapshotPage extends StatefulWidget {
|
||||
@override
|
||||
State<StatefulWidget> createState() => _SnapShotState();
|
||||
}
|
||||
|
||||
class _SnapShotState extends State<_SnapShotBody> {
|
||||
class _SnapShotState extends State<SnapshotPage> {
|
||||
AMapController? _mapController;
|
||||
Uint8List? _imageBytes;
|
||||
@override
|
||||
|
|
|
@ -1,24 +1,15 @@
|
|||
import 'package:amap_map/amap_map.dart';
|
||||
import 'package:amap_map_example/base_page.dart';
|
||||
import 'package:amap_map_example/const_config.dart';
|
||||
import 'package:amap_map_example/widgets/amap_radio_group.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class ChangeMapTypePage extends BasePage {
|
||||
ChangeMapTypePage(String title, String subTitle) : super(title, subTitle);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => _PageBody();
|
||||
}
|
||||
|
||||
class _PageBody extends StatefulWidget {
|
||||
_PageBody({Key? key}) : super(key: key);
|
||||
class ChangeMapTypePage extends StatefulWidget {
|
||||
ChangeMapTypePage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_PageBodyState createState() => _PageBodyState();
|
||||
}
|
||||
|
||||
class _PageBodyState extends State<_PageBody> {
|
||||
class _PageBodyState extends State<ChangeMapTypePage> {
|
||||
//地图类型
|
||||
late MapType _mapType;
|
||||
final Map<String, MapType> _radioValueMap = {
|
||||
|
|
|
@ -1,27 +1,16 @@
|
|||
import 'dart:typed_data';
|
||||
|
||||
import 'package:amap_map/amap_map.dart';
|
||||
import 'package:amap_map_example/base_page.dart';
|
||||
import 'package:amap_map_example/const_config.dart';
|
||||
import 'package:amap_map_example/widgets/amap_switch_button.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
class CustomMapStylePage extends BasePage {
|
||||
CustomMapStylePage(String title, String subTitle) : super(title, subTitle);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => _CustomMapStyleBody();
|
||||
}
|
||||
|
||||
class _CustomMapStyleBody extends StatefulWidget {
|
||||
_CustomMapStyleBody({Key? key}) : super(key: key);
|
||||
class CustomMapStylePage extends StatefulWidget {
|
||||
CustomMapStylePage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_CustomMapStyleState createState() => _CustomMapStyleState();
|
||||
}
|
||||
|
||||
class _CustomMapStyleState extends State<_CustomMapStyleBody> {
|
||||
class _CustomMapStyleState extends State<CustomMapStylePage> {
|
||||
bool _mapCreated = false;
|
||||
|
||||
CustomStyleOptions _customStyleOptions = CustomStyleOptions(false);
|
||||
|
|
|
@ -1,24 +1,15 @@
|
|||
import 'package:amap_map/amap_map.dart';
|
||||
import 'package:x_amap_base/x_amap_base.dart';
|
||||
import 'package:amap_map_example/base_page.dart';
|
||||
import 'package:amap_map_example/const_config.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class LimitMapBoundsPage extends BasePage {
|
||||
LimitMapBoundsPage(String title, String subTitle) : super(title, subTitle);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => _Body();
|
||||
}
|
||||
|
||||
class _Body extends StatefulWidget {
|
||||
_Body({Key? key}) : super(key: key);
|
||||
class LimitMapBoundsPage extends StatefulWidget {
|
||||
LimitMapBoundsPage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_BodyState createState() => _BodyState();
|
||||
}
|
||||
|
||||
class _BodyState extends State<_Body> {
|
||||
class _BodyState extends State<LimitMapBoundsPage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final AMapWidget amap = AMapWidget(
|
||||
|
|
|
@ -1,28 +1,18 @@
|
|||
import 'dart:typed_data';
|
||||
|
||||
import 'package:amap_map/amap_map.dart';
|
||||
import 'package:amap_map_example/base_page.dart';
|
||||
import 'package:amap_map_example/const_config.dart';
|
||||
import 'package:amap_map_example/widgets/amap_switch_button.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:x_amap_base/x_amap_base.dart';
|
||||
|
||||
class AllMapConfigDemoPage extends BasePage {
|
||||
AllMapConfigDemoPage(String title, String subTitle) : super(title, subTitle);
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return _MapUiBody();
|
||||
}
|
||||
}
|
||||
|
||||
class _MapUiBody extends StatefulWidget {
|
||||
class AllMapConfigDemoPage extends StatefulWidget {
|
||||
@override
|
||||
State<StatefulWidget> createState() => _MapUiBodyState();
|
||||
}
|
||||
|
||||
class _MapUiBodyState extends State<_MapUiBody> {
|
||||
class _MapUiBodyState extends State<AllMapConfigDemoPage> {
|
||||
//默认显示在北京天安门
|
||||
static final CameraPosition _kInitialPosition = const CameraPosition(
|
||||
target: LatLng(39.909187, 116.397451),
|
||||
|
|
|
@ -1,22 +1,14 @@
|
|||
import 'package:amap_map/amap_map.dart';
|
||||
import 'package:amap_map_example/base_page.dart';
|
||||
import 'package:amap_map_example/const_config.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
|
||||
class MyLocationPage extends BasePage {
|
||||
MyLocationPage(String title, String subTitle) : super(title, subTitle);
|
||||
@override
|
||||
Widget build(BuildContext context) => _Body();
|
||||
}
|
||||
|
||||
class _Body extends StatefulWidget {
|
||||
_Body({Key? key}) : super(key: key);
|
||||
class MyLocationPage extends StatefulWidget {
|
||||
MyLocationPage({Key? key}) : super(key: key);
|
||||
@override
|
||||
_BodyState createState() => _BodyState();
|
||||
}
|
||||
|
||||
class _BodyState extends State<_Body> {
|
||||
class _BodyState extends State<MyLocationPage> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
@ -44,6 +36,7 @@ class _BodyState extends State<_Body> {
|
|||
circleStrokeWidth: 1,
|
||||
),
|
||||
);
|
||||
|
||||
return Container(
|
||||
child: amap,
|
||||
);
|
||||
|
|
|
@ -1,23 +1,14 @@
|
|||
import 'package:amap_map/amap_map.dart';
|
||||
import 'package:amap_map_example/base_page.dart';
|
||||
import 'package:amap_map_example/const_config.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class MinMaxZoomDemoPage extends BasePage {
|
||||
MinMaxZoomDemoPage(String title, String subTitle) : super(title, subTitle);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => _Body();
|
||||
}
|
||||
|
||||
class _Body extends StatefulWidget {
|
||||
_Body({Key? key}) : super(key: key);
|
||||
class MinMaxZoomDemoPage extends StatefulWidget {
|
||||
MinMaxZoomDemoPage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_BodyState createState() => _BodyState();
|
||||
}
|
||||
|
||||
class _BodyState extends State<_Body> {
|
||||
class _BodyState extends State<MinMaxZoomDemoPage> {
|
||||
final double _minZoom = 10;
|
||||
final double _maxZoom = 15;
|
||||
String? _currentZoom;
|
||||
|
|
|
@ -1,23 +1,14 @@
|
|||
import 'package:amap_map/amap_map.dart';
|
||||
import 'package:x_amap_base/x_amap_base.dart';
|
||||
import 'package:amap_map_example/base_page.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class MultiMapDemoPage extends BasePage {
|
||||
MultiMapDemoPage(String title, String subTitle) : super(title, subTitle);
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return const _MultiMapDemoBody();
|
||||
}
|
||||
}
|
||||
|
||||
class _MultiMapDemoBody extends StatefulWidget {
|
||||
const _MultiMapDemoBody();
|
||||
class MultiMapDemoPage extends StatefulWidget {
|
||||
const MultiMapDemoPage();
|
||||
@override
|
||||
State<StatefulWidget> createState() => _MultiMapDemoState();
|
||||
}
|
||||
|
||||
class _MultiMapDemoState extends State<_MultiMapDemoBody> {
|
||||
class _MultiMapDemoState extends State<MultiMapDemoPage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
|
|
|
@ -1,23 +1,13 @@
|
|||
import 'package:amap_map_example/base_page.dart';
|
||||
import 'package:amap_map_example/const_config.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:amap_map/amap_map.dart';
|
||||
|
||||
class ShowMapPage extends BasePage {
|
||||
ShowMapPage(String title, String subTitle) : super(title, subTitle);
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return _ShowMapPageBody();
|
||||
}
|
||||
}
|
||||
|
||||
class _ShowMapPageBody extends StatefulWidget {
|
||||
class ShowMapPage extends StatefulWidget {
|
||||
@override
|
||||
State<StatefulWidget> createState() => _ShowMapPageState();
|
||||
}
|
||||
|
||||
class _ShowMapPageState extends State<_ShowMapPageBody> {
|
||||
class _ShowMapPageState extends State<ShowMapPage> {
|
||||
List<Widget> _approvalNumberWidget = <Widget>[];
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
|
@ -1,22 +1,13 @@
|
|||
import 'package:amap_map/amap_map.dart';
|
||||
import 'package:x_amap_base/x_amap_base.dart';
|
||||
import 'package:amap_map_example/base_page.dart';
|
||||
import 'package:amap_map_example/const_config.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class MarkerAddAfterMapPage extends BasePage {
|
||||
MarkerAddAfterMapPage(String title, String subTitle) : super(title, subTitle);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => _Body();
|
||||
}
|
||||
|
||||
class _Body extends StatefulWidget {
|
||||
class MarkerAddAfterMapPage extends StatefulWidget {
|
||||
@override
|
||||
_BodyState createState() => _BodyState();
|
||||
}
|
||||
|
||||
class _BodyState extends State<_Body> {
|
||||
class _BodyState extends State<MarkerAddAfterMapPage> {
|
||||
static final LatLng defaultPosition = const LatLng(39.909187, 116.397451);
|
||||
//需要先设置一个空的map赋值给AMapWidget的markers,否则后续无法添加marker
|
||||
final Map<String, Marker> _markers = <String, Marker>{};
|
||||
|
|
|
@ -2,23 +2,14 @@ import 'dart:math';
|
|||
|
||||
import 'package:amap_map/amap_map.dart';
|
||||
import 'package:x_amap_base/x_amap_base.dart';
|
||||
import 'package:amap_map_example/base_page.dart';
|
||||
import 'package:amap_map_example/const_config.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class MarkerAddWithMapPage extends BasePage {
|
||||
MarkerAddWithMapPage(String title, String subTitle) : super(title, subTitle);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => _Body();
|
||||
}
|
||||
|
||||
class _Body extends StatefulWidget {
|
||||
class MarkerAddWithMapPage extends StatefulWidget {
|
||||
@override
|
||||
_BodyState createState() => _BodyState();
|
||||
}
|
||||
|
||||
class _BodyState extends State<_Body> {
|
||||
class _BodyState extends State<MarkerAddWithMapPage> {
|
||||
static final LatLng mapCenter = const LatLng(39.909187, 116.397451);
|
||||
final Map<String, Marker> _initMarkerMap = <String, Marker>{};
|
||||
|
||||
|
|
|
@ -2,33 +2,21 @@ import 'dart:async';
|
|||
import 'dart:typed_data';
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:amap_map_example/base_page.dart';
|
||||
import 'package:amap_map_example/const_config.dart';
|
||||
import 'package:amap_map_example/widgets/amap_switch_button.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'package:amap_map/amap_map.dart';
|
||||
import 'package:x_amap_base/x_amap_base.dart';
|
||||
import 'dart:math';
|
||||
|
||||
class MarkerConfigDemoPage extends BasePage {
|
||||
MarkerConfigDemoPage(String title, String subTitle) : super(title, subTitle);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return _Body();
|
||||
}
|
||||
}
|
||||
|
||||
class _Body extends StatefulWidget {
|
||||
const _Body();
|
||||
class MarkerConfigDemoPage extends StatefulWidget {
|
||||
const MarkerConfigDemoPage();
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _State();
|
||||
}
|
||||
|
||||
class _State extends State<_Body> {
|
||||
class _State extends State<MarkerConfigDemoPage> {
|
||||
static final LatLng mapCenter = const LatLng(39.909187, 116.397451);
|
||||
|
||||
Map<String, Marker> _markers = <String, Marker>{};
|
||||
|
|
|
@ -1,22 +1,13 @@
|
|||
import 'package:amap_map/amap_map.dart';
|
||||
import 'package:x_amap_base/x_amap_base.dart';
|
||||
import 'package:amap_map_example/base_page.dart';
|
||||
import 'package:amap_map_example/const_config.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class MarkerCustomIconPage extends BasePage {
|
||||
MarkerCustomIconPage(String title, String subTitle) : super(title, subTitle);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => _Body();
|
||||
}
|
||||
|
||||
class _Body extends StatefulWidget {
|
||||
class MarkerCustomIconPage extends StatefulWidget {
|
||||
@override
|
||||
_BodyState createState() => _BodyState();
|
||||
}
|
||||
|
||||
class _BodyState extends State<_Body> {
|
||||
class _BodyState extends State<MarkerCustomIconPage> {
|
||||
static final LatLng markerPosition = const LatLng(39.909187, 116.397451);
|
||||
final Map<String, Marker> _initMarkerMap = <String, Marker>{};
|
||||
String? _currentMarkerId;
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import 'package:amap_map_example/base_page.dart';
|
||||
import 'package:amap_map_example/widgets/amap_switch_button.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
@ -6,22 +5,14 @@ import 'package:flutter/widgets.dart';
|
|||
import 'package:amap_map/amap_map.dart';
|
||||
import 'package:x_amap_base/x_amap_base.dart';
|
||||
|
||||
class PolygonDemoPage extends BasePage {
|
||||
PolygonDemoPage(String title, String subTitle) : super(title, subTitle);
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return _Body();
|
||||
}
|
||||
}
|
||||
|
||||
class _Body extends StatefulWidget {
|
||||
const _Body();
|
||||
class PolygonDemoPage extends StatefulWidget {
|
||||
const PolygonDemoPage();
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _State();
|
||||
}
|
||||
|
||||
class _State extends State<_Body> {
|
||||
class _State extends State<PolygonDemoPage> {
|
||||
_State();
|
||||
|
||||
// Values when toggling Polygon color
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import 'package:amap_map_example/base_page.dart';
|
||||
import 'package:amap_map_example/widgets/amap_switch_button.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
@ -6,22 +5,14 @@ import 'package:flutter/widgets.dart';
|
|||
import 'package:amap_map/amap_map.dart';
|
||||
import 'package:x_amap_base/x_amap_base.dart';
|
||||
|
||||
class PolylineDemoPage extends BasePage {
|
||||
PolylineDemoPage(String title, String subTitle) : super(title, subTitle);
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return _Body();
|
||||
}
|
||||
}
|
||||
|
||||
class _Body extends StatefulWidget {
|
||||
const _Body();
|
||||
class PolylineDemoPage extends StatefulWidget {
|
||||
const PolylineDemoPage();
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _State();
|
||||
}
|
||||
|
||||
class _State extends State<_Body> {
|
||||
class _State extends State<PolylineDemoPage> {
|
||||
_State();
|
||||
|
||||
// Values when toggling polyline color
|
||||
|
|
|
@ -1,27 +1,17 @@
|
|||
import 'package:amap_map_example/base_page.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'package:amap_map/amap_map.dart';
|
||||
import 'package:x_amap_base/x_amap_base.dart';
|
||||
|
||||
class PolylineGeodesicDemoPage extends BasePage {
|
||||
PolylineGeodesicDemoPage(String title, String subTitle)
|
||||
: super(title, subTitle);
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return _Body();
|
||||
}
|
||||
}
|
||||
|
||||
class _Body extends StatefulWidget {
|
||||
const _Body();
|
||||
class PolylineGeodesicDemoPage extends StatefulWidget {
|
||||
const PolylineGeodesicDemoPage();
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _State();
|
||||
}
|
||||
|
||||
class _State extends State<_Body> {
|
||||
class _State extends State<PolylineGeodesicDemoPage> {
|
||||
_State();
|
||||
|
||||
// Values when toggling polyline color
|
||||
|
|
|
@ -1,27 +1,16 @@
|
|||
import 'package:amap_map/amap_map.dart';
|
||||
import 'package:amap_map_example/base_page.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'package:x_amap_base/x_amap_base.dart';
|
||||
|
||||
class PolylineTextureDemoPage extends BasePage {
|
||||
PolylineTextureDemoPage(String title, String subTitle)
|
||||
: super(title, subTitle);
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return _Body();
|
||||
}
|
||||
}
|
||||
|
||||
class _Body extends StatefulWidget {
|
||||
const _Body();
|
||||
class PolylineTextureDemoPage extends StatefulWidget {
|
||||
const PolylineTextureDemoPage();
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _State();
|
||||
}
|
||||
|
||||
class _State extends State<_Body> {
|
||||
class _State extends State<PolylineTextureDemoPage> {
|
||||
_State();
|
||||
|
||||
Map<String, Polyline> _polylines = <String, Polyline>{};
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
import 'package:amap_map_example/demo.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
typedef PathWidgetBuilder = Widget Function(BuildContext, String?);
|
||||
|
||||
class Path {
|
||||
const Path(this.pattern, this.builder);
|
||||
|
||||
/// A RegEx string for route matching.
|
||||
final String pattern;
|
||||
|
||||
/// The builder for the associated pattern route. The first argument is the
|
||||
/// [BuildContext] and the second argument a RegEx match if that is included
|
||||
/// in the pattern.
|
||||
///
|
||||
/// ```dart
|
||||
/// Path(
|
||||
/// 'r'^/([\w-]+)$',
|
||||
/// (context, matches) => Page(argument: match),
|
||||
/// )
|
||||
/// ```
|
||||
final PathWidgetBuilder builder;
|
||||
}
|
||||
|
||||
class RouteConfig {
|
||||
static List<Path> _paths = [
|
||||
Path(
|
||||
r'^/([\w-]+)$',
|
||||
(context, match) => DemoPage(slug: match),
|
||||
),
|
||||
];
|
||||
|
||||
static Route<dynamic>? onGenerateRoute(RouteSettings settings) {
|
||||
for (final path in _paths) {
|
||||
final regExpPattern = RegExp(path.pattern);
|
||||
if (regExpPattern.hasMatch(settings.name!)) {
|
||||
final firstMatch = regExpPattern.firstMatch(settings.name!)!;
|
||||
final match = (firstMatch.groupCount == 1) ? firstMatch.group(1) : null;
|
||||
|
||||
return MaterialPageRoute<void>(
|
||||
builder: (context) => path.builder(context, match),
|
||||
settings: settings,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class DemoThemeData {
|
||||
static const _lightFillColor = Colors.black;
|
||||
static const ColorScheme lightColorScheme = ColorScheme(
|
||||
primary: Color(0xFFB93C5D),
|
||||
primaryContainer: Color(0xFF117378),
|
||||
secondary: Color(0xFFEFF3F3),
|
||||
secondaryContainer: Color(0xFFFAFBFB),
|
||||
background: Color(0xFFE6EBEB),
|
||||
surface: Color(0xFFFAFBFB),
|
||||
onBackground: Colors.white,
|
||||
error: _lightFillColor,
|
||||
onError: _lightFillColor,
|
||||
onPrimary: _lightFillColor,
|
||||
onSecondary: Color(0xFF322942),
|
||||
onSurface: Color(0xFF241E30),
|
||||
brightness: Brightness.light,
|
||||
);
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
import 'package:amap_map_example/base_page.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class DemoGroupWidget extends StatefulWidget {
|
||||
final String groupLabel;
|
||||
final List<BasePage>? itemPages;
|
||||
|
||||
DemoGroupWidget({Key? key, required this.groupLabel, this.itemPages})
|
||||
: super(key: key);
|
||||
@override
|
||||
State<StatefulWidget> createState() => _GroupState();
|
||||
}
|
||||
|
||||
class _GroupState extends State<DemoGroupWidget> {
|
||||
void _pushPage(BuildContext context, BasePage page) {
|
||||
Navigator.of(context).push(MaterialPageRoute<void>(
|
||||
builder: (_) => Scaffold(
|
||||
appBar: AppBar(title: Text(page.title)),
|
||||
body: page,
|
||||
)));
|
||||
}
|
||||
|
||||
bool _hasItemPages = false;
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
if (widget.itemPages != null && widget.itemPages!.length > 0) {
|
||||
_hasItemPages = true;
|
||||
} else {
|
||||
_hasItemPages = false;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
ListTile(
|
||||
title: Text(
|
||||
widget.groupLabel,
|
||||
style: TextStyle(fontWeight: FontWeight.w600, fontSize: 18),
|
||||
)),
|
||||
Divider(height: 1),
|
||||
Container(
|
||||
padding: EdgeInsets.only(left: 10),
|
||||
child: _hasItemPages
|
||||
? ListView.separated(
|
||||
shrinkWrap: true,
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
itemCount: widget.itemPages!.length,
|
||||
itemBuilder: (_, int index) => ListTile(
|
||||
title: Text(widget.itemPages![index].title),
|
||||
subtitle: Text(widget.itemPages![index].subTitle),
|
||||
onTap: () => _pushPage(context, widget.itemPages![index]),
|
||||
),
|
||||
separatorBuilder: (BuildContext context, int index) =>
|
||||
Divider(
|
||||
height: 1,
|
||||
indent: 16,
|
||||
),
|
||||
)
|
||||
: null,
|
||||
),
|
||||
Divider(height: 1),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,136 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
//Toast 显示位置控制
|
||||
enum ToastPostion {
|
||||
top,
|
||||
center,
|
||||
bottom,
|
||||
}
|
||||
|
||||
class Toast {
|
||||
// toast靠它加到屏幕上
|
||||
static OverlayEntry? _overlayEntry;
|
||||
// toast是否正在showing
|
||||
static bool _showing = false;
|
||||
// 开启一个新toast的当前时间,用于对比是否已经展示了足够时间
|
||||
static DateTime? _startedTime;
|
||||
// 提示内容
|
||||
static String? _msg;
|
||||
// toast显示时间
|
||||
static int _showTime = 10;
|
||||
// 背景颜色
|
||||
static Color? _bgColor;
|
||||
// 文本颜色
|
||||
static Color? _textColor;
|
||||
// 文字大小
|
||||
static double? _textSize;
|
||||
// 显示位置
|
||||
static ToastPostion? _toastPosition;
|
||||
// 左右边距
|
||||
static double? _pdHorizontal;
|
||||
// 上下边距
|
||||
static double? _pdVertical;
|
||||
static void toast(
|
||||
BuildContext context, {
|
||||
//显示的文本
|
||||
String? msg,
|
||||
//显示的时间 单位毫秒
|
||||
int showTime = 1000,
|
||||
//显示的背景
|
||||
Color bgColor = Colors.black,
|
||||
//显示的文本颜色
|
||||
Color textColor = Colors.white,
|
||||
//显示的文字大小
|
||||
double textSize = 14.0,
|
||||
//显示的位置
|
||||
ToastPostion position = ToastPostion.center,
|
||||
//文字水平方向的内边距
|
||||
double pdHorizontal = 20.0,
|
||||
//文字垂直方向的内边距
|
||||
double pdVertical = 10.0,
|
||||
}) async {
|
||||
assert(msg != null);
|
||||
_msg = msg;
|
||||
_startedTime = DateTime.now();
|
||||
_showTime = showTime;
|
||||
_bgColor = bgColor;
|
||||
_textColor = textColor;
|
||||
_textSize = textSize;
|
||||
_toastPosition = position;
|
||||
_pdHorizontal = pdHorizontal;
|
||||
_pdVertical = pdVertical;
|
||||
//获取OverlayState
|
||||
OverlayState overlayState = Overlay.of(context)!;
|
||||
_showing = true;
|
||||
if (_overlayEntry == null) {
|
||||
//OverlayEntry负责构建布局
|
||||
//通过OverlayEntry将构建的布局插入到整个布局的最上层
|
||||
_overlayEntry = OverlayEntry(
|
||||
builder: (BuildContext context) => Positioned(
|
||||
//top值,可以改变这个值来改变toast在屏幕中的位置
|
||||
top: buildToastPosition(context),
|
||||
child: Container(
|
||||
alignment: Alignment.center,
|
||||
width: MediaQuery.of(context).size.width,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 40.0),
|
||||
child: AnimatedOpacity(
|
||||
opacity: _showing ? 1.0 : 0.0, //目标透明度
|
||||
duration: _showing
|
||||
? Duration(milliseconds: 100)
|
||||
: Duration(milliseconds: 400),
|
||||
child: _buildToastWidget(),
|
||||
),
|
||||
)),
|
||||
));
|
||||
//插入到整个布局的最上层
|
||||
overlayState.insert(_overlayEntry!);
|
||||
} else {
|
||||
//重新绘制UI,类似setState
|
||||
_overlayEntry!.markNeedsBuild();
|
||||
}
|
||||
// 等待时间
|
||||
await Future.delayed(Duration(milliseconds: _showTime));
|
||||
//2秒后 到底消失不消失
|
||||
if (DateTime.now().difference(_startedTime!).inMilliseconds >= _showTime) {
|
||||
_showing = false;
|
||||
_overlayEntry!.markNeedsBuild();
|
||||
await Future.delayed(Duration(milliseconds: 400));
|
||||
_overlayEntry!.remove();
|
||||
_overlayEntry = null;
|
||||
}
|
||||
}
|
||||
|
||||
//toast绘制
|
||||
static _buildToastWidget() {
|
||||
return Center(
|
||||
child: Card(
|
||||
color: _bgColor,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: _pdHorizontal!, vertical: _pdVertical!),
|
||||
child: Text(
|
||||
_msg!,
|
||||
style: TextStyle(
|
||||
fontSize: _textSize,
|
||||
color: _textColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// 设置toast位置
|
||||
static buildToastPosition(context) {
|
||||
var backResult;
|
||||
if (_toastPosition == ToastPostion.top) {
|
||||
backResult = MediaQuery.of(context).size.height * 1 / 4;
|
||||
} else if (_toastPosition == ToastPostion.center) {
|
||||
backResult = MediaQuery.of(context).size.height * 2 / 5;
|
||||
} else {
|
||||
backResult = MediaQuery.of(context).size.height * 3 / 4;
|
||||
}
|
||||
return backResult;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue