I want BottomNavigationBar as well as TabBar in flutter without having appBar - flutter

I want BottomNavigationBar as well as TabBar in flutter without having appBar, Individually both widgets are working but when combined, it is saying The following assertion was thrown during performLayout():
RenderCustomMultiChildLayoutBox object was given an infinite size during layout.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Haate Khori',
theme: ThemeData.light().copyWith(
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage>
with SingleTickerProviderStateMixin {
int _selectedIndex = 0;
static const TextStyle optionStyle =
TextStyle(fontSize: 30, fontWeight: FontWeight.bold);
static List<Widget> _widgetOptions = <Widget>[
Donation(),
Text(
'EXPENSES',
style: optionStyle,
),
Text(
'ACTIVITIES',
style: optionStyle,
),
Text(
'GALLERY',
style: optionStyle,
),
Text(
'DONATE US',
style: optionStyle,
),
];
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Container(
child: Padding(
padding: const EdgeInsets.all(40.0),
child: SizedBox(
height: 70.0,
),
),
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [Colors.white, Colors.teal], // whitish to gray
stops: [0.0, 0.8]),
),
),
Container(
padding: EdgeInsets.all(10.0),
child: Text(
'Title goes here',
style: TextStyle(color: Colors.white, fontSize: 25.0),
),
color: Colors.teal,
),
_widgetOptions.elementAt(_selectedIndex),
],
),
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
title: Text('Home'),
backgroundColor: Colors.teal,
),
BottomNavigationBarItem(
icon: Icon(Icons.receipt),
title: Text('Expenses'),
backgroundColor: Colors.teal,
),
BottomNavigationBarItem(
icon: Icon(Icons.fiber_smart_record),
title: Text('Activities'),
backgroundColor: Colors.teal,
),
BottomNavigationBarItem(
icon: Icon(Icons.collections),
title: Text('Gallery'),
backgroundColor: Colors.teal,
),
BottomNavigationBarItem(
icon: Icon(Icons.favorite),
title: Text('Donate us'),
backgroundColor: Colors.teal,
),
],
currentIndex: _selectedIndex,
selectedItemColor: Colors.white,
unselectedItemColor: Colors.white,
onTap: _onItemTapped,
),
),
);
}
}
class Donation extends StatefulWidget {
#override
_DonationState createState() => _DonationState();
}
class _DonationState extends State<Donation>
with SingleTickerProviderStateMixin {
TabController tabController;
#override
void initState() {
// TODO: implement initState
super.initState();
tabController = TabController(length: 2, vsync: this);
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
backgroundColor: Colors.white,
body: Column(
children: <Widget>[
SizedBox(
height: 10.0,
),
TabBar(
labelColor: Colors.teal,
controller: tabController,
tabs: <Widget>[
Tab(
child: Text('Tab1'),
),
Tab(
child: Text('Tab2'),
)
],
),
Expanded(
child: Container(
child: TabBarView(
controller: tabController,
children: <Widget>[
Text(
'Hello',
style: TextStyle(fontSize: 20.0),
textAlign: TextAlign.center,
),
Text(
'World',
style: TextStyle(
fontSize: 20.0,
),
textAlign: TextAlign.center,
),
],
),
),
),
],
),
),
);
}
}
Target : What I want
&
This is what I am getting

I have attached a code snippet which is from my unComplete web app same can be useful for you I haven't used TabBar in the scaffold tab instead created a row inside the scaffold and used it, you can look into my code and can figure out something for you hope it helps.
import 'package:flutter/material.dart';
import 'package:transportWeb/provider/dimensions.dart';
import 'package:transportWeb/screens/mainScreenViews/aboutUs.dart';
import 'package:transportWeb/screens/mainScreenViews/contactUs.dart';
import 'package:transportWeb/screens/mainScreenViews/home.dart';
import 'package:url_launcher/url_launcher.dart';
import '../constants.dart';
class MainScreen extends StatefulWidget {
#override
_MainScreenState createState() => _MainScreenState();
}
class _MainScreenState extends State<MainScreen>
with SingleTickerProviderStateMixin {
TabController _tabController;
var _currentDateTime = DateTime.now();
var _currentHours;
#override
void initState() {
super.initState();
_currentHours = _currentDateTime.hour;
print(_currentHours);
_tabController = TabController(length: 3, vsync: this, initialIndex: 1);
}
#override
void dispose() {
// TODO: implement dispose
super.dispose();
_tabController.dispose();
}
#override
Widget build(BuildContext context) {
Dimensions(context);
return Scaffold(
floatingActionButton: FloatingActionButton(
tooltip: "Request Call",
backgroundColor: Colors.deepPurpleAccent,
onPressed: () {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text(
"Enter your Phone no",
style: kh3,
),
);
},
);
},
child: Icon(
Icons.phone,
color: Colors.white,
size: 30,
),
),
body: ListView(
children: [
Container(
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 0),
height: 70,
decoration: BoxDecoration(
color: Colors.transparent,
border: Border(
bottom: BorderSide(
color: Colors.grey.shade200,
width: 3,
),
),
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Padding(
padding: const EdgeInsets.only(bottom: 15),
child: RichText(
text: TextSpan(
style: kh2.copyWith(letterSpacing: 10),
children: <TextSpan>[
TextSpan(text: "JSSR "),
TextSpan(text: "Road"),
TextSpan(
text: "L",
style: kh2.copyWith(color: Colors.red),
),
TextSpan(text: "ines"),
],
),
),
),
Expanded(
child: SizedBox(
width: 0,
height: 0,
),
),
TabBar(
isScrollable: true,
indicatorColor: Colors.black,
indicatorSize: TabBarIndicatorSize.label,
labelColor: Colors.black,
unselectedLabelColor: Colors.grey.withOpacity(0.6),
controller: _tabController,
tabs: [
Tab(
child: Padding(
padding: const EdgeInsets.only(bottom: 10),
child: Text(
"HOME",
style: kh5,
),
),
),
Tab(
child: Padding(
padding: const EdgeInsets.only(bottom: 10),
child: Text(
"ABOUT US",
style: kh5,
),
),
),
Tab(
child: Padding(
padding: const EdgeInsets.only(bottom: 10),
child: Text(
"CONTACT US",
style: kh5,
),
),
),
],
),
GestureDetector(
onTap: () {
launch(
"https://pub.dev/packages/url_launcher#-installing-tab-");
},
child: Container(
margin: EdgeInsets.only(left: 15, bottom: 12),
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
color: Colors.deepPurpleAccent,
),
child: Text(
"DOWNLOAD APP",
style: kh5.copyWith(color: Colors.white),
),
),
),
],
),
),
Container(
width: double.maxFinite,
height: double.maxFinite,
child: TabBarView(
controller: _tabController,
children: [
Home(),
AboutUs(),
ContactUs(),
],
),
)
],
),
);
}
}

