Update position in relatime of map in flutter - google-maps

Hello the code below displays a map with the user's position using the google_maps_flutter and location package, the code below correctly displays the map with the initial position of latitude and longitude but when the user starts the app from the device the position does not it becomes the actual one of the user but remains on the initial position, how do I solve this?
Flutter Code:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:location/location.dart';
import 'package:MyApp/View/Cantieri/mediterranesn_diet_view.dart'
show MediterranesnDietView;
import 'package:MyApp/View/Cantieri/title_view.dart' show TitleView;
import 'package:MyApp/View/Home_theme.dart';
import 'package:MyApp/View/MarcaTempo/FunzioneMarcatempoView.dart'
show MarcaTempoListView;
//Valori longitudine e latitudine
double longitudine = 12.4818, latitudine = 41.9109;
LatLng _center = LatLng(latitudine, longitudine);
//Recupero e salvataggio dei valori del gps di longitudine e latitudine
Future<void> _getGpsValue() async {
//Instanzio l'oggetto che si occupa di recuperare i dati per la marcatura
var location = new Location();
location.onLocationChanged().listen((LocationData currentLocation) async {
longitudine = currentLocation.longitude;
latitudine = currentLocation.latitude;
_center = LatLng(latitudine, longitudine);
});
Timer(Duration(seconds: 1), () {
print("E' passato 1 secondo");
print("Latitudine: " +
latitudine.toString() +
"\n Longitudine: " +
longitudine.toString());
});
}
class MyDiaryScreen extends StatefulWidget {
const MyDiaryScreen({Key key, this.animationController}) : super(key: key);
final AnimationController animationController;
#override
_MyDiaryScreenState createState() => _MyDiaryScreenState();
}
class _MyDiaryScreenState extends State<MyDiaryScreen>
with TickerProviderStateMixin {
GoogleMapController mapController;
var width;
void _onMapCreated(GoogleMapController controller) {
mapController = controller;
}
List<Widget> listViews = <Widget>[];
final ScrollController scrollController = ScrollController();
Animation<double> topBarAnimation;
double topBarOpacity = 0.0;
#override
void initState() {
_getGpsValue();
topBarAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
parent: widget.animationController,
curve: Interval(0, 0.5, curve: Curves.fastOutSlowIn)));
addAllListData();
scrollController.addListener(() {
if (scrollController.offset >= 24) {
if (topBarOpacity != 1.0) {
setState(() {
topBarOpacity = 1.0;
});
}
} else if (scrollController.offset <= 24 &&
scrollController.offset >= 0) {
if (topBarOpacity != scrollController.offset / 24) {
setState(() {
topBarOpacity = scrollController.offset / 24;
});
}
} else if (scrollController.offset <= 0) {
if (topBarOpacity != 0.0) {
setState(() {
topBarOpacity = 0.0;
});
}
}
});
super.initState();
}
void addAllListData() {
_getGpsValue();
const int count = 9;
//Prima view che comprende il titolo della Posizione
listViews.add(
TitleView(
titleTxt: 'Posizione',
subTxt: '',
animation: Tween<double>(begin: 0.0, end: 1.0).animate(CurvedAnimation(
parent: widget.animationController,
curve:
Interval((1 / count) * 0, 1.0, curve: Curves.fastOutSlowIn))),
animationController: widget.animationController,
),
);
//Inserimento del modulo con le informazioni sulla posizione
listViews.add(
MediterranesnDietView(
animation: Tween<double>(begin: 0.0, end: 1.0).animate(CurvedAnimation(
parent: widget.animationController,
curve:
Interval((1 / count) * 1, 1.0, curve: Curves.fastOutSlowIn))),
animationController: widget.animationController,
),
);
//Inserimento del titolo di registrazione
listViews.add(
TitleView(
titleTxt: 'Registrazione',
subTxt: '',
animation: Tween<double>(begin: 0.0, end: 1.0).animate(CurvedAnimation(
parent: widget.animationController,
curve:
Interval((1 / count) * 2, 1.0, curve: Curves.fastOutSlowIn))),
animationController: widget.animationController,
),
);
//Inserimento dei button per il marcatempo
listViews.add(
MarcaTempoListView(
mainScreenAnimation: Tween<double>(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
parent: widget.animationController,
curve: Interval((1 / count) * 3, 1.0,
curve: Curves.fastOutSlowIn))),
mainScreenAnimationController: widget.animationController,
),
);
//Inserimento del titolo di registrazione
listViews.add(
TitleView(
titleTxt: 'Mappa',
subTxt: '',
animation: Tween<double>(begin: 0.0, end: 1.0).animate(CurvedAnimation(
parent: widget.animationController,
curve:
Interval((1 / count) * 2, 1.0, curve: Curves.fastOutSlowIn))),
animationController: widget.animationController,
),
);
listViews.add(new Container(
width: width,
height: 400.0,
child: GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: _center,
zoom: 6.0,
))));
}
Future<bool> getData(BuildContext context) async {
await Future<dynamic>.delayed(const Duration(milliseconds: 50));
width = MediaQuery.of(context).size.width;
return true;
}
Widget getMainListViewUI() {
return FutureBuilder<bool>(
future: getData(context),
builder: (BuildContext context, AsyncSnapshot<bool> snapshot) {
if (!snapshot.hasData) {
return const SizedBox();
} else {
return ListView.builder(
shrinkWrap: true,
controller: scrollController,
padding: EdgeInsets.only(
top: AppBar().preferredSize.height +
MediaQuery.of(context).padding.top +
24,
bottom: 62 + MediaQuery.of(context).padding.bottom,
),
itemCount: listViews.length,
scrollDirection: Axis.vertical,
itemBuilder: (BuildContext context, int index) {
widget.animationController.forward();
return listViews[index];
},
);
}
},
);
}
//Recupero della barra per la UI
Widget getAppBarUI() {
return Column(
children: <Widget>[
AnimatedBuilder(
animation: widget.animationController,
builder: (BuildContext context, Widget child) {
return FadeTransition(
opacity: topBarAnimation,
child: Transform(
transform: Matrix4.translationValues(
0.0, 30 * (1.0 - topBarAnimation.value), 0.0),
child: Container(
decoration: BoxDecoration(
color: TemaApp.white.withOpacity(topBarOpacity),
borderRadius: const BorderRadius.only(
bottomLeft: Radius.circular(32.0),
),
boxShadow: <BoxShadow>[
BoxShadow(
color: TemaApp.grey.withOpacity(0.4 * topBarOpacity),
offset: const Offset(1.1, 1.1),
blurRadius: 10.0),
],
),
child: Column(
children: <Widget>[
SizedBox(
height: MediaQuery.of(context).padding.top,
),
Padding(
padding: EdgeInsets.only(
left: 16,
right: 16,
top: 16 - 8.0 * topBarOpacity,
bottom: 12 - 8.0 * topBarOpacity),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'Marcatempo',
textAlign: TextAlign.left,
style: TextStyle(
fontFamily: TemaApp.fontName,
fontWeight: FontWeight.w700,
fontSize: 22 + 6 - 6 * topBarOpacity,
letterSpacing: 1.2,
color: TemaApp.darkerText,
),
),
),
),
],
),
)
],
),
),
),
);
},
)
],
);
}
#override
Widget build(BuildContext context) {
return Container(
color: TemaApp.background,
child: Scaffold(
backgroundColor: Colors.transparent,
resizeToAvoidBottomPadding: true,
body: Stack(
children: <Widget>[
//getMap(),
getMainListViewUI(),
getAppBarUI(),
SizedBox(
height: MediaQuery.of(context).padding.bottom,
)
],
),
),
);
}
}

