Widgets in a stack are not displayed until I hot reload - flutter

I'm trying to display some widgets on top of a Map, and the widgets are created onMapCreated. Now, the problem is that the widgets are formed but not displayed immediately. They are displayed after I press hot reload on the IDE. How can I display the widgets immediately the page is loaded?
Here's my map
SafeArea(
child: Stack(children: [
GoogleMap(
myLocationEnabled: true,
myLocationButtonEnabled: true,
initialCameraPosition: CameraPosition(
target:
LatLng(widget.position.latitude, widget.position.longitude),
zoom: 16,
),
onMapCreated: _onMapCreated,
markers: markers.toSet(),
),
SizedBox(
height: 120,
child: ListView(
scrollDirection: Axis.horizontal,
children: tiles,
),
),
]),
),
The _onMapCreated function is
void _onMapCreated(GoogleMapController controller) {
stream!.listen((List<DocumentSnapshot> documentList) {
_updateMarkers(documentList, controller);
});
setState(() {
mapController = controller;
});
}

Related

Flutter Tabs and Maps

I am using google maps in my project, i use it in different pages, but one page i have that i use tabviews, one of these tabs is the google map. however when ever i click on the tab the app crashes out, seems to be on android only it does this. I have tried it wih the SafeArea and without, make no difference. the first window opens just when touch to go to the map tab it crashes out.
Works fine on IOS, same code works on other pages but they dont have tabs
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
title: Text(
widget.amenityName,
style: GoogleFonts.kaushanScript(fontSize: 20, color: Colors.white),
),
bottom: const TabBar(
tabs: [
Tab(icon: Icon(Icons.home)),
Tab(icon: Icon(Icons.map)),
],
),
),
body: TabBarView(
children: [amenity(), showGoogleMap()],
),
),
);
}
Widget amenity() {
return FutureBuilder(
future: getAmenity(widget.amenityID),
builder: (BuildContext context,
AsyncSnapshot<AmenityDetailsDataSet> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(child: CircularProgressIndicator());
} else if (snapshot.error != null) {
return const Center(child: Text('an error occured!'));
} else {.................
}
Widget showGoogleMap() {
return SafeArea(
child: GoogleMap(
mapToolbarEnabled: false,
buildingsEnabled: false,
zoomControlsEnabled: true,
compassEnabled: true,
myLocationButtonEnabled: false,
scrollGesturesEnabled: true,
tiltGesturesEnabled: false,
trafficEnabled: false,
zoomGesturesEnabled: true,
rotateGesturesEnabled: false,
mapType: MapType.hybrid,
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: widget.coords,
zoom: zoomLevel,
),
markers: _markers.values.toSet(),
),
);
}

How to Prevent Google Map Padding Delay?

I have a pair of widgets that generate a Google map and updates the user location but for some reason the padding seems to delay for a while, causing the MyLocation button to move into place instead of starting off in its correct position.
Is there any way to prevent this movement/delay in padding?
#override
Widget build(BuildContext context) {
return Scaffold(body: googleMapUI());
}
Widget googleMapUI() {
return Consumer<LocationProvider>(builder: (
consumerContext,
model,
child,
) {
if (model.locationPosition != null) {
return Column(
children: [
Expanded(
child: GoogleMap(
mapType: MapType.normal,
padding: const EdgeInsets.only(top: 40.0),
initialCameraPosition:
CameraPosition(target: model.locationPosition!, zoom: 18),
myLocationEnabled: true,
myLocationButtonEnabled: true,
onMapCreated: (GoogleMapController controller) async {
Provider.of<LocationProvider>(context, listen: false);
},
),
)
],
);
}
return Container(
child: const Center(
child: CircularProgressIndicator(),
),
);
});
}

Change color of myLocationButton -- Google Maps

Is there a way to change the default color of the myLocationButton in Google's APIs for iOS/Android? Can't seem to figure out how to do so.
#override
Widget build(BuildContext context) {
return new Scaffold(
body: _initialPosition == null
? Center(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(Colors.blue),
),
)
: Stack(children: [
GoogleMap(
mapType: MapType.normal,
initialCameraPosition: _currentPosition,
onMapCreated: (GoogleMapController controller) {
_setStyle(controller);
_controller.complete(controller);
},
zoomGesturesEnabled: true,
markers: _markers,
polylines: _polylines,
myLocationButtonEnabled: true,
myLocationEnabled: true,
mapToolbarEnabled: true,
),
]));
}