Related

How can I add the contact details in the prototype to my code?

The page is loading fine but, how can I add the contact details in the center of prototype to the center of the Appbar and the bottom navigation bar? Can anyone tell me how can I add that..
Updated the full code as requested in the comments.
class _MyHomePageState extends State<MyHomePage>
with SingleTickerProviderStateMixin {
String title = 'Tabar / BottomNavigationBar';
TabController _tabController;
#override
void initState() {
super.initState();
_tabController = TabController(length: 5, vsync: this);
}
#override
void dispose() {
super.dispose();
_tabController.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
bottom: PreferredSize(child: Container(),
preferredSize: Size.fromHeight(45.0)
),
backgroundColor: Colors.white,
title: Image.asset('images/logo1.jpg',
height: 50.0,
width: 70.0),
),
body: TabBarView(
controller: _tabController,
physics: NeverScrollableScrollPhysics(),
children: [
TopTabBar(),
Center(
child: Text('Accounts',
style: TextStyle(fontSize: 25.0)
),
),
Center(
child: Text('Service',
style: TextStyle(fontSize: 25.0)
),
),
Center(
child: Text('Products',
style: TextStyle(fontSize: 25.0)
),
),
Center(
child: Text('Log Out',
style: TextStyle(fontSize: 25.0)
),
),
],
),
bottomNavigationBar: Container(
color: Colors.amber,
child: TabBar(
controller: _tabController,
unselectedLabelColor: Colors.black,
indicator: UnderlineTabIndicator(
borderSide: BorderSide(width: 0.0),
),
labelColor: Colors.white,
labelStyle: TextStyle(fontSize: 12.0),
tabs: [
Tab(
icon: Icon(Icons.home),
text: 'Home',
),
Tab(
icon: Icon(Icons.account_balance),
text: 'Accounts',
),
Tab(
icon: Icon(Icons.home_repair_service),
text: 'Service',
),
Tab(
icon: Icon(Icons.account_circle_rounded),
text: 'Products',
),
Tab(
icon: Icon(Icons.logout),
text: 'Log Out',
),
],
),
),
);
}
}
class TopTabBar extends StatefulWidget {
TopTabBar({Key key}) : super(key: key);
#override
_TopTabBarState createState() => _TopTabBarState();
}
class _TopTabBarState extends State<TopTabBar>
with SingleTickerProviderStateMixin {
TabController _tabController;
#override
void initState() {
super.initState();
_tabController = TabController(length: 3, vsync: this);
}
#override
void dispose(){
super.dispose();
_tabController.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: PreferredSize(
preferredSize: Size.fromHeight(kToolbarHeight),
child: Container(
color: Colors.amber,
child: TabBar(
controller: _tabController,
indicator: UnderlineTabIndicator(
borderSide: BorderSide(width: 0.0),
),
indicatorColor: Colors.white,
unselectedLabelColor: Colors.black,
labelColor: Colors.white,
indicatorWeight: 5.0,
tabs: [
Tab(
text: 'Contact Us'
),
Tab(
text: 'Nearest Branch'
),
Tab(
text: 'Nearest ATM'
),
],
),
),
),
);
}
}
This is my prototype and the interface generated by the code
body: Column(
children: [
TabBarView(
controller: _tabController,
physics: NeverScrollableScrollPhysics(),
children: [
TopTabBar(),
Center(
child: Text('Accounts',
style: TextStyle(fontSize: 25.0)
),
),
Center(
child: Text('Service',
style: TextStyle(fontSize: 25.0)
),
),
Center(
child: Text('Products',
style: TextStyle(fontSize: 25.0)
),
),
Center(
child: Text('Log Out',
style: TextStyle(fontSize: 25.0)
),
),
],
),
Expanded(
child: Center(ContactDetailsWidget())
),
],
)
Add the above code on the body, Here the remaining space will use by your custom widget ContactDetailsWidget where you can display anything

Error: A FocusNode was used after being disposed. Once you have called dispose() on a FocusNode, it can no longer be used