You need to call setState() inside the _getGpsValue() to update the user's location.
setState(() {
longitudine = currentLocation.longitude;
latitudine = currentLocation.latitude;
_center = LatLng(latitudine, longitudine);
})
As per the documentation:
Calling setState notifies the framework that the internal state of
this object has changed in a way that might impact the user interface
in this subtree, which causes the framework to schedule a build for
this State object.

Related

Flutter how can NOT reload FutureBuilder when state is updated?

I'm studying flutter by myself.
trying to make doto Calendar with carousel calendar.
I want to make date number big when there's event
-> it's done
the problem is
# line 238
if I put code like below, the calendar is keep refreshing whenever I press date button.
return snapshot.hasData && _markedDateMap.events.length > 0 ...
if I put code like below, my lovely big big date buttons becomes small!!
return snapshot.hasData ...
is there any solution for this problem?
please help me to stop the future builder is keep building!
TT
enter image description here
import 'package:flutter/material.dart';
import 'package:flutter_calendar_carousel/flutter_calendar_carousel.dart'
show CalendarCarousel;
import 'package:flutter_calendar_carousel/classes/event.dart';
import 'package:flutter_calendar_carousel/classes/event_list.dart';
import 'package:intl/intl.dart' show DateFormat;
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:intl/intl.dart';
Future<List<ipoData>> fetchIPODatas(http.Client client) async {
final response = await client.get('http://realchord.net/ipo/getIPOData.php');
// Use the compute function to run parseIpoData in a separate isolate.
return compute(parseIpoData, response.body);
}
// A function that converts a response body into a List<Photo>.
List<ipoData> parseIpoData(String responseBody) {
final parsed = jsonDecode(responseBody).cast<Map<String, dynamic>>();
return parsed.map<ipoData>((json) => ipoData.fromJson(json)).toList();
}
// ignore: camel_case_types
class ipoData {
final String ipoDate;
final String company;
ipoData({this.ipoDate, this.company});
factory ipoData.fromJson(Map<String, dynamic> json) => ipoData(
ipoDate: json['date'],
company: json['company'],
);
}
// factory Model.fromJson(Map<String, dynamic> json) => Model(
// value1: json['key1'],
// value2: json['key2'],
// value3: json['key3'],
// value4: json['key4'],
// );
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'IPO calendar',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'IPO calendar'));
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
DateTime _currentDate = new DateTime.now();
DateTime _currentDate2 = new DateTime.now();
String _currentMonth = DateFormat.MMMM().format(new DateTime.now());
DateTime _next = new DateTime(
DateTime.now().year, DateTime.now().month + 1, DateTime.now().day);
DateTime _prev = new DateTime(
DateTime.now().year, DateTime.now().month - 1, DateTime.now().day);
String _nextMonth;
String _prevMonth;
DateTime _targetDateTime = new DateTime.now();
// List<DateTime> _markedDate = [DateTime(2018, 9, 20), DateTime(2018, 10, 11)];
EventList<Event> _markedDateMap = new EventList<Event>();
// ignore: unused_field
CalendarCarousel _calendarCarouselNoHeader;
// load data
#override
void initState() {
super.initState();
}
// List response = await fetchIPODatas(http.Client());
#override
Widget build(BuildContext context) {
/// Example Calendar Carousel without header and custom prev & next button
_calendarCarouselNoHeader = CalendarCarousel<Event>(
onDayPressed: (DateTime date, List<Event> events) {
this.setState(() => _currentDate2 = date);
// events.forEach((event) => print(event.title));
},
//달력 기본 설정
daysHaveCircularBorder: true,
showOnlyCurrentMonthDate: false,
showHeader: false,
customGridViewPhysics: NeverScrollableScrollPhysics(),
height: 500.0,
daysTextStyle: TextStyle(
fontWeight: FontWeight.w600,
color: Colors.white, //weekend day font color
),
weekendTextStyle: TextStyle(
fontWeight: FontWeight.w600,
color: Colors.white, //weekend day font color
),
weekdayTextStyle: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
),
// thisMonthDayBorderColor: Colors.grey, // border color of each day
weekFormat: false,
// firstDayOfWeek: 4,
markedDatesMap: _markedDateMap,
selectedDateTime: _currentDate2,
targetDateTime: _targetDateTime,
minSelectedDate: _currentDate.subtract(Duration(days: 360)),
maxSelectedDate: _currentDate.add(Duration(days: 360)),
// //이벤트가 있는 날에 대한 설정
// markedDateCustomShapeBorder:
// CircleBorder(side: BorderSide(color: Colors.yellow)),
markedDateCustomTextStyle: TextStyle(
fontSize: 30,
color: Colors.white,
),
// markedDateIconBorderColor: Colors.white,
// markedDateMoreShowTotal: true,
//오늘에 대한 설정
todayTextStyle: TextStyle(
color: Colors.white,
),
todayButtonColor: Colors.white24,
todayBorderColor: null,
// 선택한 날에 대한 설정
selectedDayTextStyle: TextStyle(
color: Colors.black,
),
selectedDayButtonColor: Colors.white,
// selectedDayBorderColor: Colors.white,
// 지난 달에 대한 설정
prevDaysTextStyle: TextStyle(
fontSize: 16,
color: Colors.white38,
),
// 다음 달에 대한 설정
nextDaysTextStyle: TextStyle(
fontSize: 16,
color: Colors.white38,
),
inactiveDaysTextStyle: TextStyle(
color: Colors.white38,
fontSize: 16,
),
onCalendarChanged: (DateTime date) {
this.setState(() {
_targetDateTime = date;
_currentMonth = DateFormat.MMMM().format(_targetDateTime);
_next = new DateTime(_targetDateTime.year, _targetDateTime.month + 1,
_targetDateTime.day);
_nextMonth = DateFormat.MMMM().format(_next);
_prev = new DateTime(_targetDateTime.year, _targetDateTime.month - 1,
_targetDateTime.day);
_prevMonth = DateFormat.M().format(_prev);
});
},
onDayLongPressed: (DateTime date) {
print('long pressed date $date');
},
);
_markedDateMap.clear();
_nextMonth = DateFormat.MMMM().format(_next);
_prevMonth = DateFormat.M().format(_prev);
// dotColorList.add(Colors.white);
return new Scaffold(
body: FutureBuilder<List<ipoData>>(
future: fetchIPODatas(http.Client()),
builder: (context, snapshot) {
if (snapshot.hasError) print(snapshot.error);
if (snapshot.connectionState == ConnectionState.done &&
snapshot.hasData &&
snapshot.data != null) {
final List<ipoData> ipoDataList = snapshot.data;
for (var i = 0; i < snapshot.data.length; i++) {
DateTime dt = DateTime.parse(ipoDataList[i].ipoDate.toString());
_markedDateMap.add(
dt,
new Event(
date: dt,
title: ipoDataList[i].company,
dot: Container(
margin: EdgeInsets.symmetric(horizontal: 1.0),
color: Colors.red.shade300,
height: 5.0,
width: 5.0,
),
));
}
}
return snapshot.hasData && _markedDateMap.events.length > 0
? SingleChildScrollView(
child: Stack(children: [
Container(
padding: EdgeInsets.only(top: 50),
color: Colors.blue,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
//custom icon without header
Container(
//display Month
margin: EdgeInsets.only(
top: 20.0,
bottom: 16.0,
left: 0.0,
right: 0.0,
),
padding: EdgeInsets.all(0),
child: new Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
FlatButton(
padding: EdgeInsets.all(0),
child: Text(_prevMonth,
// softWrap: false,
maxLines: 1,
textAlign: TextAlign.right,
style: TextStyle(
color: Colors.white12,
fontSize: 48,
fontWeight: FontWeight.bold,
)),
onPressed: () {
setState(() {
_targetDateTime = DateTime(
_targetDateTime.year,
_targetDateTime.month - 1);
_currentMonth = DateFormat.MMMM()
.format(_targetDateTime);
});
},
),
Text(
_currentMonth,
maxLines: 1,
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 48.0,
),
),
FlatButton(
child: Text(
_nextMonth,
softWrap: true,
maxLines: 1,
style: TextStyle(
color: Colors.white12,
fontSize: 48,
fontWeight: FontWeight.bold,
),
),
onPressed: () {
setState(() {
_targetDateTime = DateTime(
_targetDateTime.year,
_targetDateTime.month + 1);
_currentMonth = DateFormat.MMMM()
.format(_targetDateTime);
_next = new DateTime(
_targetDateTime.year,
_targetDateTime.month + 1,
_targetDateTime.day);
_nextMonth =
DateFormat.MMMM().format(_next);
_prev = new DateTime(
_targetDateTime.year,
_targetDateTime.month - 1,
_targetDateTime.day);
_prevMonth = DateFormat.M().format(_prev);
});
},
)
],
),
),
Container(
margin: EdgeInsets.symmetric(horizontal: 16.0),
child: _calendarCarouselNoHeader,
)
],
),
),
Container(
height: MediaQuery.of(context).size.height - 500,
width: MediaQuery.of(context).size.width,
margin: const EdgeInsets.only(top: 500),
padding: const EdgeInsets.only(
top: 40,
left: 15,
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(50),
color: Colors.white,
),
child: Column(
children: [
EventItem(
company: "LGENSol",
)
],
),
)
]),
)
: Center(child: CircularProgressIndicator());
},
));
}
}
class EventItem extends StatefulWidget {
// final Icon icon;
final String company;
// final Text category;
// final Function() notifyParent;
EventItem(
{
// #required this.icon,
#required this.company}); //#required this.notifyParent
#override
_EventItemState createState() => _EventItemState();
}
class _EventItemState extends State<EventItem> {
get futureAlbum => null;
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Row(
children: [
Icon(
Icons.favorite,
color: Colors.pink,
size: 24.0,
),
Padding(
padding: EdgeInsets.all(12.0),
child: Text(widget.company,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20,
)),
),
Padding(
padding: EdgeInsets.all(5.0),
child: Text("(청약)",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20,
)),
),
],
),
Row(
children: [
Padding(
padding: EdgeInsets.only(left: 37),
child: Text("공모가:20,000원 | 상장:8/20 | 주관:키움",
style: TextStyle(
fontSize: 20,
)),
),
],
)
],
);
}
}
Every time you call setState in your stateful widget, you're calling that widget's build method, and since your FutureBuilder is part of it then it will get called. It doesn't seem like you're changing the future so I'd suggest you could bring the FutureBuilder a level higher and put your stateful widget inside the FutureBuilder
class MyHomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder(
future: fetchIPODatas(http.Client()),
builder: (context, snapshot) {
//... (add your extracted stateful widget in here..)
},
),
);
}
}

