I am having an error with Flutter saying: Controller's length property does not match - flutter

I have been having this issue in Flutter when I am trying to use the DefaultTabController() widget but it seems it does not work the way I have specified the layout. Can anyone help me with it.
This is my code:
class HomeScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 3,
initialIndex: 0,
child: Scaffold(
appBar: AppBar(
leading: IconButton(icon: Icon(Icons.menu), onPressed: () {}),
title: Text('Home'),
bottom: TabBar(tabs: [
Tab(child: Text("Videos")),
Tab(child: Text("Live Videos")),
Tab(child: Text("Gallery")),
]),
),
body: TabBarView(
children: [
new Card(
color: Colors.blue,
),
],
),
));
}
}
What am I doing wrong here?

Your body element only contains one element. According to your length attribute of the DefaultTabController, there should be 3 elements in that array.
body: TabBarView(
children: [
new Card(
color: Colors.blue,
),
new Card(
color: Colors.red,
),
new Card(
color: Colors.orange,
),
],
),

Related

How can i implement navigation drawer under appbar in flutter

I want to implement navigation drawer in flutter like this screenshot. But don't know how.
Please give me some code hint.
Thank you.
This is the image I like to archive
use the Drawer Widget in scaffold
this is an example from the official documentation
Scaffold(
appBar: AppBar(
title: const Text('Drawer Demo'),
),
drawer: Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: const <Widget>[
DrawerHeader(
decoration: BoxDecoration(
color: Colors.blue,
),
child: Text(
'Drawer Header',
style: TextStyle(
color: Colors.white,
fontSize: 24,
),
),
),
ListTile(
leading: Icon(Icons.message),
title: Text('Messages'),
),
ListTile(
leading: Icon(Icons.account_circle),
title: Text('Profile'),
),
ListTile(
leading: Icon(Icons.settings),
title: Text('Settings'),
),
],
),
),
);
this is the result =>
You have to use the Drawer widget.
Scaffold(
drawer: Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: [
ListTile(
title: const Text('Item 1'),
onTap: (){
// do something
},
),
ListTile(
title: const Text('Item 2'),
onTap: (){
// do something
},
),
],
),
),
...
And that's pretty much it! Learn more about Drawer, here.
An easy to archive this is using another Scaffold on body and using drawer there. And to control the drawer use ScaffoldState GlobalKey.
Result
Widget
class _MyApp extends StatefulWidget {
#override
State<_MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<_MyApp> {
static final GlobalKey<ScaffoldState> _key = GlobalKey();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
onPressed: () {
if (_key.currentState != null) {
if (_key.currentState!.isDrawerOpen) {
Navigator.pop(_key.currentContext!);
} else {
_key.currentState!.openDrawer();
}
}
},
icon: const Icon(
Icons.more,
),
),
),
body: Scaffold(
key: _key,
drawer: Drawer(
child: Container(
color: Colors.red,
),
),
body: Column(
children: const [
Text("Child"),
],
),
));
}
}

how to get Data from Tabs in main flutter

I have a class where there are 2 Tabs (used DefaultTabController) . AppBar have Action button/Text to save the Edited Text in each tab either It may tab0 or tab1. Both Tabs are separate stateful widget . I don't know, how to get How to get EditedText/String from a tab when save action is pressed in main Class ?
I looked into the similar Question but didn't get idea from it Flutter: send Data from TabBarView (StatefullWidgets) back to main Scaffold
your help would be appreciated .Thanks a lot.
class EditPocketMoney extends StatefulWidget {
#override
_EditPocketMoneyState createState() => _EditPocketMoneyState();
}
class _EditPocketMoneyState extends State<EditPocketMoney> {
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
backgroundColor: Theme.of(context).primaryColor,
appBar: AppBar(
elevation: 0.0,
automaticallyImplyLeading: false,
leading: IconButton(icon: Icon(Icons.clear,color: Color(0xffE44663),), onPressed: (){Navigator.pop(context);}),
title: Text('Edit',style: TextStyle(color: Colors.white,fontFamily: 'SF Pro Text',fontSize: 17.0, ),),
centerTitle: true,
actions: [
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
InkWell(
onTap: (){
},
child: Container(
margin:EdgeInsets.only(right:15.0 ),
child: Text('SAVE',style: TextStyle(color: Color(0xffE44663),fontFamily: 'SF Pro Text',fontSize: 17.0, ),)),
),
],
),
],
bottom: PreferredSize(
preferredSize: Size(MediaQuery.of(context).size.width*0.8, 45.0),
child: Container(
margin: EdgeInsets.only(left: 18.0,right: 18.0,top: 5.0),
child: TabBar(
unselectedLabelColor: Colors.white,
labelColor:Colors.black ,
labelPadding: EdgeInsets.all(8.0),
tabs: [
Center(child: Text('Per Day',style: TextStyle(fontSize: 15.0,fontWeight: FontWeight.w600),)),
Center(child: Text('Per Month',style: TextStyle(fontSize: 15.0,fontWeight: FontWeight.w600),)),
],
indicator: BoxDecoration(
borderRadius: BorderRadius.circular(10.0),
color: Colors.white,
),),
),
),
),
body: TabBarView(children: [
PocketMoneyPerDay(),
PocketMoneyEditPerMonth()
])
),
);
}
You can use any State Management package like Provider.
Refer this link for Provider https://medium.com/flutterpub/provider-state-management-in-flutter-d453e73537c5
I have given example using Provider package.
ChangeNotifier code:
class Data extends ChangeNotifier {
TextEditingController tab_0_controller = TextEditingController();
TextEditingController tab_1_controller = TextEditingController();
}
Tab0 TextField code:
TextField(
controller: Provider.of<Data>(context).tab_0_controller;
)

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,
// ),
],
),
),
),
);
}
}