I have created a simple web page where I have two buttons, one to add a donor and the other to list the donors. When each of the button is clicked, I want the respective pages to open.
I click on the 'Add Donor' button, fill the form and click on 'Submit'. Then I click on 'List Donors' and return back to 'Add Donor', and on clicking on the 'Name' field', I get the below error when running this on Chrome Browser.
Error: A FocusNode was used after being disposed.
Once you have called dispose() on a FocusNode, it can no longer be used.
at Object.throw_ [as throw] (http://localhost:62365/dart_sdk.js:5334:11)
at http://localhost:62365/packages/flutter/src/foundation/change_notifier.dart.lib.js:83:21
at focus_manager.FocusNode.new.[_debugAssertNotDisposed] (http://localhost:62365/packages/flutter/src/foundation/change_notifier.dart.lib.js:86:25)
at focus_manager.FocusNode.new.notifyListeners (http://localhost:62365/packages/flutter/src/foundation/change_notifier.dart.lib.js:113:51)
at focus_manager.FocusNode.new.[_notify] (http://localhost:62365/packages/flutter/src/widgets/widget_span.dart.lib.js:47534:12)
at focus_manager.FocusManager.new.[_applyFocusChange] (http://localhost:62365/packages/flutter/src/widgets/widget_span.dart.lib.js:48310:26)
at Object._microtaskLoop (http://localhost:62365/dart_sdk.js:39176:13)
at _startMicrotaskLoop (http://localhost:62365/dart_sdk.js:39182:13)
at http://localhost:62365/dart_sdk.js:34689:9
This is my code snippet
import 'package:flutter/material.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) =>
BloodDonationPage(),
),
);
},
child: Scaffold(
body: Center(
child: Container(
width: 200,
height: 100,
child: Card(
elevation: 20,
color: Colors.pink[100],
shape: RoundedRectangleBorder(
side:
BorderSide(color: Colors.white70, width: 1),
borderRadius: BorderRadius.circular(10),
),
margin: EdgeInsets.all(8.0),
child: Center(
child: Text(
"Blood Donation",
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold),
)),
),
),
),
),
);
}
}
class BloodDonationPage extends StatefulWidget {
#override
_BloodDonationPageState createState() => _BloodDonationPageState();
}
class _BloodDonationPageState extends State<BloodDonationPage> {
bool _addButton = false;
bool _listButton = false;
#override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
height: 60,
//width: 600,
child: Card(
color: Colors.pink[50],
shadowColor: Colors.pink,
elevation: 20,
child: ListView(
scrollDirection: Axis.horizontal,
children: [
GestureDetector(
onTap: () {
setState(() {
_addButton = true;
_listButton = false;
});
},
child: Padding(
padding: const EdgeInsets.only(left: 60, right: 30.0),
child: Card(
elevation: 20,
color: Colors.pink[100],
shape: RoundedRectangleBorder(
side:
BorderSide(color: Colors.white70, width: 1),
borderRadius: BorderRadius.circular(10),
),
margin: EdgeInsets.all(8.0),
child: Container(
padding: EdgeInsets.symmetric(horizontal: 10),
child: Center(
child: Text(
"Add Donor",
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold),
)),
),
),
),
),
GestureDetector(
onTap: () {
setState(() {
_addButton = false;
_listButton = true;
});
},
child: Padding(
padding: const EdgeInsets.only(left: 60, right: 30.0),
child: Card(
elevation: 20,
color: Colors.pink[100],
shape: RoundedRectangleBorder(
side: BorderSide(color: Colors.white70, width: 1),
borderRadius: BorderRadius.circular(10),
),
margin: EdgeInsets.all(8.0),
child: Container(
padding: EdgeInsets.symmetric(horizontal: 10),
child: Center(
child: Text(
"List Donors",
style: TextStyle(
fontSize: 18, fontWeight: FontWeight.bold),
)),
),
),
),
),
],
),
),
),
_addButton ? Flexible(child: BloodDonorDetailPage()) : SizedBox.shrink(),
_listButton ? Flexible(child: ListBloodDonorPage()) : SizedBox.shrink(),
],
);
}
}
class BloodDonorDetailPage extends StatefulWidget {
#override
_BloodDonorDetailPageState createState() => _BloodDonorDetailPageState();
}
class _BloodDonorDetailPageState extends State<BloodDonorDetailPage> {
final _formKey = GlobalKey<FormBuilderState>();
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(30.0),
child: FormBuilder(
autovalidateMode: AutovalidateMode.disabled,
key: _formKey,
child: Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
FormBuilderTextField(
autofocus: true,
name: 'name',
validator: FormBuilderValidators.compose([
FormBuilderValidators.required(context),
FormBuilderValidators.maxLength(context, 50),
]),
decoration: InputDecoration(labelText: 'Name'),
),
FormBuilderTextField(
name: 'phone',
validator: FormBuilderValidators.compose([
FormBuilderValidators.required(context),
FormBuilderValidators.minLength(context, 10),
FormBuilderValidators.maxLength(context, 10),
FormBuilderValidators.numeric(context,
errorText: 'Mobile No should be 10 digits')
]),
keyboardType: TextInputType.number,
decoration: InputDecoration(labelText: 'Phone'),
),
FormBuilderChoiceChip(
name: 'gender',
elevation: 10,
selectedColor: Colors.white,
disabledColor: Colors.black12,
alignment: WrapAlignment.spaceAround,
options: ['M', 'F']
.map((value) => FormBuilderFieldOption(
value: value,
child: (value == 'M')
? Text('Male')
: Text('Female'),
))
.toList(),
decoration: InputDecoration(labelText: 'Gender'),
),
FormBuilderChoiceChip(
name: 'bloodGroup',
elevation: 10,
selectedColor: Colors.white,
disabledColor: Colors.black12,
alignment: WrapAlignment.spaceAround,
options: ['A+','O+']
.map((value) => FormBuilderFieldOption(value: value))
.toList(),
decoration: InputDecoration(labelText: 'Blood Group'),
),
Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
MaterialButton(
color: Theme.of(context).accentColor,
child: Text('Submit',
style: TextStyle(color: Colors.white),
),
onPressed: () async {
//print(_formKey.currentState.mounted);
Map<String, dynamic> _donorMap;
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
//print(_formKey.currentState.value);
_donorMap = {
..._formKey.currentState.value,
'createdDate': DateTime.now()
};
print(_donorMap);
/*await BloodDonorsController()
.saveBloodDonors(widget.mode!, _donorMap);*/
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Add Donor Successful'),
),
);
_formKey.currentState.reset();
//FocusScope.of(context).requestFocus(focusNode);
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Validation Failed'),
),
);
}
},
),
SizedBox(width: 20),
MaterialButton(
color: Theme.of(context).accentColor,
child: Text(
"Reset",
style: TextStyle(color: Colors.white),
),
onPressed: () {
_formKey.currentState.reset();
},
),
],
),
)
],
),
),
),
);
}
}
class ListBloodDonorPage extends StatefulWidget {
#override
_ListBloodDonorPageState createState() => _ListBloodDonorPageState();
}
class _ListBloodDonorPageState extends State<ListBloodDonorPage> {
#override
Widget build(BuildContext context) {
return Container(child: Text('Display List of Donors'),);
}
}
What is the problem here?
Can anyone please help me?
I was able to finally solve this by converting the stateful widgets to methods and adding the Visibility widget to display the widget with the state maintained as shown below.
import 'package:flutter/material.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) =>
BloodDonationPage(),
),
);
},
child: Scaffold(
body: Center(
child: Container(
width: 200,
height: 100,
child: Card(
elevation: 20,
color: Colors.pink[100],
shape: RoundedRectangleBorder(
side:
BorderSide(color: Colors.white70, width: 1),
borderRadius: BorderRadius.circular(10),
),
margin: EdgeInsets.all(8.0),
child: Center(
child: Text(
"Blood Donation",
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold),
)),
),
),
),
),
);
}
}
class BloodDonationPage extends StatefulWidget {
#override
_BloodDonationPageState createState() => _BloodDonationPageState();
}
class _BloodDonationPageState extends State<BloodDonationPage> {
bool _addButton = false;
bool _listButton = false;
final _formKey = GlobalKey<FormBuilderState>();
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
height: 60,
//width: 600,
child: Card(
color: Colors.pink[50],
shadowColor: Colors.pink,
elevation: 20,
child: ListView(
scrollDirection: Axis.horizontal,
children: [
GestureDetector(
onTap: () {
setState(() {
_addButton = true;
_listButton = false;
});
},
child: Padding(
padding: const EdgeInsets.only(left: 60, right: 30.0),
child: Card(
elevation: 20,
color: Colors.pink[100],
shape: RoundedRectangleBorder(
side:
BorderSide(color: Colors.white70, width: 1),
borderRadius: BorderRadius.circular(10),
),
margin: EdgeInsets.all(8.0),
child: Container(
padding: EdgeInsets.symmetric(horizontal: 10),
child: Center(
child: Text(
"Add Donor",
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold),
)),
),
),
),
),
GestureDetector(
onTap: () {
setState(() {
_addButton = false;
_listButton = true;
});
},
child: Padding(
padding: const EdgeInsets.only(left: 60, right: 30.0),
child: Card(
elevation: 20,
color: Colors.pink[100],
shape: RoundedRectangleBorder(
side: BorderSide(color: Colors.white70, width: 1),
borderRadius: BorderRadius.circular(10),
),
margin: EdgeInsets.all(8.0),
child: Container(
padding: EdgeInsets.symmetric(horizontal: 10),
child: Center(
child: Text(
"List Donors",
style: TextStyle(
fontSize: 18, fontWeight: FontWeight.bold),
)),
),
),
),
),
],
),
),
),
Visibility(visible: _addButton, maintainState: true,child: buildAdd()),
Visibility(visible: _listButton ,child: buildList()),
],
),
);
}
Widget buildList() => Container(child: Text('Display List of Donors'),);
Widget buildAdd() => Padding(
padding: const EdgeInsets.all(30.0),
child: Column( children: [ FormBuilder(
autovalidateMode: AutovalidateMode.disabled,
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
FormBuilderTextField(
autofocus: true,
name: 'name',
validator: FormBuilderValidators.compose([
FormBuilderValidators.required(context),
FormBuilderValidators.maxLength(context, 50),
]),
decoration: InputDecoration(labelText: 'Name'),
),
FormBuilderTextField(
name: 'phone',
validator: FormBuilderValidators.compose([
FormBuilderValidators.required(context),
FormBuilderValidators.minLength(context, 10),
FormBuilderValidators.maxLength(context, 10),
FormBuilderValidators.numeric(context,
errorText: 'Mobile No should be 10 digits')
]),
keyboardType: TextInputType.number,
decoration: InputDecoration(labelText: 'Phone'),
),
FormBuilderChoiceChip(
name: 'gender',
elevation: 10,
selectedColor: Colors.white,
disabledColor: Colors.black12,
alignment: WrapAlignment.spaceAround,
options: ['M', 'F']
.map((value) => FormBuilderFieldOption(
value: value,
child: (value == 'M')
? Text('Male')
: Text('Female'),
))
.toList(),
decoration: InputDecoration(labelText: 'Gender'),
),
FormBuilderChoiceChip(
name: 'bloodGroup',
elevation: 10,
selectedColor: Colors.white,
disabledColor: Colors.black12,
alignment: WrapAlignment.spaceAround,
options: ['A+','O+']
.map((value) => FormBuilderFieldOption(value: value))
.toList(),
decoration: InputDecoration(labelText: 'Blood Group'),
),
],),),
SizedBox(height: 100,),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
MaterialButton(
color: Theme.of(context).accentColor,
child: Text('Submit',
style: TextStyle(color: Colors.white),
),
onPressed: () async {
//print(_formKey.currentState.mounted);
Map<String, dynamic> _donorMap;
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
//print(_formKey.currentState.value);
_donorMap = {
..._formKey.currentState.value,
'createdDate': DateTime.now()
};
print(_donorMap);
/*await BloodDonorsController()
.saveBloodDonors(widget.mode!, _donorMap);*/
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Add Donor Successful'),
),
);
_formKey.currentState.reset();
//FocusScope.of(context).requestFocus(focusNode);
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Validation Failed'),
),
);
}
},
),
SizedBox(width: 20),
MaterialButton(
color: Theme.of(context).accentColor,
child: Text(
"Reset",
style: TextStyle(color: Colors.white),
),
onPressed: () {
_formKey.currentState.reset();
},
),
],
)
],
),
);
}