How to put the result of a function into a Text widget in Flutter?

I am new in this language and I am working on a BMI(body mass index) app. As you see in the picture below:
I take the user input and calculate the result, and print out the result in console. For example:
I/flutter ( 4500): 2.25
I/flutter ( 4500): 20.0 // this is the result of BMI
I/flutter ( 4500): you are at your ideal weight. // this is the explanation
I want to show these results in a Text widget to let user see them. But I do not know how to do it. How can I take the value of the result from a function and add it to interface?
Here is my code, and in code I pointed out where did I stuck. Main function:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'calculation.dart';
void main() => runApp(MyApp());
/// This is the main application widget.
class MyApp extends StatelessWidget {
static const String _title = 'BMI';
#override
Widget build(BuildContext context) {
return MaterialApp(
title: _title,
home: Scaffold(
appBar: AppBar(title: const Text(_title),
centerTitle: true,
backgroundColor: Colors.amber[900],
),
body: Center(
child: MyStatefulWidget(),
),
),
);
}
}
enum SingingCharacter { lafayette, jefferson }
/// This is the stateful widget that the main application instantiates.
class MyStatefulWidget extends StatefulWidget {
MyStatefulWidget({Key key}) : super(key: key);
#override
_MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}
/// This is the private State class that goes with MyStatefulWidget.
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
SingingCharacter _character = SingingCharacter.lafayette;
double height=1;
double weight=1;
String info1="";
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(10.0),
child:Scrollbar(
child:SingleChildScrollView(
child:Card(
color: Colors.amber[50],
child:Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.fromLTRB(0, 30, 10, 10),
child: Text("Sex:",
style:TextStyle(fontSize: 24, letterSpacing: 1.0)),
),
ListTile(
title: const Text('Female',
style:TextStyle(fontSize: 18, letterSpacing: 1.0)
),
leading: Radio(
activeColor: Colors.orange,
value: SingingCharacter.lafayette,
groupValue: _character,
onChanged: (SingingCharacter value) {
setState(() {
_character = value;
});
},
),
),
ListTile(
title: const Text('Male',
style:TextStyle(fontSize: 18, letterSpacing: 1.0,)
),
leading: Radio(
activeColor: Colors.orange,
value: SingingCharacter.jefferson,
groupValue: _character,
onChanged: (SingingCharacter value) {
setState(() {
_character = value;
});
},
),
),
SizedBox(height: 10.0),
Text("Your height:",
style:TextStyle(fontSize: 24, letterSpacing: 1.0)
),
SizedBox(height: 10),
Padding(
padding: const EdgeInsets.fromLTRB(30, 0, 50, 10),
child: TextField(
decoration: new InputDecoration(labelText: "Your height(cm)"),
keyboardType: TextInputType.number,
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.digitsOnly
], // Only numbers can be entered
onSubmitted: (input1){
if(double.parse(input1)>0){
setState(() => height=double.parse(input1));
print(input1);
}
},
),
),
SizedBox(height: 20),
Text("Your weight:",
style:TextStyle(fontSize: 24, letterSpacing: 1.0)
),
SizedBox(height: 10),
Padding(
padding: const EdgeInsets.fromLTRB(30, 0, 50, 10),
child: new TextField(
decoration: new InputDecoration(labelText: "Your weight(kg)"),
keyboardType: TextInputType.number,
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.digitsOnly
], // Only numbers can be entered
onSubmitted: (input2){
if (double.parse(input2)>0){
// print(weight);
setState(() {
return weight=double.parse(input2);
});
}
},
),),
SizedBox(height: 10,),
RaisedButton(
padding:EdgeInsets.fromLTRB(20, 5, 20, 5),
onPressed: () async{
await Calculation(height, weight);
// return Calculation.info1 ??? //i don't know how to take info1 from calculation function
},
color: Colors.amber[900],
child:Text(
'Calculate',
style:TextStyle(
color: Colors.white,
fontSize: 30,
letterSpacing: 2.0,
),
),
),
SizedBox(height: 20,),
Text('Results: $height,$weight'),
// Text('Calculation.info1'), // i do not know how to show info in a text box.
],
),
),
),
),
);
}
}
Calculation function;
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'dart:math';
void Calculation(height,weight) {
double squarevalue = pow(height, 2);
double newsquare = squarevalue / 10000;
String info1="";
print(newsquare);
double value = weight / newsquare;
print(value);
// return value.toString();
if (value < 18.5) {
print("your weight is less than your ideal weight.");
// setState(() => info1="your weight is less than your ideal weight."); //i do not know how to set
// info1 to a new text
// return info1;
}
if (value > 25) {
if (value > 30) {
print("your weight is more than your ideal weight, your health is under risk.");
// info1="your weight is more than your ideal weight, your health is under risk.";
}
else {
print("your weight is more than your ideal weight.");
// info1="your weight is more than your ideal weight.";
}
}
else {
print("you are at your ideal weight.");
// info1="you are at your ideal weight.";
}
}
Instead of returning void from Calculation(height,weight) function, return String and display the string value in the Text Widget.
String Calculation(height,weight) {
....// your code with all conditions
return "you are at your ideal weight."
}
In onpressed function, update the obtained string to the state variable inside setState.
onPressed: () async{
String info = await Calculation(height, weight);
setState(){
infoDisplayedInText = info;
}
},

