map: removed app bar, added overlay back button
This commit is contained in:
parent
4c13f665df
commit
9a59bec05a
8 changed files with 78 additions and 53 deletions
|
@ -791,9 +791,6 @@
|
||||||
"settingsCoordinateFormatTitle": "Coordinate Format",
|
"settingsCoordinateFormatTitle": "Coordinate Format",
|
||||||
"@settingsCoordinateFormatTitle": {},
|
"@settingsCoordinateFormatTitle": {},
|
||||||
|
|
||||||
"mapPageTitle": "Map",
|
|
||||||
"@mapPageTitle": {},
|
|
||||||
|
|
||||||
"statsPageTitle": "Stats",
|
"statsPageTitle": "Stats",
|
||||||
"@statsPageTitle": {},
|
"@statsPageTitle": {},
|
||||||
"statsImage": "{count, plural, =1{image} other{images}}",
|
"statsImage": "{count, plural, =1{image} other{images}}",
|
||||||
|
@ -858,14 +855,16 @@
|
||||||
"viewerInfoLabelAddress": "Address",
|
"viewerInfoLabelAddress": "Address",
|
||||||
"@viewerInfoLabelAddress": {},
|
"@viewerInfoLabelAddress": {},
|
||||||
|
|
||||||
"viewerInfoMapStyleTitle": "Map Style",
|
"mapStyleTitle": "Map Style",
|
||||||
"@viewerInfoMapStyleTitle": {},
|
"@mapStyleTitle": {},
|
||||||
"viewerInfoMapStyleTooltip": "Select map style",
|
"mapStyleTooltip": "Select map style",
|
||||||
"@viewerInfoMapStyleTooltip": {},
|
"@mapStyleTooltip": {},
|
||||||
"viewerInfoMapZoomInTooltip": "Zoom in",
|
"mapZoomInTooltip": "Zoom in",
|
||||||
"@viewerInfoMapZoomInTooltip": {},
|
"@mapZoomInTooltip": {},
|
||||||
"viewerInfoMapZoomOutTooltip": "Zoom out",
|
"mapZoomOutTooltip": "Zoom out",
|
||||||
"@viewerInfoMapZoomOutTooltip": {},
|
"@mapZoomOutTooltip": {},
|
||||||
|
"mapPointNorthUpTooltip": "Point north up",
|
||||||
|
"@mapPointNorthUpTooltip": {},
|
||||||
"mapAttributionOsmHot": "Map data © [OpenStreetMap](https://www.openstreetmap.org/copyright) contributors • Tiles by [HOT](https://www.hotosm.org/) • Hosted by [OSM France](https://openstreetmap.fr/)",
|
"mapAttributionOsmHot": "Map data © [OpenStreetMap](https://www.openstreetmap.org/copyright) contributors • Tiles by [HOT](https://www.hotosm.org/) • Hosted by [OSM France](https://openstreetmap.fr/)",
|
||||||
"@mapAttributionOsmHot": {},
|
"@mapAttributionOsmHot": {},
|
||||||
"mapAttributionStamen": "Map data © [OpenStreetMap](https://www.openstreetmap.org/copyright) contributors • Tiles by [Stamen Design](http://stamen.com), [CC BY 3.0](http://creativecommons.org/licenses/by/3.0)",
|
"mapAttributionStamen": "Map data © [OpenStreetMap](https://www.openstreetmap.org/copyright) contributors • Tiles by [Stamen Design](http://stamen.com), [CC BY 3.0](http://creativecommons.org/licenses/by/3.0)",
|
||||||
|
|
|
@ -389,8 +389,6 @@
|
||||||
"settingsCoordinateFormatTile": "좌표 표현",
|
"settingsCoordinateFormatTile": "좌표 표현",
|
||||||
"settingsCoordinateFormatTitle": "좌표 표현",
|
"settingsCoordinateFormatTitle": "좌표 표현",
|
||||||
|
|
||||||
"mapPageTitle": "지도",
|
|
||||||
|
|
||||||
"statsPageTitle": "통계",
|
"statsPageTitle": "통계",
|
||||||
"statsImage": "{count, plural, other{사진}}",
|
"statsImage": "{count, plural, other{사진}}",
|
||||||
"statsVideo": "{count, plural, other{동영상}}",
|
"statsVideo": "{count, plural, other{동영상}}",
|
||||||
|
@ -419,10 +417,11 @@
|
||||||
"viewerInfoLabelCoordinates": "좌표",
|
"viewerInfoLabelCoordinates": "좌표",
|
||||||
"viewerInfoLabelAddress": "주소",
|
"viewerInfoLabelAddress": "주소",
|
||||||
|
|
||||||
"viewerInfoMapStyleTitle": "지도 유형",
|
"mapStyleTitle": "지도 유형",
|
||||||
"viewerInfoMapStyleTooltip": "지도 유형 선택",
|
"mapStyleTooltip": "지도 유형 선택",
|
||||||
"viewerInfoMapZoomInTooltip": "확대",
|
"mapZoomInTooltip": "확대",
|
||||||
"viewerInfoMapZoomOutTooltip": "축소",
|
"mapZoomOutTooltip": "축소",
|
||||||
|
"mapPointNorthUpTooltip": "북쪽을 위로 가리키기",
|
||||||
"mapAttributionOsmHot": "지도 데이터 © [OpenStreetMap](https://www.openstreetmap.org/copyright) 기여자 • 타일 [HOT](https://www.hotosm.org/) • 호스팅 [OSM France](https://openstreetmap.fr/)",
|
"mapAttributionOsmHot": "지도 데이터 © [OpenStreetMap](https://www.openstreetmap.org/copyright) 기여자 • 타일 [HOT](https://www.hotosm.org/) • 호스팅 [OSM France](https://openstreetmap.fr/)",
|
||||||
"mapAttributionStamen": "지도 데이터 © [OpenStreetMap](https://www.openstreetmap.org/copyright) 기여자 • 타일 [Stamen Design](http://stamen.com), [CC BY 3.0](http://creativecommons.org/licenses/by/3.0)",
|
"mapAttributionStamen": "지도 데이터 © [OpenStreetMap](https://www.openstreetmap.org/copyright) 기여자 • 타일 [Stamen Design](http://stamen.com), [CC BY 3.0](http://creativecommons.org/licenses/by/3.0)",
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ import 'package:flutter/scheduler.dart';
|
||||||
import 'package:latlong2/latlong.dart';
|
import 'package:latlong2/latlong.dart';
|
||||||
|
|
||||||
class MapButtonPanel extends StatelessWidget {
|
class MapButtonPanel extends StatelessWidget {
|
||||||
|
final bool showBackButton;
|
||||||
final ValueNotifier<ZoomedBounds> boundsNotifier;
|
final ValueNotifier<ZoomedBounds> boundsNotifier;
|
||||||
final Future<void> Function(double amount)? zoomBy;
|
final Future<void> Function(double amount)? zoomBy;
|
||||||
final VoidCallback? resetRotation;
|
final VoidCallback? resetRotation;
|
||||||
|
@ -26,6 +27,7 @@ class MapButtonPanel extends StatelessWidget {
|
||||||
|
|
||||||
const MapButtonPanel({
|
const MapButtonPanel({
|
||||||
Key? key,
|
Key? key,
|
||||||
|
required this.showBackButton,
|
||||||
required this.boundsNotifier,
|
required this.boundsNotifier,
|
||||||
this.zoomBy,
|
this.zoomBy,
|
||||||
this.resetRotation,
|
this.resetRotation,
|
||||||
|
@ -46,34 +48,51 @@ class MapButtonPanel extends StatelessWidget {
|
||||||
),
|
),
|
||||||
child: Stack(
|
child: Stack(
|
||||||
children: [
|
children: [
|
||||||
if (resetRotation != null)
|
Positioned(
|
||||||
Positioned(
|
left: 0,
|
||||||
left: 0,
|
child: Column(
|
||||||
child: ValueListenableBuilder<ZoomedBounds>(
|
mainAxisSize: MainAxisSize.min,
|
||||||
valueListenable: boundsNotifier,
|
children: [
|
||||||
builder: (context, bounds, child) {
|
if (showBackButton)
|
||||||
final degrees = bounds.rotation;
|
MapOverlayButton(
|
||||||
return AnimatedOpacity(
|
icon: const BackButtonIcon(),
|
||||||
opacity: degrees == 0 ? 0 : 1,
|
onPressed: () => Navigator.pop(context),
|
||||||
duration: Durations.viewerOverlayAnimation,
|
tooltip: MaterialLocalizations.of(context).backButtonTooltip,
|
||||||
child: MapOverlayButton(
|
),
|
||||||
icon: Transform(
|
if (resetRotation != null) ...[
|
||||||
origin: iconSize.center(Offset.zero),
|
const SizedBox(height: padding),
|
||||||
transform: Matrix4.rotationZ(degToRadian(degrees)),
|
ValueListenableBuilder<ZoomedBounds>(
|
||||||
child: CustomPaint(
|
valueListenable: boundsNotifier,
|
||||||
painter: CompassPainter(
|
builder: (context, bounds, child) {
|
||||||
color: iconTheme.color!,
|
final degrees = bounds.rotation;
|
||||||
|
final opacity = degrees == 0 ? .0 : 1.0;
|
||||||
|
return IgnorePointer(
|
||||||
|
ignoring: opacity == 0,
|
||||||
|
child: AnimatedOpacity(
|
||||||
|
opacity: opacity,
|
||||||
|
duration: Durations.viewerOverlayAnimation,
|
||||||
|
child: MapOverlayButton(
|
||||||
|
icon: Transform(
|
||||||
|
origin: iconSize.center(Offset.zero),
|
||||||
|
transform: Matrix4.rotationZ(degToRadian(degrees)),
|
||||||
|
child: CustomPaint(
|
||||||
|
painter: CompassPainter(
|
||||||
|
color: iconTheme.color!,
|
||||||
|
),
|
||||||
|
size: iconSize,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onPressed: () => resetRotation?.call(),
|
||||||
|
tooltip: context.l10n.mapPointNorthUpTooltip,
|
||||||
),
|
),
|
||||||
size: iconSize,
|
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
onPressed: () => resetRotation?.call(),
|
},
|
||||||
tooltip: context.l10n.viewerInfoMapZoomInTooltip,
|
),
|
||||||
),
|
],
|
||||||
);
|
],
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
|
),
|
||||||
Positioned(
|
Positioned(
|
||||||
right: 0,
|
right: 0,
|
||||||
child: Column(
|
child: Column(
|
||||||
|
@ -100,7 +119,7 @@ class MapButtonPanel extends StatelessWidget {
|
||||||
return AvesSelectionDialog<EntryMapStyle>(
|
return AvesSelectionDialog<EntryMapStyle>(
|
||||||
initialValue: initialStyle,
|
initialValue: initialStyle,
|
||||||
options: Map.fromEntries(availableStyles.map((v) => MapEntry(v, v.getName(context)))),
|
options: Map.fromEntries(availableStyles.map((v) => MapEntry(v, v.getName(context)))),
|
||||||
title: context.l10n.viewerInfoMapStyleTitle,
|
title: context.l10n.mapStyleTitle,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -110,7 +129,7 @@ class MapButtonPanel extends StatelessWidget {
|
||||||
settings.infoMapStyle = style;
|
settings.infoMapStyle = style;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
tooltip: context.l10n.viewerInfoMapStyleTooltip,
|
tooltip: context.l10n.mapStyleTooltip,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -124,13 +143,13 @@ class MapButtonPanel extends StatelessWidget {
|
||||||
MapOverlayButton(
|
MapOverlayButton(
|
||||||
icon: const Icon(AIcons.zoomIn),
|
icon: const Icon(AIcons.zoomIn),
|
||||||
onPressed: zoomBy != null ? () => zoomBy?.call(1) : null,
|
onPressed: zoomBy != null ? () => zoomBy?.call(1) : null,
|
||||||
tooltip: context.l10n.viewerInfoMapZoomInTooltip,
|
tooltip: context.l10n.mapZoomInTooltip,
|
||||||
),
|
),
|
||||||
const SizedBox(height: padding),
|
const SizedBox(height: padding),
|
||||||
MapOverlayButton(
|
MapOverlayButton(
|
||||||
icon: const Icon(AIcons.zoomOut),
|
icon: const Icon(AIcons.zoomOut),
|
||||||
onPressed: zoomBy != null ? () => zoomBy?.call(-1) : null,
|
onPressed: zoomBy != null ? () => zoomBy?.call(-1) : null,
|
||||||
tooltip: context.l10n.viewerInfoMapZoomOutTooltip,
|
tooltip: context.l10n.mapZoomOutTooltip,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
|
@ -27,7 +27,7 @@ import 'package:provider/provider.dart';
|
||||||
class GeoMap extends StatefulWidget {
|
class GeoMap extends StatefulWidget {
|
||||||
final AvesMapController? controller;
|
final AvesMapController? controller;
|
||||||
final List<AvesEntry> entries;
|
final List<AvesEntry> entries;
|
||||||
final bool interactive;
|
final bool interactive, showBackButton;
|
||||||
final double? mapHeight;
|
final double? mapHeight;
|
||||||
final ValueNotifier<bool> isAnimatingNotifier;
|
final ValueNotifier<bool> isAnimatingNotifier;
|
||||||
final UserZoomChangeCallback? onUserZoomChange;
|
final UserZoomChangeCallback? onUserZoomChange;
|
||||||
|
@ -41,6 +41,7 @@ class GeoMap extends StatefulWidget {
|
||||||
this.controller,
|
this.controller,
|
||||||
required this.entries,
|
required this.entries,
|
||||||
required this.interactive,
|
required this.interactive,
|
||||||
|
required this.showBackButton,
|
||||||
this.mapHeight,
|
this.mapHeight,
|
||||||
required this.isAnimatingNotifier,
|
required this.isAnimatingNotifier,
|
||||||
this.onUserZoomChange,
|
this.onUserZoomChange,
|
||||||
|
@ -65,6 +66,8 @@ class _GeoMapState extends State<GeoMap> {
|
||||||
|
|
||||||
bool get interactive => widget.interactive;
|
bool get interactive => widget.interactive;
|
||||||
|
|
||||||
|
bool get showBackButton => widget.showBackButton;
|
||||||
|
|
||||||
double? get mapHeight => widget.mapHeight;
|
double? get mapHeight => widget.mapHeight;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -137,6 +140,7 @@ class _GeoMapState extends State<GeoMap> {
|
||||||
controller: widget.controller,
|
controller: widget.controller,
|
||||||
boundsNotifier: _boundsNotifier,
|
boundsNotifier: _boundsNotifier,
|
||||||
interactive: interactive,
|
interactive: interactive,
|
||||||
|
showBackButton: showBackButton,
|
||||||
minZoom: 0,
|
minZoom: 0,
|
||||||
maxZoom: 20,
|
maxZoom: 20,
|
||||||
style: mapStyle,
|
style: mapStyle,
|
||||||
|
@ -149,6 +153,7 @@ class _GeoMapState extends State<GeoMap> {
|
||||||
controller: widget.controller,
|
controller: widget.controller,
|
||||||
boundsNotifier: _boundsNotifier,
|
boundsNotifier: _boundsNotifier,
|
||||||
interactive: interactive,
|
interactive: interactive,
|
||||||
|
showBackButton: showBackButton,
|
||||||
minZoom: 2,
|
minZoom: 2,
|
||||||
maxZoom: 16,
|
maxZoom: 16,
|
||||||
style: mapStyle,
|
style: mapStyle,
|
||||||
|
@ -191,6 +196,7 @@ class _GeoMapState extends State<GeoMap> {
|
||||||
interactive: interactive,
|
interactive: interactive,
|
||||||
),
|
),
|
||||||
MapButtonPanel(
|
MapButtonPanel(
|
||||||
|
showBackButton: showBackButton,
|
||||||
boundsNotifier: _boundsNotifier,
|
boundsNotifier: _boundsNotifier,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
@ -18,7 +18,7 @@ import 'package:latlong2/latlong.dart' as ll;
|
||||||
class EntryGoogleMap extends StatefulWidget {
|
class EntryGoogleMap extends StatefulWidget {
|
||||||
final AvesMapController? controller;
|
final AvesMapController? controller;
|
||||||
final ValueNotifier<ZoomedBounds> boundsNotifier;
|
final ValueNotifier<ZoomedBounds> boundsNotifier;
|
||||||
final bool interactive;
|
final bool interactive, showBackButton;
|
||||||
final double? minZoom, maxZoom;
|
final double? minZoom, maxZoom;
|
||||||
final EntryMapStyle style;
|
final EntryMapStyle style;
|
||||||
final MarkerClusterBuilder markerClusterBuilder;
|
final MarkerClusterBuilder markerClusterBuilder;
|
||||||
|
@ -31,6 +31,7 @@ class EntryGoogleMap extends StatefulWidget {
|
||||||
this.controller,
|
this.controller,
|
||||||
required this.boundsNotifier,
|
required this.boundsNotifier,
|
||||||
required this.interactive,
|
required this.interactive,
|
||||||
|
required this.showBackButton,
|
||||||
this.minZoom,
|
this.minZoom,
|
||||||
this.maxZoom,
|
this.maxZoom,
|
||||||
required this.style,
|
required this.style,
|
||||||
|
@ -126,6 +127,7 @@ class _EntryGoogleMapState extends State<EntryGoogleMap> with WidgetsBindingObse
|
||||||
child: _buildMap(),
|
child: _buildMap(),
|
||||||
),
|
),
|
||||||
MapButtonPanel(
|
MapButtonPanel(
|
||||||
|
showBackButton: widget.showBackButton,
|
||||||
boundsNotifier: boundsNotifier,
|
boundsNotifier: boundsNotifier,
|
||||||
zoomBy: _zoomBy,
|
zoomBy: _zoomBy,
|
||||||
resetRotation: interactive ? _resetRotation : null,
|
resetRotation: interactive ? _resetRotation : null,
|
||||||
|
|
|
@ -19,7 +19,7 @@ import 'package:latlong2/latlong.dart';
|
||||||
class EntryLeafletMap extends StatefulWidget {
|
class EntryLeafletMap extends StatefulWidget {
|
||||||
final AvesMapController? controller;
|
final AvesMapController? controller;
|
||||||
final ValueNotifier<ZoomedBounds> boundsNotifier;
|
final ValueNotifier<ZoomedBounds> boundsNotifier;
|
||||||
final bool interactive;
|
final bool interactive, showBackButton;
|
||||||
final double minZoom, maxZoom;
|
final double minZoom, maxZoom;
|
||||||
final EntryMapStyle style;
|
final EntryMapStyle style;
|
||||||
final MarkerClusterBuilder markerClusterBuilder;
|
final MarkerClusterBuilder markerClusterBuilder;
|
||||||
|
@ -33,6 +33,7 @@ class EntryLeafletMap extends StatefulWidget {
|
||||||
this.controller,
|
this.controller,
|
||||||
required this.boundsNotifier,
|
required this.boundsNotifier,
|
||||||
required this.interactive,
|
required this.interactive,
|
||||||
|
required this.showBackButton,
|
||||||
this.minZoom = 0,
|
this.minZoom = 0,
|
||||||
this.maxZoom = 22,
|
this.maxZoom = 22,
|
||||||
required this.style,
|
required this.style,
|
||||||
|
@ -107,6 +108,7 @@ class _EntryLeafletMapState extends State<EntryLeafletMap> with TickerProviderSt
|
||||||
child: _buildMap(),
|
child: _buildMap(),
|
||||||
),
|
),
|
||||||
MapButtonPanel(
|
MapButtonPanel(
|
||||||
|
showBackButton: widget.showBackButton,
|
||||||
boundsNotifier: boundsNotifier,
|
boundsNotifier: boundsNotifier,
|
||||||
zoomBy: _zoomBy,
|
zoomBy: _zoomBy,
|
||||||
resetRotation: interactive ? _resetRotation : null,
|
resetRotation: interactive ? _resetRotation : null,
|
||||||
|
|
|
@ -3,7 +3,6 @@ import 'package:aves/model/settings/map_style.dart';
|
||||||
import 'package:aves/model/settings/settings.dart';
|
import 'package:aves/model/settings/settings.dart';
|
||||||
import 'package:aves/theme/durations.dart';
|
import 'package:aves/theme/durations.dart';
|
||||||
import 'package:aves/utils/debouncer.dart';
|
import 'package:aves/utils/debouncer.dart';
|
||||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
|
||||||
import 'package:aves/widgets/common/map/controller.dart';
|
import 'package:aves/widgets/common/map/controller.dart';
|
||||||
import 'package:aves/widgets/common/map/geo_map.dart';
|
import 'package:aves/widgets/common/map/geo_map.dart';
|
||||||
import 'package:aves/widgets/common/providers/media_query_data_provider.dart';
|
import 'package:aves/widgets/common/providers/media_query_data_provider.dart';
|
||||||
|
@ -61,9 +60,6 @@ class _MapPageState extends State<MapPage> {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MediaQueryDataProvider(
|
return MediaQueryDataProvider(
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
appBar: AppBar(
|
|
||||||
title: Text(context.l10n.mapPageTitle),
|
|
||||||
),
|
|
||||||
body: SafeArea(
|
body: SafeArea(
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
@ -73,6 +69,7 @@ class _MapPageState extends State<MapPage> {
|
||||||
controller: _mapController,
|
controller: _mapController,
|
||||||
entries: entries,
|
entries: entries,
|
||||||
interactive: true,
|
interactive: true,
|
||||||
|
showBackButton: true,
|
||||||
isAnimatingNotifier: _isAnimatingNotifier,
|
isAnimatingNotifier: _isAnimatingNotifier,
|
||||||
onMarkerTap: (markerEntry, getClusterEntries) {
|
onMarkerTap: (markerEntry, getClusterEntries) {
|
||||||
final index = entries.indexOf(markerEntry);
|
final index = entries.indexOf(markerEntry);
|
||||||
|
|
|
@ -85,6 +85,7 @@ class _LocationSectionState extends State<LocationSection> {
|
||||||
GeoMap(
|
GeoMap(
|
||||||
entries: [entry],
|
entries: [entry],
|
||||||
interactive: false,
|
interactive: false,
|
||||||
|
showBackButton: false,
|
||||||
mapHeight: 200,
|
mapHeight: 200,
|
||||||
isAnimatingNotifier: widget.isScrollingNotifier,
|
isAnimatingNotifier: widget.isScrollingNotifier,
|
||||||
onUserZoomChange: (zoom) => settings.infoMapZoom = zoom,
|
onUserZoomChange: (zoom) => settings.infoMapZoom = zoom,
|
||||||
|
|
Loading…
Reference in a new issue