TabBarView inside Sliver with StickyHeader

I have made this layout so far using CustomScrollView and Sticky Header
https://imgur.com/a/Xo4AfAM
What I want to achieve is that the content below the tabs should not scroll unless there is extra content available. Also, after scrolling, the content should not go behind the sticky header.
My Code so far.
Scaffold(
backgroundColor: Colors.white,
extendBodyBehindAppBar: true,
appBar: AppBar(
toolbarHeight: getHeight() * (1 / 11),
),
body: Padding(
padding: getPaddings(),
child: DefaultTabController(
length: 3,
child: CustomScrollView(
slivers: [
SliverToBoxAdapter(
child: Container(
height: getHeight() * (3 / 11),
color: Colors.blue,
),
),
SliverStickyHeader(
header: Column(
children: [
Container(
height: getHeight() * (1 / 11),
width: double.infinity,
color: kPrimaryColor,
child: Center(
child: Text(
"TEXT",
style: TextStyle(
fontSize: 32,
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
),
),
Container(
height: getHeight() * (1 / 11),
color: kPrimaryColor,
child: TabBar(
tabs: [
Tab(
child: Text(
'TITLE1',
style: TextStyle(color: Colors.black),
),
),
Tab(
child: Text(
'TITLE2',
style: TextStyle(color: Colors.black),
),
),
Tab(
child: Text(
'TITLE3',
style: TextStyle(color: Colors.black),
),
),
],
),
),
],
),
sliver: SliverFillRemaining(
child: TabBarView(
children: [
Padding(
padding: EdgeInsets.symmetric(
horizontal: getProportionateScreenWidth(50),
vertical: getProportionateScreenHeight(20)),
child: Column(
children: [
RoundedPicture(),
FittedBox(
child: Text("Hello World",
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black,
fontSize: 40)),
),
SizedBox(
height: getProportionateScreenHeight(20),
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
RichText(
text: TextSpan(
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black,
fontSize: 20),
text: 'Info1: ',
children: [
TextSpan(
text: "123",
style: TextStyle(
color: kSecondaryColor,
),
),
]),
),
SizedBox(
height: getProportionateScreenHeight(20),
),
RichText(
text: TextSpan(
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black,
fontSize: 20),
text: 'Info2: ',
children: [
TextSpan(
text: "abcd",
style: TextStyle(
color: kSecondaryColor,
),
),
]),
),
SizedBox(
height: getProportionateScreenHeight(20),
),
RichText(
text: TextSpan(
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black,
fontSize: 20),
text: 'Info3: ',
children: [
TextSpan(
text: "xyz",
style: TextStyle(
color: kSecondaryColor,
),
),
]),
),
],
),
],
),
),
Center(
child: Text("TITLE2"),
),
Center(
child: Text("TITLE3"),
),
],
),
),
),
],
),
),
),
To achieve the required layout, I tried using TabBarView inside different slivers i.e SliverList and SliverToBoxAdapter but they all resulted in an error because TabBarView doesn't have a predefined height.
Here is my implementation.
Because there are no method related to size, I just set a value myself.
Stack
DefaultTabController
NestedScrollView
SliverAppBar
SliverPersistentHeader
SliverPersistentHeader
TabBarView
Container // For back button
import 'package:flutter/material.dart';
import 'dart:math' as math;
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage>
with SingleTickerProviderStateMixin {
TabController _tabController;
#override
void initState() {
super.initState();
_tabController = TabController(initialIndex: 0, length: 3, vsync: this);
}
double getHeight() {
return 800;
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
extendBodyBehindAppBar: true,
body: SafeArea(
child: Stack(
children: [
DefaultTabController(
length: 3,
child: NestedScrollView(
headerSliverBuilder: (context, value) {
return [
SliverAppBar(
expandedHeight: 200.0,
flexibleSpace: FlexibleSpaceBar(),
),
SliverPersistentHeader(
pinned: true,
delegate: _SliverAppBarDelegate(
minHeight: 90,
maxHeight: 90,
child: Container(
height: getHeight() * (1 / 11),
width: double.infinity,
color: Colors.green[200],
child: Center(
child: Text(
"TEXT",
style: TextStyle(
fontSize: 32,
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
),
),
),
),
SliverPersistentHeader(
pinned: true,
delegate: _SliverAppBarDelegate(
minHeight: 90,
maxHeight: 90,
child: Container(
color: Colors.green[200],
child: TabBar(
controller: _tabController,
tabs: [
Tab(
child: Text(
'TITLE1',
style: TextStyle(
color: Colors.black,
),
),
),
Tab(
child: Text(
'TITLE2',
style: TextStyle(color: Colors.black),
),
),
Tab(
child: Text(
'TITLE3',
style: TextStyle(color: Colors.black),
),
),
],
),
),
),
),
];
},
body: TabBarView(
controller: _tabController,
children: [
SingleChildScrollView(
child: Container(
padding: EdgeInsets.only(bottom: 600),
child: Column(
children: [
// RoundedPicture(),
Icon(
Icons.favorite,
color: Colors.pink,
size: 150.0,
semanticLabel:
'Text to announce in accessibility modes',
),
FittedBox(
child: Text("Hello World",
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black,
fontSize: 40)),
),
SizedBox(
height: 20,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
RichText(
text: TextSpan(
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black,
fontSize: 20),
text: 'Info1: ',
children: [
TextSpan(
text: "123",
style: TextStyle(),
),
]),
),
SizedBox(
height: 20,
),
RichText(
text: TextSpan(
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black,
fontSize: 20),
text: 'Info2: ',
children: [
TextSpan(
text: "abcd",
style: TextStyle(),
),
]),
),
SizedBox(
height: 20,
),
RichText(
text: TextSpan(
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black,
fontSize: 20),
text: 'Info3: ',
children: [
TextSpan(
text: "xyz",
style: TextStyle(),
),
]),
),
],
),
],
),
),
),
SingleChildScrollView(
child: Container(
padding: EdgeInsets.only(bottom: 600),
child: Column(
children: [
Container(
padding: EdgeInsets.only(bottom: 600),
child: Center(
child: Text("TITLE2"),
),
),
],
),
),
),
SingleChildScrollView(
child: Container(
padding: EdgeInsets.only(bottom: 600),
child: Column(
children: [
Container(
padding: EdgeInsets.only(bottom: 600),
child: Center(
child: Text("TITLE3"),
),
),
],
),
),
),
],
),
),
),
Container(
height: 90,
padding: EdgeInsets.symmetric(horizontal: 15),
child: InkWell(
onTap: () {},
child: Icon(Icons.arrow_back),
),
),
],
),
),
);
}
}
class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
_SliverAppBarDelegate({
#required this.minHeight,
#required this.maxHeight,
#required this.child,
});
final double minHeight;
final double maxHeight;
final Widget child;
#override
double get minExtent => minHeight;
#override
double get maxExtent => math.max(maxHeight, minHeight);
#override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
return SizedBox.expand(child: child);
}
#override
bool shouldRebuild(_SliverAppBarDelegate oldDelegate) {
return maxHeight != oldDelegate.maxHeight ||
minHeight != oldDelegate.minHeight ||
child != oldDelegate.child;
}
}
After finding no possible solution, I decided to implement my own tab bar view instead of using the default one. The solution isn't as fancy since the transition of tabs is done by changing the current page number and rebuilding the widget but solves the issue. I used a gesture detector for allowing users to swipe the page.
GestureDetector(
onHorizontalDragEnd: (dragDetails) {
if (dragDetails.primaryVelocity != 0) {
final int val = dragDetails.primaryVelocity.sign.toInt();
if (currentPage - val >= 0 &&
currentPage - val < tabController.length)
tabController.animateTo(currentPage - val);
}
},
child: CustomScrollView(
shrinkWrap: true,
controller: scrollController,
slivers: [
SliverToBoxAdapter(
child: LogoContainer(),
),
SliverStickyHeader(
header: Column(
children: [
NameContainer(text: 'TEXT'),
Container(
height: 60,
color: kSecondaryColor,
child: TabBar(
controller: tabController,
tabs: [
Tab(
child: Text(
'TITLE1',
style: TextStyle(color: Colors.black),
),
),
Tab(
child: Text(
'TITLE2',
style: TextStyle(color: Colors.black),
),
),
Tab(
child: Text(
'TITLE3',
style: TextStyle(color: Colors.black),
),
),
],
),
),
],
),
sliver: SliverToBoxAdapter(
child: ConstrainedBox(
constraints:
BoxConstraints(minHeight: getHeight() * (6 / 11)),
child: [
Column(
children: [
RoundedPicture(),
FittedBox(
child: Text(
'HELLO WORLD',
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black,
fontSize: 40),
),
),
SizedBox(
height: getProportionateScreenHeight(20),
),
Column(
children: [
ProfileInfoText(
title: 'INFO1',
text: 'abcd',
),
SizedBox(
height: getProportionateScreenHeight(20),
),
ProfileInfoText(
title: 'INFO2',
text: '123',
),
SizedBox(
height: getProportionateScreenHeight(20),
),
ProfileInfoText(
title: 'INFO3',
text: 'xyz',
),
],
),
],
),
Center(
child: Text("TITLE2"),
),
Center(
child: Text("TITLE3"),
),
].elementAt(currentPage),
),
),
),
],
),
),
I also used scroll controller to animate the list back to top when changing the tabs to give it a smooth look.
#override
void initState() {
super.initState();
tabController = TabController(length: 3, vsync: this)
..addListener(() async {
await scrollController.animateTo(
0,
duration: Duration(seconds: 1),
curve: Curves.ease,
);
setState(() {
currentPage = tabController.index;
});
});
}

