To return an empty space that causes the building widget to fill available room, return "Container()" - flutter

I'm getting this error as I wrote on the title above. I'm a new learner in flutter, I have seeking for some solution to solve it, example this link below.
But I still cannot solve the problem can anyone help me on that?
I know this might be a duplicate question, I have try my best to understand it and still cannot solve, can anyone help out? Thanks. And
below is the main.dart code :
import 'package:flutter/material.dart';
import 'package:sharing_app/MyFlutterApp_icons.dart';
import 'package:sharing_app/Sharer.dart';
import 'package:sharing_app/Customer.dart';
void main() => runApp(MainPage());
class MainPage extends StatefulWidget{
Home createState()=> Home();
}
class Home extends State<MainPage> {
#override
Widget build(BuildContext context) {
Scaffold(
appBar: AppBar(
backgroundColor: Colors.amber,
centerTitle: true,
title: Text('Welcome',
style: TextStyle(
fontSize: 16.0,
color: Colors.black87,
letterSpacing: 1.0,
),
),
),
body: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
flex: 1,
child: Container(
padding: EdgeInsets.all(20.0),
child: RaisedButton.icon(
onPressed: () {
Navigator.of(context)
.push(MaterialPageRoute(
builder: (context) {
return Sharer();
}
)
);
},
icon: Icon(
Icons.account_circle,
),
label: Text(
'Login as Sharer',
style: TextStyle(
fontFamily: 'MyFlutterApp',
color: Colors.black87,
letterSpacing: 1.0,
),
),
),
),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
flex: 1,
child: Container(
padding: EdgeInsets.all(20.0),
child: RaisedButton.icon(
onPressed: () {
Navigator.of(context)
.push(MaterialPageRoute(
builder: (context) {
return Customer();
}
)
);
},
icon: Icon(
Icons.account_circle,
),
label: Text(
'Login as Customer',
style: TextStyle(
fontFamily: 'MyFlutterApp',
color: Colors.black87,
letterSpacing: 1.0,
),
),
),
),
),
],
),
],
),
);
}
}
Error : it tells on the android studio console "A build function returned null.". Then, "To return an empty space that causes the building widget to fill available room, return "Container()". To return an empty space that takes as little room as possible, return "Container(width: 0.0, height: 0.0)"."
Can anyone help out?

Well you just forget the return statement before your Scafffold :
class Home extends State<MainPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
The build method expect a Widget (in you case the scaffold) to be return so it can draw / build this widget.

Related

Passing variables from Tab to DefaultTabController - Flutter