How do I display a TextFormField over GoogleMap without filling the entire screen in Flutter?

I want to show a TextFormField and a submit button at the top of the screen over a GoogleMap, but it's filling the entire screen and hiding the map below. I am getting the following error, which I know is due to the height of the contain parent being infinity:
RenderFlex children have non-zero flex but incoming height constraints are unbounded.
In my _buildForm() widget I wrapped the form in a container added height:100.0, but I'm still getting the error.
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:manchester_maps/locale/locales.dart';
void main() => runApp(CampusForm());
class CampusForm extends StatefulWidget {
#override
_CampusFormState createState() => _CampusFormState();
}
class _CampusFormState extends State<CampusForm> {
final _formKey = GlobalKey<_CampusFormState>();
#override
Widget build(BuildContext context) {
return MaterialApp(
localizationsDelegates: [
// A class which loads the translations from JSON files
AppLocalizationsDelegate(),
// Built-in localization of basic text for Material screens
GlobalMaterialLocalizations.delegate,
// Built-in localization for text direction LTR/RTL
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: [
Locale('en', ''),
Locale('fr', ''),
Locale('ar', ''),
Locale('de', ''),
Locale('es', ''),
Locale('hi', ''),
Locale('zh', ''),
Locale('ja', '')
],
home: Scaffold(
body: _buildForm(),
),
);
}
Widget _buildSearchField() {
return Expanded(
child: TextFormField(
decoration: InputDecoration(
labelText: AppLocalizations.of(context).bottomBarCampusMap,
),
),
);
}
Widget _buildSubmitButton() {
return Expanded(
child: RaisedButton(
onPressed: () {},
child: Icon(Icons.search),
),
);
}
Widget _buildForm() {
return Container(
width: MediaQuery.of(context).size.width,
height: 100.0,
child: Form(
key: _formKey,
child: Row(
children: <Widget>[
_buildSearchField(),
_buildSubmitButton(),
],
),
),
);
}
}
Here is the GoogleMaps code
home: Scaffold(
body: Stack(
children: <Widget>[
_userLocation == null
? Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
CircularProgressIndicator(
backgroundColor: Theme.UniColour.primary[900],
),
SizedBox(height: 20.0),
Text("Retrieving your location..."),
],
),
)
: GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: // required parameter that sets the starting camera position. Camera position describes which part of the world you want the map to point at.
CameraPosition(
target: _userLocation,
zoom: _defaultZoom,
tilt: _tiltAngle), //LatLng(53.467125, -2.233966)
scrollGesturesEnabled: _scrollGesturesEnabled,
tiltGesturesEnabled: _tiltGesturesEnabled,
compassEnabled: _compassEnabled,
rotateGesturesEnabled: _rotateGesturesEnabled,
myLocationEnabled: _myLocationEnabled,
buildingsEnabled: _buildingsEnabled, // not added to db
indoorViewEnabled: _indoorViewEnabled, // not added to db
mapToolbarEnabled: _mapToolbarEnabled, // not added to db
myLocationButtonEnabled:
_myLocationButtonEnabled, // not added to db
mapType: _currentMapType,
zoomGesturesEnabled: _zoomGesturesEnabled,
cameraTargetBounds: CameraTargetBounds(
new LatLngBounds(
northeast: uniCampusNE,
southwest: uniCampusSW,
),
),
minMaxZoomPreference:
MinMaxZoomPreference(_minZoom, _maxZoom),
),
// Display Building Search feature
CampusForm(),
],
),
Any help is appreciated.
thanks

Implementing GoogleMap inside SliverAppBar