Loading different PDF document using ListView Builder in Flutter

I am a newbie in Flutter and in programming as well.
I have created a ListView with several Cards inside each card points to separate PDF documents which are loaded using the package 'advance_pdf_viewer'. I have done all this hardcoded. But I would like to generate the Cards and the pdf document dynamically. How can I do that?
Here are my existing Codes:
Main.dart file:
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'c9Bban.dart';
import 'c9Bbanbakoron.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'HSC Textbooks',
theme: ThemeData(
primarySwatch: Colors.cyan,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
'১ম - ১০ম শ্রেণী পাঠ্যবই',
style: TextStyle(
//fontSize: 14,
fontFamily: 'Baloo Da',
),
),
centerTitle: true,
),
body: ListView(children: [
Card(
child: Row(children: <Widget>[
Expanded(
flex: 8, // 20%
child: Container(
child: ListTile(
leading: ConstrainedBox(
constraints: BoxConstraints(
maxWidth: 44,
maxHeight: 44,
),
child: Image.asset('images/bangla bakaron.jpg',
fit: BoxFit.cover),
),
title: Text(
'বাংলা ব্যাকরণ',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
fontFamily: 'Baloo da',
),
),
subtitle: Text(
'জাতীয় শিক্ষাক্রম ও পাঠ্যপুস্তক বোর্ড',
style: TextStyle(
fontSize: 12,
fontFamily: 'Baloo da',
),
),
),
),
),
Expanded(
flex: 4, // 20%
child: GestureDetector(
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => C9Bbanbakoron()));
},
child: Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.grey[300])),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Icon(FontAwesomeIcons.book, color: Colors.green),
SizedBox(height: 5),
Text('বাংলা ও ইংরেজি ভার্সন',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 14,
)),
],
),
),
),
),
]),
),
Card(
child: Row(children: <Widget>[
Expanded(
flex: 8, // 20%
child: Container(
child: ListTile(
leading: ConstrainedBox(
constraints: BoxConstraints(
maxWidth: 44,
maxHeight: 44,
),
child: Image.asset('images/BGS.jpg', fit: BoxFit.cover),
),
title: Text(
'বাংলাদেশ ও বিশ্বপরিচয়',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
fontFamily: 'Baloo da',
),
),
subtitle: Text(
'জাতীয় শিক্ষাক্রম ও পাঠ্যপুস্তক বোর্ড',
style: TextStyle(
fontSize: 12,
fontFamily: 'Baloo da',
),
),
),
),
),
Expanded(
flex: 2, // 20%
child: GestureDetector(
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => C9Bbgs()));
},
child: Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.grey[300])
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Icon(FontAwesomeIcons.book, color: Colors.green),
SizedBox(height: 5),
Text('বাংলা ভার্সন',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 14,
)
),
],
),
),
),
),
Expanded(
flex: 2, // 20%
child: GestureDetector(
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => C9Ebgs()));
},
child: Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.grey[300])
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Icon(FontAwesomeIcons.book, color: Colors.green),
SizedBox(height: 5),
Text('ইংরেজি ভার্সন',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 14,
)
),
],
),
),
),
),
]),
),
]),
);
}
}
c9Bban.dart file (one of the separate files for loading separate PDF documents. Rest of the files are exactly the same except the PDF URL is different):
import 'package:flutter/material.dart';
import 'package:advance_pdf_viewer/advance_pdf_viewer.dart';
class C9Bban extends StatefulWidget {
#override
_MyC9Bban createState() => _MyC9Bban();
}
class _MyC9Bban extends State<C9Bban> {
bool _isLoading = true;
PDFDocument document;
#override
void initState() {
super.initState();
loadDocument();
}
loadDocument() async {
document = await PDFDocument.fromURL('https://storage.googleapis.com/school_books/Class9/ban/Bangla%20Sahitto.pdf');
setState(() => _isLoading = false);
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
toolbarHeight: 20,
),
body: Center(
child: _isLoading
? Center(child: CircularProgressIndicator())
: PDFViewer(
document: document,
zoomSteps: 1,
),
),
bottomNavigationBar: BottomAppBar(
child: Container(
height: 85.0,
),
),
),
);
}
}
So far I was able to create this which works for creating the ListView Cards dynamically.
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:advance_pdf_viewer/advance_pdf_viewer.dart';
import 'c9Bban.dart';
import 'c9Bbansohopath.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'HSC Textbooks',
theme: ThemeData(
primarySwatch: Colors.cyan,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
List booklist = [
Books(
image: 'Bangla.jpg',
bookname: 'Bangla',
banbookname: 'C9Bban',
),
Books(
image: 'bangla shapath.jpg',
bookname: 'Bangla Sahapath',
banbookname: 'C9Bbansohopath',
),
];
void updateBook(index) {
Navigator.push(context, MaterialPageRoute(builder: (context) => booklist[index].banbookname));
}
return Scaffold(
appBar: AppBar(
title: Text('Book App'),
centerTitle: true,
),
body: ListView.builder(
itemCount: booklist.length,
itemBuilder: (context, index) {
return Card(
child: Row(children: <Widget>[
Expanded(
flex: 8, // 20%
child: Container(
child: ListTile(
leading: ConstrainedBox(
constraints: BoxConstraints(
maxWidth: 44,
maxHeight: 44,
),
child:
Image.asset('images/islam.jpg', fit: BoxFit.cover),
),
title: Text(
booklist[index].bookname,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
fontFamily: 'Baloo da',
),
),
subtitle: Text(
'জাতীয় শিক্ষাক্রম ও পাঠ্যপুস্তক বোর্ড',
style: TextStyle(
fontSize: 12,
fontFamily: 'Baloo da',
),
),
),
),
),
Expanded(
flex: 2, // 20%
child: GestureDetector(
onTap: () {
updateBook(index);
},
child: Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.grey[300])),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Icon(FontAwesomeIcons.book, color: Colors.green),
SizedBox(height: 5),
Text('বাংলা ভার্সন',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 14,
)),
],
),
),
),
),
Expanded(
flex: 2, // 20%
child: GestureDetector(
onTap: () {
updateBook(index);
},
child: Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.grey[300])),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Icon(FontAwesomeIcons.book, color: Colors.green),
SizedBox(height: 5),
Text('ইংরেজি ভার্সন',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 14,
)),
],
),
),
),
),
]),
);
}),
);
}
}
class Books {
String image;
String bookname;
String banbookname;
String engbook;
Books({this.image, this.bookname, this.banbookname});
}