I have a DefaultTabController with two pages nested in a scaffold. In my scaffold's App Bar is a save button and I want this button to return a value to a previous page, based on a variable that is calculated in one of the tabs. How do I get this value?
Here is my DefaultTabController
DefaultTabController(
initialIndex: index,
length: 2,
child: Scaffold(
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
appBar: AppBar(
elevation: 0,
backgroundColor: fumigruen_accent,
leading: CloseButton(
color: Colors.black,
onPressed: () {
Navigator.of(context).pop();
},
),
actions: buildEditingActions(),
),
body: Column(children: [
tabBar(),
Expanded(
child: TabBarView(children: [
//1st Tab
GewichtsrechnerEinfach(),
//2nd Tab
Column()
]),
)
]),
));}
And here is the save-Button I want to use to pass a varaible to the previous screen
List<Widget> buildEditingActions() => [
ElevatedButton.icon(
style: ElevatedButton.styleFrom(
backgroundColor: fumigruen_accent,
elevation: 0,
foregroundColor: Colors.black,
),
onPressed: () {
Navigator.of(context).pop(gewicht);
},
icon: Icon(Icons.save),
label: Text("Speichern"))
];
The tabbar Code
Widget tabBar() => TabBar(
labelColor: Theme.of(context).primaryColor,
indicatorColor: Theme.of(context).primaryColor,
labelStyle: TextStyle(fontWeight: FontWeight.bold),
tabs: [
Tab(
child: Row(mainAxisSize: MainAxisSize.min, children: [
Icon(
Icons.assessment_outlined,
),
SizedBox(
width: 5,
),
Text("Einfach")
]),
),
Tab(
child: Row(mainAxisSize: MainAxisSize.min, children: [
Icon(
Icons.addchart,
),
SizedBox(
width: 5,
),
Text("Fortgeschritten")
]),
),
]);
and an extract of the GewichtsrechnerEinfach():
class _GewichtsrechnerEinfachState extends State<GewichtsrechnerEinfach> {
final _formKey = GlobalKey<FormState>();
num koerperlaenge = 0;
num brustumfang = 0;
var _koerperlaengeControler = TextEditingController();
var _brustumfangControler = TextEditingController();
num gewicht = 0;
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: SingleChildScrollView(
child: Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
//{two textinput fields setting the variables koerperlaenge and brustumfang are here}
Center(
child: Container(
width: MediaQuery.of(context).size.width * 0.8,
decoration: ThemeHelper().buttonBoxDecoration(context),
child: ElevatedButton(
style: ThemeHelper().buttonStyle(),
child: Padding(
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
child: Text(
"berechnen".toUpperCase(),
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
),
onPressed: () async {
if (_formKey.currentState!.validate()) {
setState(() {
gewicht = Gewichtskalkulator().einfach(
brustumfang.toDouble(),
koerperlaenge.toDouble());
});
}
}),
),
),
],
),
),
),
);
}
The variable "gewicht" is calculated and changed in the first tab "GewichtsrechnerEinfach". So how do I get the changed variable to this main screen so that I can use it while saving?
Thanks a lot :)
As I found out by chatting in comments section, you are changing a value in a Page and you want to use it in another pages or screen, this is why you should use StateManagement something like Provider.
As you said you need to change the gewicht variable and use it where ever you want.
step 1) please add provider: ^6.0.5 (or any version that is compatible) in your pubspec.yaml and call flutter pub get.
step 2) now you should create a provider class to make all the variables that you want to use everywhere, alive. please create a dart file named:
gewichtsrechner_einfach_provider.dart
step 3) now you should put these codes in you provider class:
import 'package:flutter/material.dart';
class GewichtsrechnerEinfachProvider extends ChangeNotifier{
num _gewicht = 0;
num get gewicht => _gewicht;
void setGewicht(num newGewicht){
_gewicht = newGewicht;
notifyListeners();
}
}
as you see _gewicht is private and you can use it alive entire your project.
step 4) you should add the provider to main.dart:
MultiProvider(
providers: [
// you are adding your provider
ListenableProvider.value(value: GewichtsrechnerEinfachProvider()),
],
child: MaterialApp(
debugShowCheckedModeBanner: false,
home: ...........
),
);
step 5) now you should use its setter and getter of gewicht:
as you see in _GewichtsrechnerEinfachState you are setting the value and should do this by using Consumer:
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: SingleChildScrollView(
child: Consumer<GewichtsrechnerEinfachProvider>(//note this
builder: (context, gewichtsrechnerEinfachProvider ,child) {
return Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
//{two textinput fields setting the variables koerperlaenge and brustumfang are here}
Center(
child: Container(
width: MediaQuery.of(context).size.width * 0.8,
decoration: ThemeHelper().buttonBoxDecoration(context),
child: ElevatedButton(
style: ThemeHelper().buttonStyle(),
child: Padding(
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
child: Text(
"berechnen".toUpperCase(),
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
),
onPressed: () async {
if (_formKey.currentState!.validate()) {
// and note this
gewichtsrechnerEinfachProvider.setGewicht(
Gewichtskalkulator().einfach(
brustumfang.toDouble(),
koerperlaenge.toDouble())
);
}
}),
),
),
],
),
);
}
),
),
);
}
step 6) now you should use its getter where ever you want:
List<Widget> buildEditingActions() => [
Consumer<GewichtsrechnerEinfachProvider>(
builder: (context, gewichtsrechnerEinfachProvider ,child) {
return ElevatedButton.icon(
style: ElevatedButton.styleFrom(
backgroundColor: fumigruen_accent,
elevation: 0,
foregroundColor: Colors.black,
),
onPressed: () {
// Navigator.of(context).pop(gewicht);
print('here is your result:
${gewichtsrechnerEinfachProvider.gewicht}');
},
icon: Icon(Icons.save),
label: Text("Speichern"));
}
)
];
note that you can use your provider where ever you want even with this code not just consumer:
var gewichtsrechnerEinfachProvider = Provider.of<GewichtsrechnerEinfachProvider>(context,listen: false);
as you see by changing its value the provider notifies to where you are showing it.
Ich hoffe, ich konnte dir helfen ;)
happy coding my friend...

The method RegisterCustomer isn't defined for the class Dashboard when routing to another screen in flutter

