I've started playing with Flutter a little bit.
I created a page, that looks like this:
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:smooth_star_rating/smooth_star_rating.dart';
import 'package:intl/intl.dart';
class LandOffer extends StatefulWidget {
final String startPoint;
final String endPoint;
const LandOffer({Key key, this.startPoint, this.endPoint}) : super(key: key);
#override
State<StatefulWidget> createState() {
return _LandOffer(startPoint: this.startPoint, endPoint: this.endPoint);
}
}
class _LandOffer extends State<LandOffer> {
final String startPoint;
final String endPoint;
var _json;
String _name;
String _lastName;
String _image;
var isLoading = false;
_fetchBackendData() async {
setState(() {
isLoading = true;
print('Beginning loading');
});
final response =
await http.get("https://randomuser.me/api/?inc=name,picture");
if (response.statusCode == 200) {
_json = json.decode(response.body);
setState(() {
isLoading = false;
_name = toBeginningOfSentenceCase(_json['results'][0]['name']['first']);
_lastName =
toBeginningOfSentenceCase(_json['results'][0]['name']['last']);
_image = _json['results'][0]['picture']['large'];
print('Done loading...');
});
} else {
throw Exception('Failed to load backend data');
}
}
#override
void initState() {
super.initState();
_fetchBackendData().then((result) {
print('Feched data from backend');
});
}
_LandOffer({this.startPoint, this.endPoint});
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Describe your offer '),
automaticallyImplyLeading: true,
),
body: isLoading
? Center(
child: CircularProgressIndicator(),
)
: ListView(
children: <Widget>[
Column(
children: <Widget>[
Row(
children: <Widget>[
Image(
image: NetworkImage(_image),
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'First name: $_name',
textAlign: TextAlign.left,
),
Text(
'Last name: $_lastName',
textAlign: TextAlign.left,
),
Text('Rating'),
SmoothStarRating(
rating: 3.2,
),
],
),
],
),
],
),
],
));
}
}
which in additions displays the image like this:
But it seems like there is a padding added to a text.
I would like to move the text to the very top, and add a padding, should I need one.
Also, if I apply the padding to the image, it applies the padding to the whole row, which is not the desired result.
Thank you in advance for your help.
Because your image height are bigger one in row, if you add padding(assume both top,bottom,left,right) to image, the row height will be expanded too. Unless you only want padding(left, right) or you need constraint image height.
Row(
crossAxisAlignment: CrossAxisAlignment.start, //<-- move text top
children: <Widget>[
Padding(
padding: EdgeInsets.all(5),
child: Image(
image: NetworkImage(_image),
),
),
Column(
crossAxisAlignment: CrossAxisAlignment.start, //<-- move text top
children: <Widget>[
Text(
'First name: $_name',
textAlign: TextAlign.left,
),
Text(
'Last name: $_lastName',
textAlign: TextAlign.left,
),
Text('Rating'),
SmoothStarRating(
rating: 3.2,
),
],
),
],
),
Related
I'm relatively new to Flutter and have tried to find similar postings to help me but haven't had any luck in getting them to work for me unfortunately. I have an Android Studio program that's basically a game which involves a grid of flip cards. I have the flip cards in one dart file and the app bar in another. I have an iconbutton on the app bar which currently reduces the point count to zero, but I would also like for it to flip all of the flip cards back to their original positions when pressed. I have a global variable called resetBool that I've been trying to use, something like if resetBool == true then toggleCard() maybe. I think I might need to use a key but am having trouble implementing one properly.
Here is the code in the file which contains my appbar:
import 'package:flip_card/flip_card.dart';
import 'package:flutter/material.dart';
import 'gridone.dart' as gridone;
import 'globalVariables.dart';
import 'statenames.dart';
int count;
StateNames stateObject = new StateNames();
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home>with SingleTickerProviderStateMixin {
TabController controller;
#override
void initState() {
controller = new TabController(length: 1, vsync: this);
super.initState();
}
#override
void dispose() {
controller.dispose();
super.dispose();
}
void changeCount() {
setState(() {
counter += 1;
});
}
void decreaseCount() {
setState(() {
counter -= 1;
});
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title:new Text("License plate game"),
backgroundColor: Colors.greenAccent,
actions: <Widget>[
IconButton(
icon: Icon(
Icons.autorenew,
color: Colors.white,
),
onPressed: () {
setState(() {
counter = 0;
resetBool = true;
});
},
),
Center(
child: Container(
padding: EdgeInsets.fromLTRB(20, 20, 20, 20),
child: Text('points: $counter', textAlign: TextAlign.center, style: TextStyle(fontSize: 15),
)
),
),
],
bottom: new TabBar(
controller: controller,
indicatorWeight: 5.0,
indicatorColor: Colors.green,
tabs: <Widget> [
new Tab(icon: new Icon(Icons.image),),
],
),
),
body: new TabBarView(
controller: controller,
children: <Widget>[
new gridone.GridOne(changeCount, decreaseCount),
],
)
);
}
}
And here is the code in the file which contains my flip cards:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flip_card/flip_card.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'statenames.dart';
import 'globalVariables.dart';
import 'Home.dart';
import 'gridtwo.dart' as gridTwo;
StateNames stateObject = new StateNames();
Home homeObject = new Home();
class GridOne extends StatefulWidget {
final Function updateCounter;
final Function decreaseCount;
GridOne(this.updateCounter, this.decreaseCount);
#override
_GridOneState createState() => _GridOneState();
}
class _GridOneState extends State<GridOne>
with AutomaticKeepAliveClientMixin {
#override
bool get wantKeepAlive => true;
int points = 0;
#override
Widget build(BuildContext context) {
super.build(context);
return new Scaffold(
body: new Column(
children: <Widget> [
new Expanded(
child: GridView.count(
crossAxisCount: 5,
children: List.generate(52, (index){
return Card(
elevation: 0.0,
margin: EdgeInsets.only(left: 3.0, right: 3.0, top: 9.0, bottom: 0.0),
color: Color(0x00000000),
child: FlipCard(
direction: FlipDirection.HORIZONTAL,
speed: 1000,
//(resetBool == true) ? cardKey.currentState.toggleCard() : null,
onFlipDone: (status) {
setState(() {
(status)
? widget.decreaseCount()
: widget.updateCounter();
});
if (counter == 25) {
Fluttertoast.showToast(
msg: "You've got 25 states! Wow!",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM_LEFT,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 16.0);
};
print(counter);
},
front: Container(
decoration: BoxDecoration(
color: Color(0xFF006666),
borderRadius: BorderRadius.all(Radius.circular(8.0)),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
FittedBox(fit:BoxFit.fitWidth,
child: Text(stateObject.stateNames[index], style: TextStyle(fontFamily: 'Architects Daughter', color: Colors.white), )
//Theme.of(context).textTheme.headline
),
Text('',
style: Theme.of(context).textTheme.body1),
],
),
),
back: Container(
decoration: BoxDecoration(
color: Color(0xFF006666),
borderRadius: BorderRadius.all(Radius.circular(8.0)),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Image(image: AssetImage(stateObject.licensePlatePaths[index])),
//Text('',
//style: Theme.of(context).textTheme.body1),
],
),
),
),
);
})
)
)
]
),
);
}
}
The solution is to use currentState.toggleCard(); for the cards that are facing Back when the IconButton is clicked.
Basically, what I did is I gave keys to each card at initState method.
List<GlobalKey<FlipCardState>> cardKeys = [];
#override
void initState() {
List.generate(52, (index) {
cardKeys.add(GlobalKey<FlipCardState>());
});
super.initState();
}
Don't forget to put the key to widget
FlipCard(key: cardKeys[index], ... )
Then, call resetCards method below when the button is clicked. If the card is facing back then toggle logic.
void resetCards() {
cardKeys.forEach((element) {
if (!element.currentState.isFront) {
element.currentState.toggleCard();
}
});
setState(() {});
}
You need to call a method on the parent widget, that would be triggered in the child widget. For that, please check this stackoverflow link
Full working code:
import 'package:flutter/material.dart';
import 'package:flip_card/flip_card.dart';
import 'package:fluttertoast/fluttertoast.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or simply save your changes to "hot reload" in a Flutter IDE).
// Notice that the counter didn't reset back to zero; the application
// is not restarted.
primarySwatch: Colors.blue,
// This makes the visual density adapt to the platform that you run
// the app on. For desktop platforms, the controls will be smaller and
// closer together (more dense) than on mobile platforms.
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: Home(),
);
}
}
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> with SingleTickerProviderStateMixin {
TabController controller;
int counter = 0;
final GridOneController myController = GridOneController();
#override
void initState() {
controller = new TabController(length: 1, vsync: this);
super.initState();
}
#override
void dispose() {
controller.dispose();
super.dispose();
}
void changeCount() {
setState(() {
counter += 1;
});
}
void decreaseCount() {
setState(() {
counter -= 1;
});
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("License plate game"),
backgroundColor: Colors.greenAccent,
actions: <Widget>[
IconButton(
icon: Icon(
Icons.autorenew,
color: Colors.white,
),
onPressed: () {
setState(() {
counter = 0;
myController.resetCards();
});
},
),
Center(
child: Container(
padding: EdgeInsets.fromLTRB(20, 20, 20, 20),
child: Text(
'points: $counter',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 15),
)),
),
],
bottom: new TabBar(
controller: controller,
indicatorWeight: 5.0,
indicatorColor: Colors.green,
tabs: <Widget>[
new Tab(
icon: new Icon(Icons.image),
),
],
),
),
body: new TabBarView(
controller: controller,
children: <Widget>[
new GridOne(counter, myController),
],
));
}
}
class GridOneController {
void Function() resetCards;
}
class GridOne extends StatefulWidget {
int counter;
final GridOneController controller;
GridOne(this.counter, this.controller);
#override
_GridOneState createState() => _GridOneState(controller);
}
class _GridOneState extends State<GridOne> {
_GridOneState(GridOneController _controller) {
_controller.resetCards = resetCards;
}
int points = 0;
void increaseCounter() {
widget.counter += 1;
}
void decreaseCounter() {
widget.counter -= 1;
}
void resetCards() {
cardKeys.forEach((element) {
if (!element.currentState.isFront) {
element.currentState.toggleCard();
}
});
setState(() {});
}
List<GlobalKey<FlipCardState>> cardKeys = [];
#override
void initState() {
List.generate(52, (index) {
cardKeys.add(GlobalKey<FlipCardState>());
});
super.initState();
}
#override
Widget build(BuildContext context) {
print(cardKeys.length);
return new Scaffold(
body: new Column(children: <Widget>[
new Expanded(
child: GridView.count(
crossAxisCount: 5,
children: List.generate(52, (index) {
return Card(
elevation: 0.0,
margin: EdgeInsets.only(
left: 3.0, right: 3.0, top: 9.0, bottom: 0.0),
color: Color(0x00000000),
child: new FlipCard(
key: cardKeys[index],
direction: FlipDirection.HORIZONTAL,
speed: 1000,
onFlipDone: (status) {
setState(() {
(status) ? decreaseCounter() : increaseCounter();
});
if (widget.counter == 25) {
Fluttertoast.showToast(
msg: "You've got 25 states! Wow!",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM_LEFT,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 16.0);
}
;
print(widget.counter);
},
front: Container(
decoration: BoxDecoration(
color: Color(0xFF006666),
borderRadius: BorderRadius.all(Radius.circular(8.0)),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
FittedBox(
fit: BoxFit.fitWidth,
child: Text(
'FRONT',
style: TextStyle(color: Colors.white),
)
//Theme.of(context).textTheme.headline
),
Text(
'',
),
],
),
),
back: Container(
decoration: BoxDecoration(
color: Color(0xFF006666),
borderRadius: BorderRadius.all(Radius.circular(8.0)),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[Text('BACK')],
),
),
),
);
})))
]),
);
}
}
I am attempting to build a weather app as part of a Flutter course I am taking, and a message stating:
Reducing the number of considered missed Gc histogram windows from 101 to 100
appears in my console, when I would expect weather data instead. Is anyone familiar with this message?
I am pasting the code from the screens involved below, for reference.
location_screen.dart
import 'package:flutter/material.dart';
import 'package:clima/utilities/constants.dart';
class LocationScreen extends StatefulWidget {
LocationScreen({this.locationWeather});
final locationWeather;
#override
_LocationScreenState createState() => _LocationScreenState();
}
class _LocationScreenState extends State<LocationScreen> {
#override
void initState() {
super.initState();
print(widget.locationWeather);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('images/location_background.jpg'),
fit: BoxFit.cover,
colorFilter: ColorFilter.mode(
Colors.white.withOpacity(0.8), BlendMode.dstATop),
),
),
constraints: BoxConstraints.expand(),
child: SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
FlatButton(
onPressed: () {},
child: Icon(
Icons.near_me,
size: 50.0,
),
),
FlatButton(
onPressed: () {},
child: Icon(
Icons.location_city,
size: 50.0,
),
),
],
),
Padding(
padding: EdgeInsets.only(left: 15.0),
child: Row(
children: <Widget>[
Text(
'32°',
style: kTempTextStyle,
),
Text(
'☀️',
style: kConditionTextStyle,
),
],
),
),
Padding(
padding: EdgeInsets.only(right: 15.0),
child: Text(
"It's 🍦 time in San Francisco!",
textAlign: TextAlign.right,
style: kMessageTextStyle,
),
),
],
),
),
),
);
}
}
/*
double temperature = decodedData['main']['temp'];
int condition = decodedData['weather'][0]['id'];
String cityName = decodedData['name'];
*/
loading_screen.dart
import 'package:clima/screens/location_screen.dart';
import 'package:clima/services/networking.dart';
import 'package:flutter/material.dart';
import 'package:clima/services/location.dart';
import 'package:clima/services/networking.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'location_screen.dart';
const apiKey = 'APIKEY';
class LoadingScreen extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return _LoadingScreenState();
}
}
class _LoadingScreenState extends State<LoadingScreen> {
double latitude;
double longitude;
#override
void initState() {
super.initState();
getLocation();
}
void getLocationData() async {
Location location = Location();
await location.getCurrentLocation();
latitude = location.latitude;
longitude = location.longitude;
NetworkHelper networkHelper = NetworkHelper(
'https://api.openweathermap.org/data/2.5/weather?lat=$latitude&lon=$longitude&appid=$apiKey');
var weatherData = await networkHelper.getData();
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return LocationScreen(
locationWeather: weatherData,
);
},
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: SpinKitDoubleBounce(
color: Colors.white,
size: 100.0,
),
),
);
}
}
networking.dart
import 'package:http/http.dart' as http;
import 'dart:convert';
class NetworkHelper {
NetworkHelper(this.url);
final String url;
Future getData() async {
http.Response response = await http.get(url);
if (response.statusCode == 200) {
String data = response.body;
return jsonDecode(data);
} else {
print(response.statusCode);
}
}
}
You should disconnect your app. Delete it from the device or emulator if you're using one, then cold restart your app again. It will work just fine.
It worked for me on my device.
I am trying to make two switches toggle between on and off when they are clicked. I created a StatelessWidget class for the design of the switches. However, when I use this, and call the class in my User interface class, the switches do not change state. How can I update my code to allow for there to be a change?
import 'package:flutter/material.dart';
class NotificationItem extends StatelessWidget {
NotificationItem(
{#required this.title,
#required this.pushStatus,
#required this.emailStatus});
String title;
bool pushStatus;
bool emailStatus;
#override
Widget build(BuildContext context) {
return Row(
children: <Widget>[
Expanded(
child: Padding(
padding: EdgeInsets.all(20),
child: Text(
title,
style: TextStyle(
fontFamily: kFontFamilyNormal,
fontSize: 17,
color: AppColor.text,
fontWeight: FontWeight.w500),
),
),
),
Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Switch(
value: emailStatus,
onChanged: (value) {
emailStatus = value;
print(emailStatus);
},
activeTrackColor: AppColor.primaryColorDark,
activeColor: AppColor.white,
),
Switch(
value: pushStatus,
onChanged: (value) {
pushStatus = value;
print(pushStatus);
},
activeTrackColor: AppColor.primaryColorDark,
activeColor: AppColor.white,
),
],
),
),
],
);
}
}
and the following code is how I am calling it:
NotificationItem(
title: 'New messages',
emailStatus: emailStatus,
pushStatus: pushStatus,
)
Since you are changing state, it has to be a StatefulWidget. Like so:
class NotificationItem extends StatefulWidget {
const NotificationItem({
Key key,
#required this.title,
#required this.pushStatus,
#required this.emailStatus,
});
final String title;
final bool pushStatus;
final bool emailStatus;
#override
_NotificationItemState createState() => _NotificationItemState();
}
class _NotificationItemState extends State<NotificationItem> {
String _title;
bool _pushStatus;
bool _emailStatus;
void initState() {
super.initState();
_title = widget.title;
_pushStatus = widget.pushStatus;
_emailStatus = widget.emailStatus;
}
#override
Widget build(BuildContext context) {
return Row(
children: <Widget>[
Expanded(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
_title,
),
),
),
Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Switch(
value: _emailStatus,
onChanged: (value) {
setState(() => _emailStatus = value);
print(_emailStatus);
},
),
Switch(
value: _pushStatus,
onChanged: (value) {
setState(() => _pushStatus = value);
print(_pushStatus);
},
),
],
),
),
],
);
}
}
In order to change UI state you have to use StatefulWidget
You can either convert NotificationItem into a StatefulWidget or extract each switch into its own StatefulWidget
Or I recommend you to have a look at MVVM pattern using Get libary or Stacked
Your code with Get would look like this:
import 'package:flutter/material.dart';
import 'package:get/get.dart';
class NotificationItemViewModel extends GetxController {
bool pushStatus = false;
bool emailStatus = false;
void changeEmailStatus(bool newValue) {
emailStatus = newValue;
print(emailStatus);
update();
}
void changePushStatus(bool newValue) {
pushStatus = newValue;
print(pushStatus);
update();
}
}
class NotificationItem extends StatelessWidget {
const NotificationItem({#required this.title});
final String title;
#override
Widget build(BuildContext context) {
return GetBuilder<NotificationItemViewModel>(
init: NotificationItemViewModel(),
builder: (model) {
return Row(
children: <Widget>[
Expanded(
child: Padding(
padding: const EdgeInsets.all(20),
child: Text(
title,
style: TextStyle(
fontFamily: kFontFamilyNormal,
fontSize: 17,
color: AppColor.text,
fontWeight: FontWeight.w500,
),
),
),
),
Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Switch(
value: model.emailStatus,
onChanged: model.changeEmailStatus,
activeTrackColor: AppColor.primaryColorDark,
activeColor: AppColor.white,
),
Switch(
value: model.pushStatus,
onChanged: model.changePushStatus,
activeTrackColor: AppColor.primaryColorDark,
activeColor: AppColor.white,
),
],
),
),
],
);
},
);
}
}
My main.dart has become quite lengthy, so I'm splitting it up into various other .dart files for maintainability.
My main app uses a Google Map object and I place various red location markers on it. Now, I have various FloatingActionButton() along the bottom - each one opens a Bottom Sheet, using showBottomSheet() or showModalBottomSheet().
The only way I can currently think to split the main app into various files (to keep tidy) is to have the contents of these various bottom sheets in different .dart files which then are called from the main.dart - probably the wrong way.
Main.dart
...
import 'package:flutter_app/db_manager.dart' as db_manager;
import 'package:flutter_app/section_about.dart';
import 'package:flutter_app/section_settings.dart';
void main() => runApp(MyApp());
SectionAbout sectionAbout = SectionAbout();
SectionSettings sectionSettings = SectionSettings();
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
GoogleMapController mapController;
static const LatLng _center = const LatLng(xxxxxxx, xxxxxxx);
void _onMapCreated(GoogleMapController controller) {
mapController = controller;
}
void _onCameraMove(CameraPosition position) {
_lastMapPosition = position.target;
}
final Set<Marker> _markers = {};
MapType _currentMapType = MapType.normal;
LatLng _lastMapPosition = _center;
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('My Map'),
backgroundColor: Colors.green[700],
),
//Put in a stack widget so can layer other widgets on top of map widget
body: Stack(
children: <Widget>[
GoogleMap(
mapType: _currentMapType,
markers: _markers,
onMapCreated: _onMapCreated,
onCameraMove: _onCameraMove,
initialCameraPosition: CameraPosition(
target: _center,
zoom: 11.0,
),
),
Padding(
padding: const EdgeInsets.all(16.0),
child: Align(
alignment: Alignment.bottomCenter,
child: Row(mainAxisSize: MainAxisSize.min, children: <Widget>[
SizedBox(width: 16.0),
Builder(
builder: (context) => FloatingActionButton(
child: Icon(Icons.settings, size: 36.0),
backgroundColor: Colors.green,
onPressed: () {
sectionSettings.onSheetShowContents(context); <------
}),
),
SizedBox(width: 16.0),
FloatingActionButton(
onPressed: _onDownloadTestPressed,
materialTapTargetSize: MaterialTapTargetSize.padded,
backgroundColor: Colors.green,
child: const Icon(Icons.autorenew, size: 36.0),
),
SizedBox(width: 16.0),
Builder(
builder: (context) => FloatingActionButton(
child: Icon(Icons.help, size: 36.0),
backgroundColor: Colors.green,
onPressed: () {
sectionAbout.onSheetShowContents(context); <------
}),
),
SizedBox(width: 16.0),
FloatingActionButton(
onPressed: _onDBActions,
materialTapTargetSize: MaterialTapTargetSize.padded,
backgroundColor: Colors.green,
child: const Icon(Icons.change_history, size: 36.0),
),
])),
),
],
),
),
);
}
}
Settings.dart
import 'package:flutter/material.dart';
import 'package:flutter_app/db_manager.dart' as db_manager;
class SectionSettings {
int mapTypeView = 0;
void onSheetShowContents(Context context) {
showModalBottomSheet(
//showBottomSheet(
context: context,
builder: (context) {
return ListView(
padding: EdgeInsets.all(15.0),
children: <Widget>[
ListTile(
title: Text("Map Settings"),
selected: true,
),
Divider(),
Row(
mainAxisAlignment:
MainAxisAlignment.spaceEvenly,
children: [
Column(
children: <Widget>[
Text("Map View"),
],
),
Column(
children: <Widget>[
Row(
children: <Widget>[
ChoiceChip(
label: Text("Normal Map"),
selected: mapTypeView == 0,
onSelected: (value) {
setState(() {
mapTypeView = 0;
_currentMapType =
MapType.normal;
});
},
),
SizedBox(width: 8),
ChoiceChip(
label: Text("Satelite Map"),
selected: mapTypeView == 1,
onSelected: (value) {
setState(() {
mapTypeView = 1;
_currentMapType =
MapType.satellite;
});
},
),
],
),
],
)
],
),
],
// ),
);
});
}
}
Notice how I use <OtherDartFileName>.onSheetShowContents(); and that code is moved to <OtherDartFileName> rather than have a huge section here in the main dart file.
This has introduced a problem, where I cannot modify the State of the Google Map from within this Bottom Sheet as it has no reference (and I can't seem to pass one along) of the main app state.
I want to have a Bottom Sheet that contains a button that toggles Normal View and Satellite View on the main Map (and eventually other options)
Have I structured this project completely incorrectly, or can I just reference the Map state somehow?
I also have separate .dart files for one SQFlite instance and managing all DB operations. Coding for android and will be pushing to iOS eventually.
Many thanks
This is my code so far. I dont know whats wrong, I tried a lots of youtube turolial and other things as well, but its looks like the pop wont give back the correct data. I really need help, i spend 2 days already
void main() {
List<String> names = [];
List<String> mgs = [];
runApp(MaterialApp(
title: 'Returning Data',
home: HomeScreen(names, mgs),
));
}
class HomeScreen extends StatelessWidget {
List<String> names = [];
List<String> mgs = [];
HomeScreen(this.names, this.mgs);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.blue,
title: Text("Project_Drink"),
),
body: Container(
child: Column(
children: <Widget>[
new Expanded(
child: ListView.builder
(
itemCount: mgs.length,
itemBuilder: (context, Index) {
return Text("Name: " + names[Index]
+" "+ "Mg: " + mgs[Index]);
}
)
)
],
),
),
bottomNavigationBar :BottomAppBar (
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: <Widget>[
const Expanded(child: Text("TOTAL : 200")),
FloatingActionButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => AddProduct()),
);
},
child: Icon(Icons.add),
),
],
),
),
),
);
}
}
This is the AddProduct i want this to send back the data and then i should be able to put in into a list.Lika a not pad
class AddProduct extends StatefulWidget {
#override
State createState() => new _AddProductState();
}
class _AddProductState extends State<AddProduct> {
List<String> names = [];
List<String> mgs = [];
//final TextEditingController eCtrl = new TextEditingController();
final nameController = TextEditingController();
final mgController = TextEditingController();
#override
Widget build (BuildContext ctxt) {
return new Scaffold(
appBar: AppBar(
backgroundColor: Colors.blue,
title: Text("New Drink"),
),
body: new Column(
children: <Widget>[
new TextField(
decoration: InputDecoration(
hintText: "Name",
),
controller: nameController,
),
new TextField(
decoration: InputDecoration(
hintText: "Mg",
suffixText: "Mg",
),
controller: mgController,
),
RaisedButton(
onPressed: (){
names.add(nameController.text);
mgs.add(mgController.text);
setState(() {});
nameController.clear();
mgController.clear();
Navigator.pop(context, names + mgs);
},
child: Text("ADD"),
),
],
)
);
}
}
I moved your lists to HomeScreen widget instead of main function. Your main function should just run the app
void main() {
runApp(
MaterialApp(
title: 'Returning Data',
home: HomeScreen(),
),
);
}
And I convert your HomeScreen widget to StatefulWidget insted of StatelessWidget because when you add new items and display it screen your state will change and StatelessWidget is not able to do that. It will be something like that
Navigator.push returns a future value so if you want to declare a variable with the data comes from that, you need to await for it. After you get the data you can add them into your lists but it needs to be inside setState function to update UI
class HomeScreen extends StatefulWidget {
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
List<String> names = [];
List<String> mgs = [];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.blue,
title: Text("Project_Drink"),
),
body: Container(
child: Column(
children: <Widget>[
new Expanded(
child: ListView.builder(
itemCount: mgs.length,
itemBuilder: (context, index) {
return Text("Name: " + names[index] + " " + "Mg: " + mgs[index]);
}
),
),
],
),
),
bottomNavigationBar: BottomAppBar(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: <Widget>[
Expanded(child: Text("TOTAL : 200")),
FloatingActionButton(
onPressed: () async {
// Navigator.push returns a future value so you need to await for it
var data = await Navigator.push(
context,
MaterialPageRoute(builder: (context) => AddProduct()),
);
// After you get the data from the other page you need to add them into your lists inside setState function to update UI
setState(() {
names.add(data[0]);
mgs.add(data[1]);
});
},
child: Icon(Icons.add),
),
],
),
),
),
);
}
}
I didn't change anything in your AddProduct widget.
class AddProduct extends StatefulWidget {
#override
State createState() => new _AddProductState();
}
class _AddProductState extends State<AddProduct> {
List<String> names = [];
List<String> mgs = [];
//final TextEditingController eCtrl = new TextEditingController();
final nameController = TextEditingController();
final mgController = TextEditingController();
#override
Widget build (BuildContext ctxt) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.blue,
title: Text("New Drink"),
),
body: Column(
children: <Widget>[
TextField(
decoration: InputDecoration(
hintText: "Name",
),
controller: nameController,
),
TextField(
decoration: InputDecoration(
hintText: "Mg",
suffixText: "Mg",
),
controller: mgController,
),
RaisedButton(
onPressed: (){
names.add(nameController.text);
mgs.add(mgController.text);
setState(() {});
nameController.clear();
mgController.clear();
Navigator.pop(context, names + mgs);
},
child: Text("ADD"),
),
],
)
);
}
}
Although this code should work as you want, I would suggest you to have a look at some State Management methods such as Provider, Bloc and etc. It will be more effective to create what you want to do.
try this one with simple way , when press then call this method
goToView() async {
bool data=await Navigator.push(context, new CupertinoPageRoute(builder: (BuildContext context) {
return new CoolForgot();
}));
print(data);
}
My Next View is Forgot Screen so i have used CoolForgot(), you can use as per your requirement.
then when press on back button in Next View(In my case CoolForgot()) called this
Navigator.pop(context,true);
I have pass bool value and get bool value , you can pass any type of object and get from it.