I'm trying to make fixed ScrollView with google map inside of FlexibleSpaceBar.
There's NestedScrollView with SliverAppBar and body content. Inside SliverAppBar is google map widget, app bar occupy the whole view of the device. There's also FloatingActionButton, which on press should scroll to the bottom of the view revealing body content of NestedScrollView and shifting map to app bar and vice versa. It technically works, there's a code if someone wants to see how it looks like:
#override
State<MapPage> createState() => MapPageState();
}
const LatLng _coordinates = LatLng(37.43296265331129, -122.08832357078792);
class MapPageState extends State<MapPage> with SingleTickerProviderStateMixin {
ScrollController _scrollController;
Completer<GoogleMapController> _controller = Completer();
double _scrollExtent;
bool _buttonState;
static final CameraPosition _kGooglePlex = CameraPosition(
target: _coordinates,
zoom: 14.4746,
);
#override
void initState() {
_buttonState = true;
_scrollController = ScrollController(initialScrollOffset: 0.0);
super.initState();
}
#override
void dispose() {
_scrollController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
_scrollExtent = MediaQuery.of(context).size.height;
return Scaffold(
floatingActionButton: FloatingActionButton(
child: Icon(Icons.keyboard_arrow_down),
backgroundColor: Colors.white,
foregroundColor: Colors.red,
onPressed: (){
if(_buttonState){
_scrollController.animateTo(_scrollExtent, duration: Duration(seconds: 1), curve: Curves.fastOutSlowIn);
_buttonState = false;
}
else{
_scrollController.animateTo(-_scrollExtent, duration: Duration(seconds: 1), curve: Curves.fastOutSlowIn);
_buttonState = true;
}
},
),
body: NestedScrollView(
controller: _scrollController,
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverAppBar(
expandedHeight: MediaQuery.of(context).size.height,
floating: false,
pinned: true,
flexibleSpace: FlexibleSpaceBar(
title: Text("Title",
style: TextStyle(
color: Colors.white,
fontSize: 16.0,
)),
background: GoogleMap(
mapType: MapType.normal,
initialCameraPosition: _kGooglePlex,
markers: _createMarker(),
onMapCreated: (GoogleMapController controller) {
_controller.complete(controller);
},
),
),
),
];
},
body: Container(
padding: EdgeInsets.all(24.0),
child: Text(
'Content'),
),
),
);
}
Set<Marker> _createMarker() {
return <Marker>[
Marker(
markerId: MarkerId("marker_1"),
position: _coordinates,
infoWindow: InfoWindow(title: 'Marker"'),
),
].toSet();
}
}
The important part is here:
NestedScrollView(
controller: _scrollController,
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverAppBar(
expandedHeight: MediaQuery.of(context).size.height,
floating: false,
pinned: true,
flexibleSpace: FlexibleSpaceBar(
title: Text("Title",
style: TextStyle(
color: Colors.white,
fontSize: 16.0,
)),
background: GoogleMap(
mapType: MapType.normal,
initialCameraPosition: _kGooglePlex,
markers: _createMarker(),
onMapCreated: (GoogleMapController controller) {
_controller.complete(controller);
},
),
),
),
];
},
There are 3 problems:
I dont understand how to prevent user from scrolling with gestures.
I want it to be controlled only by a scroll controller. I've tried to set physics of NestedScrollView to NeverScrollableScrollPhysics(), but it doesn't have any effect.
The map gesture detection inside scrollable widget behaving weirdly
You can't properly drag it and it seems to be only working with taps. In ListView, for example, it behaved fine with NeverScrollable physics.
Every time it's getting rebuilt in app bar it seems to cause some sort of memory leak and I'm getting next warning.
E/flutter (10644): #0 _AsyncCompleter.complete (dart:async/future_impl.dart:39:31)
E/flutter (10644): #1 MapPageState.build.<anonymous closure>.<anonymous closure> (package:flutter_app/map_page2.dart:83:35)
E/flutter (10644): #2 _GoogleMapState.onPlatformViewCreated (package:google_maps_flutter/src/google_map.dart:259:14)
E/flutter (10644): <asynchronous suspension>
E/flutter (10644): #3 AndroidViewController._create (package:flutter/src/services/platform_views.dart:599:15)
...
If anyone can help out with any of those or maybe know examples of such implementation I would highly appreciate it.
I crossed the same problem, and found the solution here.
background: GoogleMap(
gestureRecognizers: [
Factory<OneSequenceGestureRecognizer>(
() => EagerGestureRecognizer(),
),
].toSet(),