MaterialApp just started to behave weird creating screens I have not clicked on

My MaterialApp started to behave strange today. The TournamnetScreen is created twice when I click on the admin tab.
What could possible cause this? I upgraded flutter yesterday. (stable channel)
#override
Widget build(BuildContext context) {
debugPrint("Starting Chess Champion");
return MaterialApp(
theme: new ThemeData(
primarySwatch: Colors.blue,
scaffoldBackgroundColor: Colors.grey
),
home: DefaultTabController(
length: 5,
child:
Scaffold(
appBar: AppBar(
title: Text('Chess Champion', style: new TextStyle(fontWeight: FontWeight.normal, fontSize: 30.0)),
bottom: TabBar(
tabs: [
Tab(icon: Icon(Icons.home)),
Tab(icon: Icon(AntDesign.table)),
Tab(icon: Icon(Octicons.versions)),
Tab(icon: Icon(MaterialCommunityIcons.podium)),
Tab(icon: Icon(Octicons.tools)),
],
),
),
body: TabBarView(
children: [
HomeScreen(title: 'Home',),
DataTableScreen(),
ChangelogScreen(),
TeamTournamentScreen(),
AdminScreen(),
],
),
),
),
);
}
Admin widget here ..
class AdminScreen extends StatelessWidget {
final _scaffoldKey = GlobalKey<ScaffoldState>();
#override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(title: Text('Admin')),
body: Builder(builder: (BuildContext context) {
return Column(
children: <Widget>[
RaisedButton(
onPressed: _createTour2,
child: new Text('Create a tournament2'),
),
RaisedButton(
onPressed: _readTour,
child: new Text('Read a tournament'),
),
RaisedButton(
onPressed: _deleteTour,
child: new Text('Delete a tournament'),
),
RaisedButton(
onPressed: _setTourLevel,
child: new Text('Set level in all Tournaments'),
),
RaisedButton(
onPressed: _listTours,
child: new Text('List Tournaments'),
),
RaisedButton(
onPressed: _listTour2s,
child: new Text('List Tournament2s '),
),
RaisedButton(
onPressed: _deleteDuplicatedTours,
child: new Text('Delete Duplicated Tournaments'),
),
RaisedButton(
onPressed: _scrapeAllsvenskan,
child: new Text('Scrape Allsvenskan'),
),
RaisedButton(
onPressed: _listClubs,
child: new Text('List Clubs'),
),
RaisedButton(
onPressed: _updateTour,
child: new Text('Update a Tournament'),
),
RaisedButton(
onPressed: _deleteDuplicatClubs,
child: new Text('Remove duplicate Clubs'),
),
RaisedButton(
onPressed: _dbCounts,
child: new Text('Database Counts'),
),
],
);
}),
);
}
This turned out to be to the fact that I accidentically created two MaterialApp's.

I want to place a custom widget in place of appbar and want a tab view below it

I have built a custom widget("cab") which displays a account login circle and no. of points user have.
I want a tab view just below it . For now I have placed this custom widget inside the tab itself :
bottomNavigationBar: Material(child: TabBar(
tabs: const <Widget>[
Tab( icon: Icon(Icons.add)),
Tab( icon: Icon(Icons.search))
]
),),
body :TabBarView(
children: <Widget>[
Column(
children: <Widget>[
cab
],
),
But I want this widget to be displayed above tab view but not the part of tab view itself . How can I do
this?
Thanks.
Replace the AppBar widget with your own widget below:
class App extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: DefaultTabController(
length: 2,
child: Scaffold(
bottomNavigationBar: TabBar(
labelColor: Colors.orange,
unselectedLabelColor: Colors.grey,
indicatorSize: TabBarIndicatorSize.tab,
indicatorColor: Colors.orange,
tabs: [
Tab(
icon: Icon(Icons.add),
),
Tab(
icon: Icon(Icons.search),
),
],
),
body: Column(
children: <Widget>[
// Remove the AppBar code below and put your "cab" widget
AppBar(
primary: true,
title: Text('Here is your cab'),
centerTitle: true,
backgroundColor: Colors.orange,
),
Expanded(
child: TabBarView(
children: [
Icon(Icons.add),
Icon(Icons.search),
],
),
),
],
),
),
),
);
}
}