How to create a vertical scrolling menu effect in Flutter

this question is an improvement for this question. In this case, I would like to reproduce the vertical menu the you can see on the left side of this we base. If you click the link relative to the example on the left you see a number of menu. For instance, clicking on Base you are going to see a vertical menu appearing and disappearing. I would like to know how to reproduce it as well. An example code would be really appreciated.
Thanks all
You can achieve this by simply using a StatefulWidget & managing the hide/show functionality using a boolean value.
Here is the updated code:
import 'package:flutter/material.dart';
final Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: MyWidget(),
),
),
);
}
}
class MyWidget extends StatefulWidget {
#override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget>
with SingleTickerProviderStateMixin {
final colors = <Color>[Colors.indigo, Colors.blue, Colors.orange, Colors.red];
double _size = 250.0;
bool _large = true;
void _updateSize() {
setState(() {
_size = _large ? 250.0 : 0.0;
_large = !_large;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Row(
children: [
AnimatedSize(
curve: Curves.easeIn,
vsync: this,
duration: Duration(seconds: 1),
child: LeftDrawer(size: _size)),
Expanded(
flex: 4,
child: Container(
child: Column(
children: [
Container(
color: Colors.white,
padding: const EdgeInsets.all(8),
child: Row(
children: [
IconButton(
icon: Icon(Icons.menu, color: Colors.black87),
onPressed: () {
_updateSize();
},
),
FlatButton(
child: Text(
'Dashboard',
style: const TextStyle(color: Colors.black87),
),
onPressed: () {},
),
FlatButton(
child: Text(
'User',
style: const TextStyle(color: Colors.black87),
),
onPressed: () {},
),
FlatButton(
child: Text(
'Settings',
style: const TextStyle(color: Colors.black87),
),
onPressed: () {},
),
const Spacer(),
IconButton(
icon: Icon(Icons.brightness_3, color: Colors.black87),
onPressed: () {},
),
IconButton(
icon: Icon(Icons.notification_important,
color: Colors.black87),
onPressed: () {},
),
CircleAvatar(),
],
),
),
Container(
height: 1,
color: Colors.black12,
),
Card(
margin: EdgeInsets.zero,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(0),
),
child: Container(
color: Colors.white,
padding: const EdgeInsets.all(20),
child: Row(
children: [
Text(
'Home / Admin / Dashboard',
style: const TextStyle(color: Colors.black),
),
],
),
),
),
Expanded(
child: ListView(
children: [
Row(
children: [
_container(0),
_container(1),
_container(2),
_container(3),
],
),
Container(
height: 400,
color: Color(0xFFE7E7E7),
padding: const EdgeInsets.all(16),
child: Card(
color: Colors.white,
child: Container(
padding: const EdgeInsets.all(16),
child: Text(
'Traffic',
style: const TextStyle(color: Colors.black87),
),
),
),
),
],
),
),
],
),
),
),
],
),
);
}
Widget _container(int index) {
return Expanded(
child: Container(
padding: const EdgeInsets.all(20),
color: Color(0xFFE7E7E7),
child: Card(
color: Color(0xFFE7E7E7),
child: Container(
color: colors[index],
width: 250,
height: 140,
padding: const EdgeInsets.all(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Expanded(
child: Text(
'9.823',
style: TextStyle(fontSize: 24),
)),
Icon(Icons.more_vert),
],
),
Text('Members online')
],
),
),
),
),
);
}
}
class LeftDrawer extends StatefulWidget {
LeftDrawer({
Key key,
this.size,
}) : super(key: key);
final double size;
#override
_LeftDrawerState createState() => _LeftDrawerState();
}
class _LeftDrawerState extends State<LeftDrawer> {
bool dropdownVisible = false;
#override
Widget build(BuildContext context) {
return Expanded(
flex: 1,
child: Container(
width: widget.size,
color: const Color(0xFF2C3C56),
child: ListView(
children: [
Container(
alignment: Alignment.center,
padding: const EdgeInsets.all(16),
color: Color(0xFF223047),
child: Text('CORE UI'),
),
_tile('Dashboard'),
Container(
padding: const EdgeInsets.only(left: 10),
margin: const EdgeInsets.only(top: 30),
child: Text('THEME',
style: TextStyle(
color: Colors.white54,
))),
_tile('Colors'),
_tile('Typography'),
_tileDropdown('Base'),
_tile('Buttons'),
],
),
),
);
}
Widget _tile(String label) {
return ListTile(
title: Text(label),
onTap: () {},
);
}
Widget _option(String label) {
return ListTile(
tileColor: Color(0xFF223047),
contentPadding: const EdgeInsets.only(left: 40),
title: Text(label),
onTap: () {},
);
}
Widget _tileDropdown(String label) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
ListTile(
title: Text(label),
onTap: () {
setState(() {
dropdownVisible = !dropdownVisible;
});
},
trailing: dropdownVisible
? Icon(Icons.arrow_drop_up)
: Icon(Icons.chevron_left),
),
Visibility(
visible: dropdownVisible,
child: _option('Breadcrumbs'),
),
Visibility(
visible: dropdownVisible,
child: _option('Cloud'),
),
Visibility(
visible: dropdownVisible,
child: _option('Carousel'),
),
Visibility(
visible: dropdownVisible,
child: _option('Collapse'),
),
],
);
}
}