I have Dashboard screen in lib directory. The register_customer.dart file is under customers subdirectory in lib folder. I have imported register_customer.dart in dashboard screen. However the RegisterCustomer class in register_customer.dart is not resolving. Here is my code:
lib/dashboard.dart
import 'package:flutter/material.dart';
import './customers/register_customer.dart';
class MyDashboard extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
backgroundColor: defaultBackgroundColor,
elevation: 0,
leading: IconButton(
icon: Icon(
Icons.arrow_back,
color: btnTextColor,
),
onPressed: () {
//navigate to the previous page
Navigator.pop(context);
},
),
//navabar title text text
title: Text('Dashboard'),
),
body: Center(
child: Column(
children: <Widget>[
Container(
margin: const EdgeInsets.all(20.0),
//color: Colors.amber[600],
width: 200.0,
height: 250.0,
child: ListView(
children: <Widget>[
GestureDetector(
child: ListTile(
title: Text(
'Register Customer',
style:
TextStyle(fontSize: 20, color: Color(0xffE06C19)),
),
leading: Icon(
Icons.user,
color: Colors.amber,
),
),
onTap: () {
**//this is where the error is being raised**
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => RegisterCustomer()));
},
),
],
),
),
],
))),
);
}
}
lib/customers/register_customer.dart
import 'package:flutter/material.dart';
class RegisterCustomer extends StatefulWidget {
#override
_RegisterCustomerState createState() => _RegisterCustomerState();
}
String _first_name;
String _last_name;
class _RegisterCustomerState extends State<RegisterCustomer> {
final GlobalKey<FormState> _formkey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primaryColor: Colors.purple[800],
accentColor: Colors.amber,
accentColorBrightness: Brightness.dark),
home: Scaffold(
appBar: AppBar(
title: Text(
'Register Customer',
style: TextStyle(fontSize: 20),
textAlign: TextAlign.center,
),
),
body: Container(
margin: EdgeInsets.all(12),
child: Form(
key: _formkey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SizedBox(
height: 50,
),
RaisedButton(
color: Color(0xff980CF0),
textColor: Colors.white,
splashColor: Colors.grey,
padding: EdgeInsets.fromLTRB(10, 10, 10, 10),
child: Text(
'Register',
style: TextStyle(
color: Colors.orangeAccent,
fontSize: 17,
),
),
onPressed: () {
if (!_formkey.currentState.validate()) {
return;
}
//submit data to the server
},
)
],
),
),
),
),
);
}
}
I am experiencing same issue with other routes. What am I doing wrong?
I think the import path is incorrect:
import 'package:projectname/customer/register_customer.dart
if the file is in lib/customer/register_customer.dart

Flutter - Exception Caught by multiple widgets

Hi I'm trying to add a drawer to my scaffold with the help of https://flutter.dev/docs/cookbook/design/drawer
And so far I'm getting multiple errors when I try to use it (and found 2, I don't know if there is more).
Code:
#override
Widget build(BuildContext context) {
return Scaffold(
drawer: Drawer(
child: Row(
children: <Widget>[
IconButton(icon: Icon(Icons.add), onPressed: () {}),
ListView(
padding: EdgeInsets.zero,
children: <Widget>[
DrawerHeader(
child: Text(
"What's up?",
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 30),
),
decoration: BoxDecoration(color: Color(0xff171719)),
),
ListTile(
title: Text(
"Change Theme",
style: TextStyle(fontSize: 24),
),
// ignore: todo
onTap: () {}, //TODO add dark mode
),
ListTile(
title: Text(
"Sign Out",
style: TextStyle(fontSize: 24),
),
onTap: () {
AuthMethods().signOut().then(
(s) {
Navigator.pushReplacement(context,
MaterialPageRoute(builder: (context) => SignIn()));
Navigator.pop(context);
},
);
// ignore: todo
}, //TODO sign out
),
],
),
],
),
),
Exception caught by gesture:
Exception caught by rendering library:
I couldn’t reproduce it on my end, but this usually means that there’s a widget whose viewport doesn’t have the dimensions established.
This generally happens when you add a ListView directly to a Row or Column. Y would suggest wrapping your ListView with an Expanded widget (or a Container).
You should put your ListView inside a Widget that will constraint the ListView vertically, such as Expanded:
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
void main() {
runApp(
MaterialApp(
title: 'Flutter Demo',
home: Scaffold(body: MyWidget()),
),
);
}
class MyWidget extends HookWidget {
#override
Widget build(BuildContext context) {
final _drawerKey = useState<GlobalKey<ScaffoldState>>(GlobalKey());
return Scaffold(
key: _drawerKey.value,
drawer: Drawer(
child: Row(
children: <Widget>[
IconButton(icon: Icon(Icons.add), onPressed: () {}),
Expanded(
child: ListView(
padding: EdgeInsets.zero,
children: <Widget>[
DrawerHeader(
child: Text(
"What's up?",
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 30),
),
decoration: BoxDecoration(color: Color(0xff171719)),
),
ListTile(
title: Text(
"Change Theme",
style: TextStyle(fontSize: 24),
),
// ignore: todo
onTap: () {}, //TODO add dark mode
),
ListTile(
title: Text(
"Sign Out",
style: TextStyle(fontSize: 24),
),
onTap: () {
print('SIGN OUT');
}, //TODO sign out
),
],
),
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => _drawerKey.value.currentState.openDrawer(),
),
);
}
}
Solution 1: Set ListView inside Expanded
Solution 2: ListView with the attribute: shrinkWrap: true,

Remove space between widgets in Row - Flutter

I am using two widgets(Text and Flatbutton) in Row. Whatever I do, there is space between them. I don't want any space between them how to do that?
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("TextColor checking"),
),
body:
Row(mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text("Already have a account?"),
FlatButton(
onPressed: () {},
child: Text("Login"),
textColor: Colors.indigo,
),
],
),
),
);
}
}
I want like this: Already have a account? Login
If you want to create a simple text like that, dont use row or flat button. Use Rich text instead.
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("TextColor checking"),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: RichText(
text: TextSpan(
style: TextStyle(fontSize: 16, color: Colors.white),
children: <TextSpan>[
TextSpan(
text: "Don't have an account? ",
),
TextSpan(
text: "Login",
style: TextStyle(
//Add any decorations here
color: Colors.indigo,
decoration: TextDecoration.underline,
),
recognizer: TapGestureRecognizer()
..onTap = () {
//Enter the function here
},
),
],
),
),
),
),
);
}
}
You're getting the space because you are using a FlatButton and FlatButtons has padding by default. You should use a GestureDetector instead.
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("TextColor checking"),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text("Already have a account? "),
GestureDetector(
onTap: () {},
child: Text(
"Login",
style: TextStyle(
color: Colors.indigo,
),
),
),
],
),
),
),
);
}
}
I tried your code and in seams the space is not between the components, but its is the padding of the FlatButton. to remove that, you will have use another component instead of Flat Button. try the below
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("TextColor checking"),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text("Already have a account?"),
RawMaterialButton(
constraints: BoxConstraints(),
padding: EdgeInsets.all(
5.0), // optional, in order to add additional space around text if needed
child: Text('Login'),
onPressed: () {})
// FlatButton(
// onPressed: () {},
// child: Text("Login"),
// textColor: Colors.indigo,
// ),
],
),
),
),
);
}
}

