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/building.dart';
3import 'package:navigine_sdk/com/navigine/idl/building_listener.dart';
4import 'package:navigine_sdk/com/navigine/idl/location_window.dart';
5import 'package:navigine_sdk/com/navigine/idl/sublocation_change_listener.dart';
6import 'package:navigine_sdk/com/navigine/idl/navigine_sdk.dart';
7import 'package:navigine_sdk/com/navigine/idl/user_location_layer.dart';
8import 'package:navigine_sdk/com/navigine/idl/camera_listener.dart';
9import 'package:navigine_sdk/com/navigine/idl/camera_update_reason.dart';
10import 'package:navigine_sdk/location_view.dart';
11import 'dart:math' as math;
12import 'default_navigation_view_config.dart';
13import 'widgets/zoom_controls.dart';
14import 'widgets/zoom_controls_config.dart';
15import 'widgets/floor_selector_view.dart';
16import 'widgets/floor_selector_view_config.dart';
17import 'widgets/follow_me_button.dart';
18import 'widgets/follow_me_button_config.dart';
19
48class DefaultNavigationView extends StatefulWidget {
50 Key? key,
51 required this.onViewCreated,
53 this.zoomControlsConfig = ZoomControlsConfig.defaultConfig,
54 this.followMeButtonConfig = FollowMeButtonConfig.defaultConfig,
55 this.floorSelectorConfig = FloorSelectorViewConfig.defaultConfig,
56 this.configController,
57 this.textDirection,
58 }) : super(key: key);
59
60 final void Function(LocationWindow) onViewCreated;
61 final DefaultNavigationViewConfig viewConfig;
62 final ZoomControlsConfig zoomControlsConfig;
63 final FollowMeButtonConfig followMeButtonConfig;
64 final FloorSelectorViewConfig floorSelectorConfig;
65 final DefaultNavigationViewController? configController;
66 final TextDirection? textDirection;
67
68 @override
69 State<DefaultNavigationView> createState() => _DefaultNavigationViewState();
70}
71
72class _DefaultNavigationViewState extends State<DefaultNavigationView>
74 LocationWindow? _locationWindow;
76 final GlobalKey<FloorSelectorViewState> _floorSelectorKey = GlobalKey<FloorSelectorViewState>();
77 bool _isFollowing = false;
79 bool _floorSelectorVisibleForBuildingFocus = false;
80
81 @override
82 void dispose() {
83 _locationWindow?.removeBuildingListener(this);
84 _locationWindow?.removeSublocationChangeListener(this);
85 _locationWindow?.removeCameraListener(this);
86 super.dispose();
87 }
88
89 void _handleViewCreated(LocationWindow window) {
90 setState(() {
91 _locationWindow = window;
92 });
94 window.addCameraListener(this);
95 window.addBuildingListener(this);
96 _userLocationLayer = NavigineSdk.getInstance().getUserLocationLayer(window);
97 _userLocationLayer!.setVisible(true);
98 widget.onViewCreated(window);
99 }
100
101 Widget _buildContent(
102 DefaultNavigationViewConfig viewConfig,
103 ZoomControlsConfig zoomConfig,
104 FollowMeButtonConfig followMeConfig,
105 FloorSelectorViewConfig floorConfig,
106 ) {
107 final children = <Widget>[
108 LocationView(
109 onViewCreated: _handleViewCreated,
110 textDirection: widget.textDirection,
111 ),
112 ];
113 if ((viewConfig.visibleWidgets & NavigationWidgetVisibility.zoomControls) != 0) {
114 children.add(ZoomControls(
115 zoomInPressed: () {
116 if (_locationWindow == null) return;
117 _locationWindow!.zoomFactor = _locationWindow!.zoomFactor * (3.0 / 2.0);
118 },
119 zoomOutPressed: () {
120 if (_locationWindow == null) return;
121 _locationWindow!.zoomFactor = _locationWindow!.zoomFactor * (2.0 / 3.0);
122 },
123 config: zoomConfig,
124 ));
125 }
126 children.add(Visibility(
127 visible: (viewConfig.visibleWidgets & NavigationWidgetVisibility.floorSelector) != 0
128 && _floorSelectorVisibleForBuildingFocus,
129 maintainState: true,
130 child: FloorSelectorView(
131 key: _floorSelectorKey,
132 onFloorSelected: (id, name) => _locationWindow?.setSublocationId(id),
133 config: floorConfig,
134 ),
135 ));
136 if ((viewConfig.visibleWidgets & NavigationWidgetVisibility.followMeButton) != 0) {
137 children.add(FollowMeButton(
138 isFollowing: _isFollowing,
139 onPressed: _handleFollowMePressed,
140 config: followMeConfig,
141 ));
142 }
143 return Stack(children: children);
144 }
145
146 @override
147 Widget build(BuildContext context) {
148 if (widget.configController != null) {
149 return ListenableBuilder(
150 listenable: widget.configController!,
151 builder: (context, _) => _buildContent(
152 widget.configController!.viewConfig,
153 widget.configController!.zoomControlsConfig,
154 widget.configController!.followMeButtonConfig,
155 widget.configController!.floorSelectorConfig,
156 ),
157 );
158 }
159 return _buildContent(
160 widget.viewConfig,
161 widget.zoomControlsConfig,
162 widget.followMeButtonConfig,
163 widget.floorSelectorConfig,
164 );
165 }
166
167 void _handleFollowMePressed() {
168 if (!mounted || _userLocationLayer == null) return;
169
170 if (!_isFollowing) {
171 final screenSize = MediaQuery.of(context).size;
172 final devicePixelRatio = MediaQuery.of(context).devicePixelRatio;
173 _userLocationLayer!.setAnchor(math.Point<double>(
174 screenSize.width * devicePixelRatio / 2,
175 screenSize.height * devicePixelRatio / 2,
176 ));
177 } else {
178 _userLocationLayer!.resetAnchor();
179 }
180 setState(() {
181 _isFollowing = !_isFollowing;
182 });
183 }
184
185 @override
186 void onActiveBuildingFocused(Building activeBuilding) {
187 final floors = <LevelInfo>[];
188 for (final s in activeBuilding.sublocations) {
189 floors.add(LevelInfo(levelId: s.levelId, sublocationId: s.id));
190 }
191 setState(() {
192 _floorSelectorVisibleForBuildingFocus = true;
193 });
194 WidgetsBinding.instance.addPostFrameCallback((_) {
195 if (!mounted) return;
196 final selector = _floorSelectorKey.currentState;
197 selector?.setFloors(floors);
198 selector?.setSublocationId(activeBuilding.getActiveSublocationId());
199 });
200 }
201
202 @override
203 void onActiveBuildingLeft() {
204 setState(() {
205 _floorSelectorVisibleForBuildingFocus = false;
206 });
207 _floorSelectorKey.currentState?.setFloors([]);
208 }
209
210 @override
211 void onActiveSublocationChanged(int sublocationId) {
212 _floorSelectorKey.currentState?.setSublocationId(sublocationId);
213 }
214
215 @override
216 void onCameraPositionChanged(CameraUpdateReason reason, bool finished) {
217 if (reason == CameraUpdateReason.APPLICATION) {
218 return;
219 }
220
221 if (_isFollowing && _userLocationLayer != null) {
222 _userLocationLayer!.resetAnchor();
223 setState(() {
224 _isFollowing = false;
225 });
226 }
227 }
228}