Access function from another class

Hello guys I'm trying to access function from another class becuse this function establish call and navigat to call page so for sure there will be setState function to update the UI but here is the problem whene the UI got updated from another class the app will go out of the widget tree so i have to use callBack function which is i dont know how pleass help
this is the perant class:
import 'dart:async';
import 'package:agora_rtc_engine/agora_rtc_engine.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:flutter_modular/flutter_modular.dart';
import 'package:flutter_social_messenger/src/modules/auth/domain/entities/user.dart';
import 'package:flutter_social_messenger/src/modules/auth/export.dart';
import 'package:flutter_social_messenger/src/modules/notifications/domain/entities/call_msg.dart';
import 'package:flutter_social_messenger/src/modules/notifications/domain/entities/notification.dart';
import 'package:flutter_social_messenger/src/modules/notifications/domain/repository/repo.dart';
import 'package:permission_handler/permission_handler.dart';
import '../../export.dart';
import './call.dart';
class IndexPage extends StatefulWidget {
String userId;
IndexPage(String this.userId);
#override
State<StatefulWidget> createState() => IndexState();
}
class IndexState extends State<IndexPage> {
/// create a channelController to retrieve text value
final _channelController = TextEditingController();
/// if channel textField is validated to have error
bool _validateError = false;
ClientRole _role = ClientRole.Broadcaster;
User currentUser = Modular.get<AuthController>().currentUser;
#override
void dispose() {
// dispose input controller
_channelController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
print("target : " + widget.userId.toString() ) ;
return Scaffold(
appBar: AppBar(
title: Text('Make a Call'),
),
body: Center(
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 20),
height: 400,
child: Column(
children: <Widget>[
/*
Row(
children: <Widget>[
Expanded(
child: TextField(
controller: _channelController..text = 'call-' + currentUser.id + "-" + widget.userId ,
decoration: InputDecoration(
errorText:
_validateError ? 'Channel name is mandatory' : null,
border: UnderlineInputBorder(
borderSide: BorderSide(width: 1),
),
hintText: 'call-' + widget.userId + "-" + currentUser.id ,
),
))
],
),
Column(
children: [
ListTile(
title: Text(ClientRole.Broadcaster.toString()),
leading: Radio(
value: ClientRole.Broadcaster,
groupValue: _role,
onChanged: (ClientRole value) {
setState(() {
_role = value;
});
},
),
),
ListTile(
title: Text(ClientRole.Audience.toString()),
leading: Radio(
value: ClientRole.Audience,
groupValue: _role,
onChanged: (ClientRole value) {
setState(() {
_role = value;
});
},
),
)
],
),
*/
Padding(
padding: const EdgeInsets.symmetric(vertical: 20),
child:
Row( children: <Widget>[
// Expanded(child: Text('call-' + currentUser.id + "-" + widget.userId ) ),
Expanded( child:
RawMaterialButton(
onPressed: () => onJoin(widget.userId,context,currentUser.id) ,
child: Icon(
Icons.call_end,
color: Colors.white,
size: 35.0,
),
shape: CircleBorder(),
elevation: 2.0,
fillColor: Colors.green,
padding: const EdgeInsets.all(15.0),
)
// RaisedButton(
// onPressed: onJoin,
// child: Text('Dial'),
// color: Colors.blueAccent,
// textColor: Colors.white,
// ),
) ], ),
)
],
),
),
),
);
}
DateTime get now => DateTime.now().toUtc();
Future<void> sendFollowNotification() {
String sendToId = widget.userId;
final followerId = currentUser.id;
print("trying to send call notification Id : " + "call-$followerId-$sendToId") ;
final not = CallNotification(
id: "call-$followerId-$sendToId",
sendTo: followerId,
senderId: sendToId,
senderName: currentUser.name,
time: now,
);
return repository.sendNotificaion(not);
}
Future<void> sendCallAlert() async {
String sendToId = widget.userId;
final followerId = currentUser.id;
print("trying to send call notification Id : " + "call-$followerId-$sendToId") ;
final not = CallNotification(
id: "call-$followerId-$sendToId",
sendTo: followerId,
senderId: sendToId,
senderName: currentUser.name,
time: now,
);
await Modular.get<NotificationsHelper>()
.registerNotification(followerId, true);
_callDocument("call-$followerId-$sendToId").setData(not.toJson());
// return _callCollection.document(currentUser.id).setData(not.toJson()) ;
// return repository.sendNotificaion(not);
}
final repository = Modular.get<NotificationReposity>();
final appStore = Modular.get<AppStore>();
final _firestore = Firestore.instance;
DocumentReference _callDocument(String callId) =>
_callCollection.document(callId);
CollectionReference get _callCollection => _firestore.collection("calls");
Future<void> onJoin(String userId,BuildContext context,final _followerId) async {
// print("qqqq") ;
String sendToId = userId;
final followerId = _followerId;
// print(userId+" i'm");
// print(_followerId+" his");
_channelController.text = "call-$followerId-$sendToId" ;
print("diallllll : " + _channelController.text ) ;
// /*
// update input validation
setState(() {
_channelController.text.isEmpty
? _validateError = true
: _validateError = false;
});
sendFollowNotification();
sendCallAlert();
if (_channelController.text.isNotEmpty) {
print('hiiiiissss');
// await for camera and mic permissions before pushing video page
await _handleCameraAndMic();
// push video page with given channel name
await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => CallPage(
channelName: _channelController.text,
role: _role,
),
),
);
}
// */
}
Future<void> _handleCameraAndMic() async {
// if (kIsWeb || !Platform.isAndroid) return true;
if (!await Permission.camera.isGranted && !await Permission.microphone.isGranted) {
var rr = ((await Permission.camera.request()).isGranted && (await Permission.microphone.request()).isGranted) ;
print("rr : " + rr.toString()) ;
}
}
// Future<bool> checkStoragePermission() async {
// if (kIsWeb || !Platform.isAndroid) return true;
// if (!await Permission.storage.isGranted) {
// return (await Permission.storage.request()).isGranted;
// }
// return true;
// }
}
and this is the child:
import 'package:agora_rtc_engine/agora_rtc_engine.dart';
import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:styled_widget/styled_widget.dart';
import '../../../../../chat/presentation/calling/index.dart';
import '../../../../../chat/presentation/calling/index.dart';
import '../../../../../chat/presentation/calling/index.dart';
import '../../../../../chat/presentation/calling/index.dart';
import '../../../../../chat/presentation/calling/index.dart';
import '../../../../export.dart';
import '../controller.dart';
import '../../widgets/profile_avatar.dart';
import 'package:flutter_social_messenger/src/modules/chat/presentation/calling/index.dart';
import 'package:flutter_social_messenger/src/modules/chat/presentation/calling/call.dart';
class OProfileHeader extends StatelessWidget implements PreferredSizeWidget {
final OtherUserProfileController controller;
OProfileHeader({Key key, #required this.controller}) : super(key: key);
User get user => controller.otherUser;
#override
Widget build(BuildContext context) {
final theme = Theme.of(context);
print("OProfileHeader : " + controller.isFollowing.toString() ) ;
return Stack(
children: <Widget>[
Positioned(
bottom: 200,
left: 0,
right: 0,
child: SizedBox(height: 200)
.decorated(gradient: AppTheme.primaryGradient),
),
Positioned(
bottom: 150,
left: 1,
right: 1,
child: Center(
child: Material(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
elevation: 5.0,
color: theme.scaffoldBackgroundColor,
child: Column(
children: <Widget>[
Observer(
builder: (_) => Text(
user.name ?? "",
style: GoogleFonts.basic().copyWith(fontSize: 28),
maxLines: 1,
),
).padding(top: 40),
Text(user.status ?? "").padding(bottom: 10),
],
),
).width(MediaQuery.of(context).size.width * 4 / 5),
),
),
Positioned(
left: 0,
right: 0,
bottom: 300,
child: AppBar(
backgroundColor: Colors.transparent,
iconTheme: IconThemeData(),
elevation: 0,
),
),
Positioned(
left: 0,
right: 0,
bottom: 210,
child: Center(
child: Material(
elevation: 5.0,
shape: CircleBorder(),
child: Observer(
builder: (_) => ProfileAvatarWidget(
photoUrl: user.photoUrl,
// isLoading: state is LoadingProfilePic,
),
),
),
),
),
Positioned(
right: 200,
left: 0,
bottom: 60,
child: Center(
child: Observer(
builder: (_) {
controller.currentUser.following;
return RaisedButton(
color: controller.isFollowing
? Colors.black
: theme.primaryColor,
onPressed: () => controller.followUser(user.id),
child: Text(
controller.isFollowing ? "UnFollow" : "Follow",
style: GoogleFonts.alike().copyWith(
fontSize: 16,
color: Colors.white,
),
textAlign: TextAlign.center,
).width(70),
);
},
),
),
),
Positioned(
right: 0,
left: 200,
bottom: 60,
child: Center(
child: Observer(
builder: (_) {
controller.currentUser.following;
return RaisedButton(
color: Colors.green,
onPressed: ()=> {
IndexState().onJoin(user.id,context,controller.currentUser.id),
print(controller.currentUser.id+" "+controller.currentUser.phoneNumber),
print(user.id+" "+user.phoneNumber)
},
child: Text(
"Call",
style: GoogleFonts.alike().copyWith(
fontSize: 16,
color: Colors.white,
),
textAlign: TextAlign.center,
).width(70),
);
},
),
),
),
],
).height(500).backgroundColor(theme.scaffoldBackgroundColor);
}
#override
Size get preferredSize => Size.fromHeight(400);
//----------------------------------------------------
// */
}
I dont understand exactly what you want, but if its how to call a method from a parent widget, if would be something like this:
class ParentWidget extends StatelessWidget{
#override
Widget build(BuildContext context) {
return ChildWidget(onAction: (resultValue){
//Do something with the value
});
}
}
class ChildWidget extends StatelessWidget{
final Function onAction;
ChildWidget({Key key, #required this.onAction}) : super(key: key);
#override
Widget build(BuildContext context) {
return Inkwell(
onTap: (){
onAction(someValue);
}
child: AnyOtherWidget
);
}
}

Flutter: How can I get the coordinates of the center of the map in google maps?

I am trying to build an app.
I am using the official google_maps_flutter. I don't have any problem with It, it is correctly configured and working fine.
But my problem is that I need to know the latitude and longitude of the map when the users move the map (no typing, moving).
The workflow I need a kind of property 'onMapMoved', that executes a method when the users move the map (problem 1) and then getting the new latitude and longitude where the user had moved the map (problem 2).
I went through the official documentation but I am not able to find anything related, only being able to move the camera with coordinates (which I don't know how to obtain from the center of the map).
I will appreciate any help!
Thanks a lot!
Here is how to achieve it,
In short, this is the relevant code
void _onCameraMove(CameraPosition position) {
_lastMapPosition = position.target;
}
_onAddMarkerButtonPressed() {
_markers.clear();
setState(() {
_markers.add(Marker(
markerId: MarkerId(_lastMapPosition.toString()),
position: _lastMapPosition,
infoWindow: InfoWindow(title: _title, snippet: _detail),
icon: BitmapDescriptor.defaultMarker));
});
}
And here is full code, with all the generally required stuff,
import 'dart:async';
import 'package:bazar/assets/colors/ThemeColors.dart';
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:geocoder/geocoder.dart';
import 'package:geolocator/geolocator.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:sliding_up_panel/sliding_up_panel.dart';
class LocationScreen extends StatefulWidget {
#override
_LocationChooserState createState() => _LocationChooserState();
}
class _LocationChooserState extends State<LocationScreen> {
Completer<GoogleMapController> _controller = Completer();
static const LatLng _center = const LatLng(45.343434, -122.545454);
final Set<Marker> _markers = {};
LatLng _lastMapPosition = _center;
MapType _currentMapType = MapType.normal;
String _title = "";
String _detail = "";
TextEditingController _lane1;
TextEditingController _lane2;
TextEditingController _lane3;
#override
void initState() {
super.initState();
_lane1 = new TextEditingController();
}
#override
Widget build(BuildContext context) {
double _height = MediaQuery.of(context).size.height;
double _width = MediaQuery.of(context).size.width;
return SafeArea(
child: Scaffold(
resizeToAvoidBottomPadding: true,
body: Stack(
children: [
GoogleMap(
mapToolbarEnabled: false,
// myLocationEnabled: true,
// myLocationButtonEnabled:true,
zoomControlsEnabled: false,
onMapCreated: _onMapCreated,
initialCameraPosition:
CameraPosition(target: _center, zoom: 11.0),
markers: _markers,
mapType: _currentMapType,
onCameraMove: _onCameraMove,
onTap: _handleTap,
),
Padding(
padding: EdgeInsets.all(20),
child: Align(
alignment: Alignment.topRight,
child: Column(
children: <Widget>[
_customButton(
FontAwesomeIcons.map, _onMapTypeButtonPressed),
SizedBox(
height: 15,
),
_customButton(
FontAwesomeIcons.mapMarker, _onAddMarkerButtonPressed),
SizedBox(
height: 5,
),
_customButton(FontAwesomeIcons.mapPin, _getUserLocation),
],
),
),
),
SlidingUpPanel(
minHeight: _height * 0.05,
maxHeight: _height * 0.4,
panel: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Container(
height: 4,
width: _width * 0.2,
color: Orange,
),
SizedBox(
height: 10,
),
Container(
color: White,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
height: _height * 0.2,
width: _width,
color: White,
child: TextField(
maxLines: 4,
controller: _lane1,
decoration: InputDecoration(
focusedBorder: OutlineInputBorder(
borderRadius:
BorderRadius.all(Radius.circular(4)),
borderSide:
BorderSide(width: 1, color: Orange),
),
errorBorder: OutlineInputBorder(
borderRadius:
BorderRadius.all(Radius.circular(4)),
borderSide:
BorderSide(width: 1, color: Maroon),
),
errorStyle: TextStyle(
color: Orange.withOpacity(0.5)),
labelStyle: TextStyle(
color: Orange.withOpacity(0.5)),
labelText: "Address "),
cursorColor: Orange,
),
),
],
),
),
SizedBox(
height: 10,
),
Container(
child: InkWell(
onTap: () {
debugPrint("Save Address");
},
child: Container(
alignment: Alignment.center,
width: _width * 0.3,
height: 40,
padding: EdgeInsets.only(
left: 10, right: 10, top: 6, bottom: 6),
decoration: BoxDecoration(
color: Orange,
borderRadius: BorderRadius.circular(12)),
child: Text(
"Save",
style: TextStyle(
color: White,
fontSize: 20,
fontWeight: FontWeight.bold),
),
),
),
)
],
),
),
body: null)
],
),
// floatingActionButton: FloatingActionButton.extended(
// onPressed: _goToTheLake,
// label: Text('To the lake!'),
// icon: Icon(Icons.directions_boat),
// ),
),
);
}
void _onMapCreated(GoogleMapController controller) {
_controller.complete(controller);
}
void _onCameraMove(CameraPosition position) {
_lastMapPosition = position.target;
}
_customButton(IconData icon, Function function) {
return FloatingActionButton(
heroTag: icon.codePoint,
onPressed: function,
materialTapTargetSize: MaterialTapTargetSize.padded,
backgroundColor: White,
child: Icon(
icon,
size: 16,
color: Maroon,
),
);
}
_onMapTypeButtonPressed() {
setState(() {
_currentMapType = _currentMapType == MapType.normal
? MapType.satellite
: MapType.normal;
});
}
_onAddMarkerButtonPressed() {
_markers.clear();
setState(() {
_markers.add(Marker(
markerId: MarkerId(_lastMapPosition.toString()),
position: _lastMapPosition,
infoWindow: InfoWindow(title: _title, snippet: _detail),
icon: BitmapDescriptor.defaultMarker));
});
}
_handleTap(LatLng point) {
_markers.clear();
_getLocation(point);
setState(() {
_markers.add(Marker(
markerId: MarkerId(point.toString()),
position: point,
infoWindow: InfoWindow(title: _title, snippet: _detail),
icon: BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueOrange),
));
});
}
_getLocation(LatLng point) async {
final coordinates = new Coordinates(point.latitude, point.longitude);
var addresses =
await Geocoder.local.findAddressesFromCoordinates(coordinates);
var first = addresses.first;
print("${first.featureName} : ${first.addressLine}");
setState(() {
_title = first.featureName;
_detail = first.addressLine;
_lane1.text = _title + " " + _detail;
});
}
_getUserLocation() async {
Position position = await Geolocator()
.getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
final coordinates = new Coordinates(position.latitude, position.longitude);
var addresses =
await Geocoder.local.findAddressesFromCoordinates(coordinates);
var first = addresses.first;
print("${first.featureName} : ${first.addressLine}");
final GoogleMapController controller = await _controller.future;
controller.animateCamera(
CameraUpdate.newCameraPosition(
CameraPosition(
target: LatLng(position.latitude, position.longitude), zoom: 16),
),
);
setState(() {
_title = first.featureName;
_detail = first.addressLine;
_lane1.text = _title + " " + _detail;
});
}
}
Hope it helps, I have a button to add a marker you can easily make it on the go, as required.
If you have a Completer called _controller:
Completer<GoogleMapController> _controller = Completer();
Future<LatLng> getCenter() async {
final GoogleMapController controller = await _controller.future;
LatLngBounds visibleRegion = await controller.getVisibleRegion();
LatLng centerLatLng = LatLng(
(visibleRegion.northeast.latitude + visibleRegion.southwest.latitude) / 2,
(visibleRegion.northeast.longitude + visibleRegion.southwest.longitude) / 2,
);
return centerLatLng;
}
Here's how to call the future:
LatLng _currentCenter = await getCenter();

