summaryrefslogtreecommitdiffstats
path: root/lib/mapbox.dart
diff options
context:
space:
mode:
authorHritik Chouhan <hritikc3961@gmail.com>2022-09-01 21:47:45 +0200
committerHritik Chouhan <hritikc3961@gmail.com>2022-09-21 12:25:15 +0200
commit0e820517cbcc6d799cf7f23c7041f3f15b732dc0 (patch)
tree93b40a2310e867a2bca5a553dbc0b567f65fb62a /lib/mapbox.dart
parent03bb9f818d8caad2213e93e25f085b8672e5ceed (diff)
Upload Flutter-Navigation app for IVI
Flutter Navigation app which Shows current location, Route for destination, search for destination in search bar, turn by turn navigation,duration and distance for destination. Used Mapbox api and Flutter_map plugin and integrated with KUKSA.VAL for current location. Update UI ,Removed unused code and remove hard coded access token. Bug-AGL: SPEC-4548 Signed-off-by: Hritik Chouhan <hritikc3961@gmail.com> Change-Id: I7314285f7b9cdc6940175758761fcc8615c5ab0e
Diffstat (limited to 'lib/mapbox.dart')
-rw-r--r--lib/mapbox.dart293
1 files changed, 293 insertions, 0 deletions
diff --git a/lib/mapbox.dart b/lib/mapbox.dart
new file mode 100644
index 0000000..f7bf91e
--- /dev/null
+++ b/lib/mapbox.dart
@@ -0,0 +1,293 @@
+// SPDX-License-Identifier: Apache-2.0
+
+import 'dart:async';
+
+import 'package:flutter/material.dart';
+import 'package:mapbox_search/mapbox_search.dart';
+
+class MapBoxPlaceSearchWidget extends StatefulWidget {
+ MapBoxPlaceSearchWidget({
+ required this.apiKey,
+ required this.onSelected,
+ // this.onSearch,
+ this.fontSize,
+ this.searchHint = 'Search',
+ required this.context,
+ this.height,
+ this.popOnSelect = false,
+ this.location,
+ this.country,
+ });
+
+ /// True if there is different search screen and you want to pop screen on select
+ final bool popOnSelect;
+
+ ///To get the height of the page
+ final BuildContext context;
+
+ /// Height of whole search widget
+ final double? height;
+
+ /// API Key of the MapBox.
+ final String apiKey;
+
+ /// The callback that is called when one Place is selected by the user.
+ final void Function(MapBoxPlace place) onSelected;
+
+ /// The callback that is called when the user taps on the search icon.
+ // final void Function(MapBoxPlaces place) onSearch;
+
+ /// The point around which you wish to retrieve place information.
+ final Location? location;
+
+ ///Limits the search to the given country
+ ///
+ /// Check the full list of [supported countries](https://docs.mapbox.com/api/search/) for the MapBox API
+ final String? country;
+
+ ///Search Hint Localization
+ final String? searchHint;
+
+ ///Font Size
+ final String? fontSize;
+
+ @override
+ _MapBoxPlaceSearchWidgetState createState() =>
+ _MapBoxPlaceSearchWidgetState();
+}
+
+class _MapBoxPlaceSearchWidgetState extends State<MapBoxPlaceSearchWidget>
+ with SingleTickerProviderStateMixin {
+ TextEditingController _textEditingController = TextEditingController();
+ late AnimationController _animationController;
+
+
+ late Animation _containerHeight;
+
+
+ late Animation _listOpacity;
+
+ List<MapBoxPlace> _placePredictions = [];
+
+
+
+ late Timer _debounceTimer;
+
+
+
+
+ @override
+ void initState() {
+ _animationController =
+ AnimationController(vsync: this, duration: Duration(milliseconds: 500));
+
+ _containerHeight = Tween<double>(
+ begin: 73,
+ end: widget.height ??
+ MediaQuery.of(widget.context).size.height - 60 ??
+ 300)
+ .animate(
+ CurvedAnimation(
+ curve: Interval(0.0, 0.5, curve: Curves.easeInOut),
+ parent: _animationController,
+ ),
+ );
+ _listOpacity = Tween<double>(
+ begin: 0,
+ end: 1,
+ ).animate(
+ CurvedAnimation(
+ curve: Interval(0.5, 1.0, curve: Curves.easeInOut),
+ parent: _animationController,
+ ),
+ );
+ super.initState();
+ }
+
+ @override
+ void dispose() {
+ _debounceTimer.cancel();
+ _animationController?.dispose();
+ super.dispose();
+ }
+
+ @override
+ Widget build(BuildContext context) => Container(
+ padding: EdgeInsets.symmetric(horizontal: 5),
+ width: MediaQuery.of(context).size.width,
+ child: _searchContainer(
+ child: _searchInput(context),
+ ),
+ );
+
+ // Widgets
+ Widget _searchContainer({Widget? child}) {
+ return AnimatedBuilder(
+ animation: _animationController,
+ builder: (context, _) {
+ return Container(
+ height: _containerHeight.value,
+ decoration: _containerDecoration(),
+ padding: EdgeInsets.only(left: 0, right: 0, top: 15),
+ alignment: Alignment.center,
+ child: Column(
+ children: <Widget>[
+ Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 12.0),
+ child: child,
+ ),
+ SizedBox(height: 10),
+ Expanded(
+ child: Opacity(
+ opacity: _listOpacity.value,
+ child: ListView(
+ // addSemanticIndexes: true,
+ // itemExtent: 10,
+ children: <Widget>[
+ for (var places in _placePredictions)
+ _placeOption(places),
+ ],
+ ),
+ ),
+ ),
+ ],
+ ),
+ );
+ });
+ }
+
+ Widget _searchInput(BuildContext context) {
+ return Center(
+ child: Row(
+ children: <Widget>[
+ Expanded(
+ child: TextField(
+ decoration: _inputStyle(),
+ controller: _textEditingController,
+ style: TextStyle(
+ fontSize: MediaQuery.of(context).size.width * 0.04,
+ ),
+ onChanged: (value) async {
+ // _debounceTimer?.cancel();
+ _debounceTimer = Timer(
+ Duration(milliseconds: 750),
+ () async {
+ await _autocompletePlace(value);
+ if (mounted) {
+ setState(() {});
+ }
+ },
+ );
+ },
+ ),
+ ),
+ Container(width: 15),
+ GestureDetector(
+ child: Icon(Icons.search, color: Colors.blue),
+ onTap: () {},
+ )
+ ],
+ ),
+ );
+ }
+
+ Widget _placeOption(MapBoxPlace prediction) {
+ String? place = prediction.text;
+ String? fullName = prediction.placeName;
+
+ return MaterialButton(
+ padding: EdgeInsets.symmetric(horizontal: 10, vertical: 3),
+ onPressed: () => _selectPlace(prediction),
+ child: ListTile(
+ title: Text(
+ place?.length != 0 ? place!.length < 45
+ ? "$place"
+ : "${place?.replaceRange(45, place.length, "")} ..." : "",
+ style: TextStyle(fontSize: MediaQuery.of(context).size.width * 0.04),
+ maxLines: 1,
+ ),
+ subtitle: Text(
+ fullName!,
+ overflow: TextOverflow.ellipsis,
+ style: TextStyle(fontSize: MediaQuery.of(context).size.width * 0.03),
+ maxLines: 1,
+ ),
+ contentPadding: EdgeInsets.symmetric(
+ horizontal: 10,
+ vertical: 0,
+ ),
+ ),
+ );
+ }
+
+ // Styling
+ InputDecoration _inputStyle() {
+ return InputDecoration(
+ hintText: widget.searchHint,
+ border: InputBorder.none,
+ contentPadding: EdgeInsets.symmetric(horizontal: 0.0, vertical: 0.0),
+ );
+ }
+
+ BoxDecoration _containerDecoration() {
+ return BoxDecoration(
+ color: Colors.white,
+ borderRadius: BorderRadius.all(Radius.circular(6.0)),
+ boxShadow: [
+ BoxShadow(color: Colors.black, blurRadius: 0, spreadRadius: 0)
+ ],
+ );
+ }
+
+ // Methods
+ Future _autocompletePlace(String input) async {
+ /// Will be called when the input changes. Making callbacks to the Places
+ /// Api and giving the user Place options
+ ///
+ if (input.length > 0) {
+ var placesSearch = PlacesSearch(
+ apiKey: widget.apiKey,
+ country: widget.country,
+ );
+
+ final predictions = await placesSearch.getPlaces(
+ input,
+ location: widget.location,
+ );
+
+ await _animationController.animateTo(0.5);
+
+
+
+ setState(() => _placePredictions = predictions!);
+
+ await _animationController.forward();
+ } else {
+
+ await _animationController.animateTo(0.5);
+ setState(() => _placePredictions = []);
+ await _animationController.reverse();
+ }
+ }
+
+ void _selectPlace(MapBoxPlace prediction) async {
+ /// Will be called when a user selects one of the Place options.
+ // Sets TextField value to be the location selected
+ _textEditingController.value = TextEditingValue(
+ text: prediction.placeName.toString(),
+ selection: TextSelection.collapsed(offset: prediction.placeName!.length),
+ );
+
+ // Makes animation
+ await _animationController.animateTo(0.5);
+ setState(() {
+ _placePredictions = [];
+
+ });
+ _animationController.reverse();
+
+ // Calls the `onSelected` callback
+ widget.onSelected(prediction);
+ if (widget.popOnSelect) Navigator.pop(context);
+ }
+} \ No newline at end of file