'constraints.hasBoundedWidth': is not true

Following is my code
main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: "Student Info",
debugShowCheckedModeBanner: false,
home: SafeArea(
child: HomePage(),
),
);
}
}
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: ListView(
children: <Widget>[StudentScreenAppBar(), StudentGraduateList()],
),
);
}
}
class StudentScreenAppBar extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
AppBar(
leading: IconButton(
icon: Icon(
Icons.arrow_back_ios,
color: Colors.black,
size: 20.0,
),
onPressed: () {}),
centerTitle: true,
title: Text(
"Student Info",
style: TextStyle(color: Colors.black),
),
actions: <Widget>[
IconButton(
icon: Icon(
Icons.settings,
size: 20.0,
color: Colors.black,
),
onPressed: () {}),
// SizedBox(width: 10.0,),
IconButton(
icon: Icon(
Icons.settings_ethernet,
color: Colors.black,
size: 20.0,
),
onPressed: () {})
],
elevation: 0.0,
backgroundColor: Colors.white,
),
Container(
decoration: BoxDecoration(border: Border.all(color: Colors.black)),
padding: const EdgeInsets.fromLTRB(8.0, 2.0, 8.0, 2.0),
child: Image.asset(
"images/isdi_school.png",
width: 40.0,
height: 15.0,
fit: BoxFit.contain,
))
],
);
}
}
class StudentGraduateList extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.fromLTRB(0.0, 20.0, 0.0, 0.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
yearListForUgPg("Under Graduate"),
yearListForUgPg("Post Graduate")
],
),
);
}
Widget yearListForUgPg(String graduationName) {
return Column(
children: <Widget>[
Container(
padding: const EdgeInsets.fromLTRB(25.0, 4.0, 25.0, 4.0),
child: Text(
graduationName,
style:
TextStyle(color: Colors.white, fontFamily: "suisseintlMedium"),
),
decoration: BoxDecoration(color: Colors.black),
),
ListView.builder(
shrinkWrap: true,
itemBuilder: (context, index) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
"2018",
style: TextStyle(
fontFamily: "okomitoBold", color: Colors.black),
),
Icon(Icons.arrow_forward)
],
);
},
itemCount: 10,
)
],
);
}
}
The ListView Widget does not get displayed. If I comment the ListView then the code works fine and I am able to see the UI. I tried wrapping the ListView in Expanded and Flexible Widget but it does not work.
If I uncomment the ListView then I get error saying 'constraints.hasBoundedWidth': is not true. I am trying to achieve something like this in my UI:
![Image][1]
Simply wrap your -Column in Expanded Widget: that way your Column will try to occupy available space in the parent Row.
Updated code:
class StudentGraduateList extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.fromLTRB(0.0, 20.0, 0.0, 0.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Expanded(child: yearListForUgPg("Under Graduate")),
Expanded(child: yearListForUgPg("Post Graduate"))
],
),
);
}