Ontap is not working on Google Maps marker in flutter

I am working on a project, i am using google_maps_flutter to show maps and markers on the screen & search_map_place to search places on the map, i have provided the source code below, there is a bug in the source code, whole project is control through bottom navigation, when first time i run the app, i navigate to the map screen, it displays markers from database and onTap also works perfectly, but when i navigate to any other screen and navigate back to map screen again, onTap doesn't work on the markers.
displaying markers on the map:
_onMapCreated() async {
// print(customerInfo);
for (var item in ud.customerInfo) {
if (item['customer_latitude'] == "" && item['customer_longitude'] == "") {
continue;
} else {
final MarkerId markerId = MarkerId((markers.length + 1).toString());
LatLng markerPos = LatLng(double.parse(item['customer_latitude']),
double.parse(item['customer_longitude']));
final Marker marker = Marker(
infoWindow: InfoWindow(
title: item['customer_name'],
snippet: item['customer_desc'],
),
// onTap: () => _onMarkerTapped(markerId),
icon: BitmapDescriptor.defaultMarkerWithHue(
item['customer_status'] == 'red'
? BitmapDescriptor.hueRed
: item['customer_status'] == 'yellow'
? BitmapDescriptor.hueYellow
: BitmapDescriptor.hueGreen),
markerId: markerId,
consumeTapEvents: true,
position: markerPos,
onTap: () {
Navigator.push(
context,
MaterialPageRoute<Null>(
builder: (BuildContext context) {
return CustomerDetail(
item['customer_id'],
item['customer_name'],
item['customer_email'],
item['customer_desc'],
item['customer_phone'],
item['customer_status']);
},
fullscreenDialog: true,
));
});
_markers = null;
markers[markerId] = marker;
}
}
setState(() {});
}
complete code:
String _mapStyle;
GoogleMapController controller;
List<Map> customerInfo;
class MapS extends StatefulWidget {
#override
_MapSState createState() => _MapSState();
}
class _MapSState extends State<MapS> {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Search Map Place Demo',
home: MainScreen(),
);
}
}
MapType _mapType = MapType.normal;
Map<MarkerId, Marker> markers = <MarkerId, Marker>{};
class MapSample extends StatefulWidget {
#override
State<MapSample> createState() => MapSampleState();
}
class MapSampleState extends State<MapSample> {
#override
void initState() {
super.initState();
getCustomerInfo();
rootBundle.loadString('assets/map_style.txt').then((string) {
_mapStyle = string;
});
getCurrentLocation();
setCustomMapPin();
// _onMapCreated(controller);
setState(() {
_onMapCreated();
});
}
Future getCustomerInfo() async {
// getting customer info using saleManagerID
var customerInfoUrl = "http://.../calender/getCustomerInfo.php";
customerInfoResponse = await http.post(customerInfoUrl, body: {
"sm_id": sm.sm_id,
});
if (jsonDecode(customerInfoResponse.body) == "No Customers") {
String noCustomers = jsonDecode(customerInfoResponse.body);
ud.customerInfo = [];
} else {
ud.customerInfo = jsonDecode(customerInfoResponse.body);
print('user data got!');
}
// print(ud.customerInfo);
}
Widget _mapTypeSwitcher() => Align(
alignment: const Alignment(0.95, -0.7),
child: FloatingActionButton(
mini: true,
heroTag: null,
tooltip: 'Map Type',
child: const Icon(Icons.layers),
onPressed: () {
final MapType nextType =
MapType.values[_mapType.index == 2 ? 1 : 2];
setState(() {
print(nextType.toString());
_mapType = nextType;
});
},
),
);
_onMapCreated() async {
// print(customerInfo);
for (var item in ud.customerInfo) {
if (item['customer_latitude'] == "" && item['customer_longitude'] == "") {
continue;
} else {
final MarkerId markerId = MarkerId((markers.length + 1).toString());
LatLng markerPos = LatLng(double.parse(item['customer_latitude']),
double.parse(item['customer_longitude']));
final Marker marker = Marker(
infoWindow: InfoWindow(
title: item['customer_name'],
snippet: item['customer_desc'],
),
// onTap: () => _onMarkerTapped(markerId),
icon: BitmapDescriptor.defaultMarkerWithHue(
item['customer_status'] == 'red'
? BitmapDescriptor.hueRed
: item['customer_status'] == 'yellow'
? BitmapDescriptor.hueYellow
: BitmapDescriptor.hueGreen),
markerId: markerId,
consumeTapEvents: true,
position: markerPos,
onTap: () {
Navigator.push(
context,
MaterialPageRoute<Null>(
builder: (BuildContext context) {
return CustomerDetail(
item['customer_id'],
item['customer_name'],
item['customer_email'],
item['customer_desc'],
item['customer_phone'],
item['customer_status']);
},
fullscreenDialog: true,
));
});
_markers = null;
markers[markerId] = marker;
}
}
setState(() {});
}
void getCurrentLocation() async {
Position res = await Geolocator()
.getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
setState(() {
position = res;
// _child = mapWidget();
print(res);
mapToggle = true;
});
}
Completer<GoogleMapController> mapController = Completer();
Set<Marker> _markers = Set();
// custom marker
BitmapDescriptor pinLocationIcon;
void setCustomMapPin() async {
pinLocationIcon = await BitmapDescriptor.fromAssetImage(
ImageConfiguration(devicePixelRatio: 4.5), 'assets/red_marker.png');
}
IconData fontAwesomeIconFromString(String name) {
switch (name) {
case 'website':
return Icons.web;
case 'phone_no':
return Icons.phone_android;
case 'desc':
return Icons.lock_outline;
case 'place':
return Icons.place;
case 'city':
return Icons.location_city;
case 'country':
return Icons.my_location;
}
}
String iconfromApi;
// textfield in bottomsheet
Widget _entryField(String title, TextEditingController tcont, String ic) {
iconfromApi = ic;
return Container(
margin: EdgeInsets.symmetric(vertical: 5),
padding: new EdgeInsets.fromLTRB(2.0, 2.0, 2.0, 2.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
TextFormField(
controller: tcont,
// obscureText: isPassword,
style: TextStyle(color: Colors.black, fontFamily: 'Montserrat'),
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: title,
prefixIcon: Icon(fontAwesomeIconFromString(iconfromApi)),
labelStyle: TextStyle(fontSize: 15)),
)
],
),
);
}
Future addData(String phone, web) async {
var url = "http://.../addData.php";
var response = await http.post(url, body: {
"name": userD.name,
"desc": userD.desc,
"status": userD.status,
"latitude": userD.latitide,
"longitude": userD.longitude,
"phone": phone != null ? phone : "n/a",
"web": web != null ? web : "n/a",
"sm_id": sm.sm_id
});
// print('Response status: ${response.statusCode}');
// print('Response body: ${response.body}');
response.body == '1' ? confirmDialog(context) : errorDialog(context);
}
Future<void> confirmDialog(BuildContext context) {
return showDialog<void>(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return AlertDialog(
title: Text('Response'),
content: const Text('Record Added!'),
actions: <Widget>[
FlatButton(
child: Text('Ok'),
onPressed: () {
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) => MainScreen()),
(Route<dynamic> route) => false);
},
),
],
);
},
);
}
Future<void> errorDialog(BuildContext context) {
return showDialog<void>(
barrierDismissible: false,
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('Response'),
content: const Text('Record submission failed'),
actions: <Widget>[
FlatButton(
child: Text('Ok'),
onPressed: () {
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) => MainScreen()),
(Route<dynamic> route) => false);
},
),
],
);
},
);
}
Widget _submitButton() {
return InkWell(
onTap: () {
print(ud.phone);
print(ud.web);
addData(ud.phone, ud.web);
},
child: Container(
width: MediaQuery.of(context).size.width,
padding: EdgeInsets.symmetric(vertical: 15),
alignment: Alignment.center,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(5)),
gradient: LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: [Hexcolor("#2a7837"), Hexcolor("#2a7837")])),
child: Text(
'Save In Database',
style: TextStyle(
fontSize: 15,
color: Colors.white,
fontWeight: FontWeight.bold,
fontFamily: 'Montserrat'),
),
),
);
}
Widget addButon = Container();
#override
Widget build(BuildContext context) {
final height = MediaQuery.of(context).size.height;
return Stack(
children: <Widget>[
GoogleMap(
myLocationEnabled: true,
myLocationButtonEnabled: true,
compassEnabled: false,
tiltGesturesEnabled: false,
mapType: _mapType,
initialCameraPosition: CameraPosition(
target: LatLng(position.latitude, position.longitude),
zoom: 15),
onMapCreated: (controller) {
mapController.complete(controller);
_onMapCreated();
// add things here on map, markers, design etc
controller.setMapStyle(_mapStyle);
},
markers:
_markers == null ? Set<Marker>.of(markers.values) : _markers
// markers: Set<Marker>.of(markers.values),
),
_mapTypeSwitcher(),
Positioned(
top: 60,
left: MediaQuery.of(context).size.width * 0.05,
// width: MediaQuery.of(context).size.width * 0.9,
child: SearchMapPlaceWidget(
apiKey: apiKEY,
location: CameraPosition(
target: LatLng(position.latitude, position.longitude),
zoom: 18)
.target,
radius: 30000,
onSelected: (place) async {
// declaring some variables
final geolocation = await place.geolocation;
// final js = geolocation.fullJSON;
controller = await mapController.future;
// get latLong in a
var latLong = geolocation.coordinates;
// to save latLong in array for db
var latLongList = new List(2);
// to save place, city & country in array for db
var loctionList = new List();
controller.animateCamera(
CameraUpdate.newLatLng(geolocation.coordinates));
controller.animateCamera(
CameraUpdate.newLatLngBounds(geolocation.bounds, 0));
print(place.fullJSON);
// converting LatLong to string and then array
latLong = latLong.toString().replaceAll(RegExp("[a-zA-Z]"), '');
latLong =
latLong.toString().replaceAll(RegExp("[\\[\\](){}]"), '');
ud.customerDetials = place.fullJSON['place_id'];
latLongList = latLong.split(', ');
print(latLongList[0]);
print(latLongList[1]);
// print(prettyJson(place.fullJSON, indent: 2));
// print(a.runtimeType);
// adding retrived values to object
userD.name = place.fullJSON['structured_formatting']['main_text'];
// place.fullJSON['structured_formatting']['secondary_text'] == null
// ? userD.desc = c_desc.text
// : userD.desc =
// place.fullJSON['structured_formatting']['secondary_text'];
// c_phone_no.text = c_place.text =
// c_city.text = c_country.text = c_desc.text = '';
// userD.place = c_place.text;
// userD.city = c_city.text;
// userD.country = c_country.text;
userD.phone = ud.phone;
userD.web = ud.web;
userD.latitide = latLongList[0];
userD.longitude = latLongList[1];
userD.status = "red";
setState(() {
markers = <MarkerId, Marker>{};
_markers = new Set();
_markers.add(
Marker(
markerId: MarkerId(place.fullJSON['place_id']),
position: geolocation.coordinates,
icon: pinLocationIcon,
infoWindow: InfoWindow(
title: place.fullJSON['structured_formatting']
['main_text'],
snippet: place.fullJSON['structured_formatting']
['secondary_text'])),
);
// markers = null;
});
// print(js);
// savejson(js);
addButon = new RawMaterialButton(
onPressed: () async {
var responseDetails =
await getLocationDetails(place.fullJSON['place_id']);
ud.phone =
responseDetails.data["result"]["formatted_phone_number"];
ud.web = responseDetails.data["result"]["website"];
showStopper(
context: context,
stops: [0.5 * height, height],
builder:
(context, scrollController, scrollPhysics, stop) {
return Padding(
padding: const EdgeInsets.all(18.0),
child: ListView(
controller: scrollController,
physics: scrollPhysics,
children: [
// show location name
Text(
userD.name,
style: TextStyle(
color: Colors.black,
fontSize: 30,
fontWeight: FontWeight.bold,
fontFamily: 'Montserrat'),
),
SizedBox(
height: 50,
),
// location desc
Text(
'Description:',
style: TextStyle(
color: Colors.black,
fontSize: 20,
fontWeight: FontWeight.bold,
fontFamily: 'Montserrat'),
),
SizedBox(
height: 10,
),
userD.desc == null
? _entryField("Description", c_desc, 'desc')
: Text(
userD.desc,
style: TextStyle(
color: Colors.black,
fontSize: 15,
fontFamily: 'Montserrat'),
),
SizedBox(
height: 20,
),
// add website, phone, place, city, country
Text(
ud.phone != null ? ud.phone : "phone: n/a"),
Text(ud.web != null ? ud.web : "website: n/a"),
// _userInfoWidget(),
// _entryField("Website", c_websitee, 'website'),
SizedBox(
height: 20,
),
_submitButton()
]),
);
});
},
child: new Icon(
Icons.add_location,
color: Hexcolor('#2a7837'),
size: 35.0,
),
shape: new CircleBorder(),
elevation: 2.0,
fillColor: Colors.white,
padding: const EdgeInsets.all(15.0),
);
},
),
),
// 2 floating buttons
Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
addButon,
new RawMaterialButton(
onPressed: () {
// Navigator.push(
// context,
// MaterialPageRoute<Null>(
// builder: (BuildContext context) {
// return MyApp();
// },
// fullscreenDialog: true,
// ));
_markers = null;
_onMapCreated();
},
child: new Icon(
Icons.person,
color: Hexcolor('#2a7837'),
size: 35.0,
),
shape: new CircleBorder(),
elevation: 2.0,
fillColor: Colors.white,
padding: const EdgeInsets.all(15.0),
),
// feedback button
new RawMaterialButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute<Null>(
builder: (BuildContext context) {
return FeedBackModal();
},
fullscreenDialog: true,
));
},
child: new Icon(
Icons.feedback,
color: Hexcolor('#2a7837'),
size: 35.0,
),
shape: new CircleBorder(),
elevation: 2.0,
fillColor: Colors.white,
padding: const EdgeInsets.all(15.0),
),
],
)
],
),
)
],
);
}
Future getLocationDetails(placeId) async {
try {
String requestUrl =
"https://maps.googleapis.com/maps/api/place/details/json?place_id=$placeId&fields=website,formatted_phone_number&key=$apiKEY";
Response placeDetails = await Dio().get(requestUrl);
return placeDetails;
} catch (e) {
print(e);
}
// ud.phone= placeDetails.data["result"]["formatted_phone_number"];
// ud.web= placeDetails.data["result"]["web"];
}
}
class MainScreen extends StatefulWidget {
#override
_MainScreenState createState() => _MainScreenState();
}
class _MainScreenState extends State<MainScreen> {
// bottom navigation variables
int _selectedIndex = 0;
static const TextStyle optionStyle =
TextStyle(fontSize: 30, fontWeight: FontWeight.bold);
List<Widget> _widgetOptions = <Widget>[
Kpi(),
Customers(),
MapSample(),
AddMeeting(),
Customers(),
];
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
fd.indexForFeedback = _selectedIndex;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: _widgetOptions.elementAt(fd.indexForFeedback),
),
bottomNavigationBar: BottomNavigationBar(
unselectedItemColor: Colors.white,
type: BottomNavigationBarType.fixed,
backgroundColor: Colors.black,
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.insert_chart),
title: Text('KPI'),
),
BottomNavigationBarItem(
icon: Icon(Icons.people),
title: Text('Customers'),
),
BottomNavigationBarItem(
icon: Icon(Icons.add_location),
title: Text('Map'),
),
BottomNavigationBarItem(
icon: Icon(Icons.calendar_today),
title: Text('Calender'),
),
BottomNavigationBarItem(
icon: Icon(Icons.group_add),
title: Text('Quotes'),
),
],
currentIndex: fd.indexForFeedback,
selectedItemColor: Hexcolor('#2a7837'),
onTap: _onItemTapped,
),
);
}
}
Replace
child: _widgetOptions.elementAt(fd.indexForFeedback),
With
child: IndexedStack(
children: _widgetOptions,
index: fd.indexForFeedback,
),
It prevents from redrawing the map every time you switch between tabs, and avoid memory leaks.
See also: https://www.youtube.com/watch?v=_O0PPD1Xfbk