Loading...
Searching...
No Matches
default_navigation_view.dart
Go to the documentation of this file.
1import 'package:flutter/material.dart';
2import 'package:navigine_sdk/com/navigine/idl/camera_listener.dart';
3import 'package:navigine_sdk/com/navigine/idl/camera_update_reason.dart';
4import 'package:navigine_sdk/com/navigine/idl/location_window.dart';
5import 'package:navigine_sdk/com/navigine/idl/navigine_sdk.dart';
6import 'package:navigine_sdk/com/navigine/idl/user_location_layer.dart';
7import 'dart:math' as math;
8import 'default_navigine_view.dart';
9import 'default_navigine_view_config.dart';
10import 'default_navigation_view_config.dart';
11import 'widgets/zoom_controls_config.dart';
12import 'widgets/floor_selector_view_config.dart';
13import 'widgets/follow_me_button.dart';
14import 'widgets/follow_me_button_config.dart';
15
43class DefaultNavigationView extends StatefulWidget {
45 Key? key,
46 required this.onViewCreated,
48 this.zoomControlsConfig = ZoomControlsConfig.defaultConfig,
49 this.followMeButtonConfig = FollowMeButtonConfig.defaultConfig,
50 this.floorSelectorConfig = FloorSelectorViewConfig.defaultConfig,
51 this.configController,
52 this.textDirection,
53 }) : super(key: key);
54
55 final void Function(LocationWindow) onViewCreated;
56 final DefaultNavigationViewConfig viewConfig;
57 final ZoomControlsConfig zoomControlsConfig;
58 final FollowMeButtonConfig followMeButtonConfig;
59 final FloorSelectorViewConfig floorSelectorConfig;
60 final DefaultNavigationViewController? configController;
61 final TextDirection? textDirection;
62
63 @override
64 State<DefaultNavigationView> createState() => _DefaultNavigationViewState();
65}
66
67class _DefaultNavigationViewState extends State<DefaultNavigationView>
68 implements CameraListener {
70 LocationWindow? _locationWindow;
71 bool _isFollowing = false;
72
73 DefaultNavigineViewConfig get _chromeConfig => DefaultNavigineViewConfig(
74 visibleWidgets:
75 widget.viewConfig.visibleWidgets & NavigineWidgetVisibility.all,
76 );
77
78 void _handleViewCreated(LocationWindow window) {
79 _locationWindow = window;
80 window.addCameraListener(this);
82 _userLocationLayer!.setVisible(true);
83 widget.onViewCreated(window);
84 }
85
86 @override
87 void dispose() {
88 _locationWindow?.removeCameraListener(this);
89 super.dispose();
90 }
91
92 @override
93 void didChangeDependencies() {
94 super.didChangeDependencies();
95
96 if (_isFollowing) {
97 WidgetsBinding.instance.addPostFrameCallback((_) {
98 if (mounted && _isFollowing) {
99 _updateFollowMeAnchor();
100 }
101 });
102 }
103 }
104
105 void _handleFollowMePressed() {
106 if (!mounted || _userLocationLayer == null) return;
107
108 if (!_isFollowing) {
109 _updateFollowMeAnchor();
110 } else {
111 _userLocationLayer!.resetAnchor();
112 }
113 setState(() {
114 _isFollowing = !_isFollowing;
115 });
116 }
117
118 void _updateFollowMeAnchor() {
119 if (!mounted || _userLocationLayer == null) return;
120
121 final mediaQuery = MediaQuery.of(context);
122 final screenSize = context.size ?? mediaQuery.size;
123 final devicePixelRatio = mediaQuery.devicePixelRatio;
124 _userLocationLayer!.setAnchor(math.Point<double>(
125 screenSize.width * devicePixelRatio / 2,
126 screenSize.height * devicePixelRatio / 2,
127 ));
128 }
129
130 List<Widget> _followMeOverlays(
131 FollowMeButtonConfig followMeConfig, int visibleWidgets) {
132 if ((visibleWidgets & NavigationWidgetVisibility.followMeButton) == 0) {
133 return const [];
134 }
135 return [
136 FollowMeButton(
137 isFollowing: _isFollowing,
138 onPressed: _handleFollowMePressed,
139 config: followMeConfig,
140 ),
141 ];
142 }
143
144 @override
145 Widget build(BuildContext context) {
146 if (widget.configController != null) {
147 return ListenableBuilder(
148 listenable: widget.configController!,
149 builder: (context, _) {
150 final vc = widget.configController!.viewConfig;
151 return DefaultNavigineView(
152 onViewCreated: _handleViewCreated,
153 viewConfig: DefaultNavigineViewConfig(
154 visibleWidgets: vc.visibleWidgets & NavigineWidgetVisibility.all,
155 ),
156 zoomControlsConfig: widget.configController!.zoomControlsConfig,
157 floorSelectorConfig: widget.configController!.floorSelectorConfig,
158 textDirection: widget.textDirection,
159 extraOverlays: _followMeOverlays(
160 widget.configController!.followMeButtonConfig,
161 vc.visibleWidgets,
162 ),
163 );
164 },
165 );
166 }
167 return DefaultNavigineView(
168 onViewCreated: _handleViewCreated,
169 viewConfig: _chromeConfig,
170 zoomControlsConfig: widget.zoomControlsConfig,
171 floorSelectorConfig: widget.floorSelectorConfig,
172 textDirection: widget.textDirection,
173 extraOverlays: _followMeOverlays(
174 widget.followMeButtonConfig,
175 widget.viewConfig.visibleWidgets,
176 ),
177 );
178 }
179
180 @override
181 void onCameraPositionChanged(CameraUpdateReason reason, bool finished) {
182 if (reason == CameraUpdateReason.APPLICATION) {
183 return;
184 }
185
186 if (_isFollowing && _userLocationLayer != null) {
187 _userLocationLayer!.resetAnchor();
188 setState(() {
189 _isFollowing = false;
190 });
191 }
192 }
193}