How to access ThemeData from imported widgets - flutter

I can not use the ThemeData from the imported custom Widgets that I have imported from other files, I dont know if the BuildContext is changing or what. To all the widgets that are used in the main.dart file they can easily use Theme.of(context).colorScheme.primary but from imported widgets this does not work.
main.dart
import 'package:flutter/material.dart';
import 'widgets/expenses_list.dart';
import 'models/expenses_model.dart';
import 'widgets/new_expense.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData().copyWith(
colorScheme: ThemeData().colorScheme.copyWith(primary: Colors.red),
),
home: MyAppPage(),
);
}
}
class MyAppPage extends StatefulWidget {
#override
_MyAppPageState createState() => _MyAppPageState();
}
class _MyAppPageState extends State<MyAppPage> {
final List<ExpensesModel> _expensesObjectList = [
ExpensesModel(
id: DateTime.now().toString(),
name: "Shoes",
amount: 1200,
date: DateTime.now(),
),
ExpensesModel(
id: DateTime.now().toString(),
name: "Gun",
amount: 120000,
date: DateTime.now(),
),
];
void _addExpense(String exTitle, double exAmount) {
final _addExpenseObject = ExpensesModel(
id: DateTime.now().toString(),
name: exTitle,
amount: exAmount,
date: DateTime.now(),
);
setState(() {
_expensesObjectList.add(_addExpenseObject);
});
}
void _startAddNewExpense(BuildContext context) {
showModalBottomSheet(
context: context,
builder: (bcontext) {
return NewExpense(_addExpense);
});
}
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.primary,
// HERE IT DOES WORK
title: Text(
"Expense App",
// style: Theme.of(context).textTheme.title,
),
actions: [
IconButton(
onPressed: () {
_startAddNewExpense(context);
},
icon: Icon(Icons.add),
),
],
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Card(
elevation: 5,
color: Theme.of(context).colorScheme.primary,
// HERE IT DOES WORK
child: Text("CHART!!"),
),
ExpensesList(_expensesObjectList), //THE IMPORTED WIDGET
],
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
floatingActionButton: FloatingActionButton(
onPressed: () {
_startAddNewExpense(context);
},
child: Icon(Icons.add),
),
),
);
}
}
imported widget
import 'package:flutter/material.dart';
import '../models/expenses_model.dart';
class ExpensesList extends StatelessWidget {
final List<ExpensesModel> expensesObjectList;
ExpensesList(this.expensesObjectList);
#override
Widget build(BuildContext context) {
return Container(
height: 600,
child: ListView.builder(
itemBuilder: (context, index) {
return Card(
elevation: 5,
child: Row(
children: [
Container(
padding: EdgeInsets.symmetric(
vertical: 10,
horizontal: 10,
),
margin: EdgeInsets.all(10),
decoration: BoxDecoration(
border: Border.all(
color: Theme.of(context).colorScheme.primary,
// HERE IT DOES NOT WORK
width: 2,
),
),
child: Text(
"PKR ${expensesObjectList[index].amount}",
style: TextStyle(
color: Theme.of(context).colorScheme.primary,
// HERE IT DOES NOT WORK
fontWeight: FontWeight.bold,
),
),
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"${expensesObjectList[index].name}",
style:
TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
),
Text(
DateTime.now().toString(),
style: TextStyle(
color: Colors.grey,
),
),
],
),
],
),
);
},
itemCount: expensesObjectList.length,
),
);
}
}
Screenshot of the app
as you can see the border and text aren't using the theme-defined color which is red.

You can access the ThemeData of your app by following.
Color color = Theme.of(context).primaryColor;

I think unnecessary "MaterialApp" of "build" in "class _MyAppPageState", like this.
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.primary,
// HERE IT DOES WORK
title: Text(
"Expense App",
// style: Theme.of(context).textTheme.title,
),
actions: [
IconButton(
onPressed: () {
_startAddNewExpense(context);
},
icon: Icon(Icons.add),
),
],
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Card(
elevation: 5,
color: Theme.of(context).colorScheme.primary,
// HERE IT DOES WORK
child: Text("CHART!!"),
),
ExpensesList(_expensesObjectList), //THE IMPORTED WIDGET
],
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
floatingActionButton: FloatingActionButton(
onPressed: () {
_startAddNewExpense(context);
},
child: Icon(Icons.add),
),
);
}
If you really need to "MaterialApp" of "class _MyAppPageState", I think you can add theme property, like this.
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: Theme.of(context), // <- add this line.
home: Scaffold(
By the way, why won't you use primarySwatch?
How about this?
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.red,
),
home: MyAppPage(),
);
}
}

Related

How can I make my bottom sheet look like this?

I would like make my bottom sheet like this- no background and the height and width determined by the content.
showModalBottomSheet(
context: context,
elevation: 0,
backgroundColor: Colors.transparent,
builder: (context) => Container(
height: 60,
decoration: BoxDecoration(
color: Colors.transparent,
borderRadius: BorderRadius.only(
topLeft: const Radius.circular(50.0),
topRight: const Radius.circular(50.0),
),
),
child: Container(
color: AppColors.grey8,
padding: EdgeInsets.all(12),
child: Text("Call Doctor",
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
fontFamily: 'Euclid',
color: AppColors.textColor,
),)
),
),
);
Check this code,let me know this work for you
for more details check this link cupertino Widgets also refer cupertino-ios-style-actionsheet
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("CupertinoActionSheet"),
),
body: Center(
child: ElevatedButton(
onPressed: () {
final action = CupertinoActionSheet(
title: Text(
"Flutter dev",
style: TextStyle(fontSize: 30),
),
message: Text(
"Select any action ",
style: TextStyle(fontSize: 15.0),
),
actions: <Widget>[
CupertinoActionSheetAction(
child: Text("Action 1"),
isDefaultAction: true,
onPressed: () {
print("Action 1 is been clicked");
},
),
CupertinoActionSheetAction(
child: Text("Action 2"),
isDestructiveAction: true,
onPressed: () {
print("Action 2 is been clicked");
},
)
],
cancelButton: CupertinoActionSheetAction(
child: Text("Cancel"),
onPressed: () {
Navigator.pop(context);
},
),
);
showCupertinoModalPopup(
context: context, builder: (context) => action);
},
child: Text("Click me "),
),
),
);
}
}

Adding an Icon to a List using a button and actively updating UI using Provider state management

I want to add an Icon to a List following UI update using flutter Provider state Management.
I was successful to add an Icon using the floating button and confirm the result by printing the new List length. This ensures the addition of an Icon to a List but it does not update the UI for the new added Icon. Snippets are below
#override
_MedicalCosmeticsDetailsPageState createState() =>
_MedicalCosmeticsDetailsPageState();
}
class _MedicalCosmeticsDetailsPageState
extends State<MedicalCosmeticsDetailsPage> {
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return ChangeNotifierProvider<GridIcons>(
create: (context) => GridIcons(),
child: SafeArea(
child: Scaffold(
appBar: AppBar(
automaticallyImplyLeading: true,
iconTheme: IconThemeData(color: Colors.purple),
title: Text(
'xyz',
style: TextStyle(color: Colors.purple),
),
backgroundColor: Colors.transparent,
elevation: size.width * 0.05,
actions: [
Padding(
padding: EdgeInsets.only(right: size.width * 0.01),
child: IconButton(
icon: Icon(
Icons.search,
),
onPressed: () {},
),
),
],
),
body: GridViewPage(),
floatingActionButton: Consumer<GridIcons>(
builder: (context, myIcons, _) {
return FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
print(myIcons.iconList.length);
myIcons.addIcon();
},
);
},
),
),
),
);
}
}
```//floating button for adding an ICON
```class GridIcons with ChangeNotifier {
List<IconData> iconList = [
Icons.ac_unit,
Icons.search,
Icons.arrow_back,
Icons.hdr_on_sharp,
];
addIcon<IconData>() {
iconList.add(Icons.sentiment_dissatisfied);
notifyListeners();
}
getIconList<IconData>() {
return iconList;
}
}
```//Function for icon addition
class GridViewPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
List _iconList = GridIcons().getIconList();
return ChangeNotifierProvider<GridIcons>(
create: (context) => GridIcons(),
child: Consumer<GridIcons>(
builder: (context, myIcon, child) {
return GridView.builder(
itemCount: _iconList.length,
padding: EdgeInsets.all(8.0),
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 250.0),
itemBuilder: (BuildContext context, int index) {
print('_buildGridViewBuilder $index');
return Card(
color: Colors.purple.shade300,
margin: EdgeInsets.all(8.0),
child: InkWell(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(
_iconList[index],
size: 48.0,
color: Colors.purple.shade100,
),
Divider(),
Text(
'Index $index',
textAlign: TextAlign.center,
style: GoogleFonts.dmSans(
fontSize: 16,
color: Colors.white,
),
),
],
),
onTap: () {
print('Row: $index');
},
),
);
},
);
},
),
);
}
}
The icon doesn't appear in the UI although an icon is added to the Icon List.
You can copy paste run full code below
Step 1: In GridViewPage, you do not need ChangeNotifierProvider
Step 2: remove List _iconList = GridIcons().getIconList();
Step 3: use myIcon.iconList.length and myIcon.iconList[index]
code snippet
class GridViewPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
//List _iconList = GridIcons().getIconList();
return Consumer<GridIcons>(
builder: (context, myIcon, child) {
return GridView.builder(
itemCount: myIcon.iconList.length,
...
Icon(
myIcon.iconList[index],
size: 48.0,
working demo
full code
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart';
class MedicalCosmeticsDetailsPage extends StatefulWidget {
#override
_MedicalCosmeticsDetailsPageState createState() =>
_MedicalCosmeticsDetailsPageState();
}
class _MedicalCosmeticsDetailsPageState
extends State<MedicalCosmeticsDetailsPage> {
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return ChangeNotifierProvider<GridIcons>(
create: (context) => GridIcons(),
child: SafeArea(
child: Scaffold(
appBar: AppBar(
automaticallyImplyLeading: true,
iconTheme: IconThemeData(color: Colors.purple),
title: Text(
'xyz',
style: TextStyle(color: Colors.purple),
),
backgroundColor: Colors.transparent,
elevation: size.width * 0.05,
actions: [
Padding(
padding: EdgeInsets.only(right: size.width * 0.01),
child: IconButton(
icon: Icon(
Icons.search,
),
onPressed: () {},
),
),
],
),
body: GridViewPage(),
floatingActionButton: Consumer<GridIcons>(
builder: (context, myIcons, _) {
return FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
print(myIcons.iconList.length);
myIcons.addIcon();
},
);
},
),
),
),
);
}
}
class GridIcons with ChangeNotifier {
List<IconData> iconList = [
Icons.ac_unit,
Icons.search,
Icons.arrow_back,
Icons.hdr_on_sharp,
];
addIcon<IconData>() {
iconList.add(Icons.sentiment_dissatisfied);
notifyListeners();
}
getIconList<IconData>() {
return iconList;
}
}
class GridViewPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
//List _iconList = GridIcons().getIconList();
return Consumer<GridIcons>(
builder: (context, myIcon, child) {
return GridView.builder(
itemCount: myIcon.iconList.length,
padding: EdgeInsets.all(8.0),
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 250.0),
itemBuilder: (BuildContext context, int index) {
print('_buildGridViewBuilder $index');
return Card(
color: Colors.purple.shade300,
margin: EdgeInsets.all(8.0),
child: InkWell(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(
myIcon.iconList[index],
size: 48.0,
color: Colors.purple.shade100,
),
Divider(),
Text(
'Index $index',
textAlign: TextAlign.center,
style: GoogleFonts.dmSans(
fontSize: 16,
color: Colors.white,
),
),
],
),
onTap: () {
print('Row: $index');
},
),
);
},
);
},
);
}
}
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: MedicalCosmeticsDetailsPage());
}
}

SolidBottomSheet Controller Example Flutter

SolidBottomSheetController() is not working in my code, I am not able to listen_events of height or anything, hopefully, and I am sure my code is correct.
Can Anyone Please Give Example of SolidBottomSheet() working, with Controller, how you are implementing and listening to the events
You can copy paste run full code below , it's from official example and add listen event
You can use _controller.heightStream.listen
code snippet
SolidController _controller = SolidController();
#override
void initState() {
_controller.heightStream.listen((event) {
print(event);
});
}
working demo
full code
import 'package:flutter/material.dart';
import 'package:solid_bottom_sheet/solid_bottom_sheet.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
SolidController _controller = SolidController();
#override
void initState() {
_controller.heightStream.listen((event) {
print(event);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Solid bottom sheet example"),
),
body: ListView.builder(
itemCount: 20,
itemBuilder: (context, index) {
return Card(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Stack(
alignment: Alignment.bottomRight,
children: <Widget>[
Image.asset("assets/cardImg.png"),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"Flutter rules?",
style: Theme.of(context).textTheme.title,
),
),
],
),
ButtonTheme.bar(
child: ButtonBar(
children: <Widget>[
FlatButton(
child: const Text('NOPE'),
onPressed: () {
/* ... */
},
),
FlatButton(
child: const Text('YEAH'),
onPressed: () {
/* ... */
},
),
],
),
),
],
),
);
},
),
bottomSheet: SolidBottomSheet(
controller: _controller,
draggableBody: true,
headerBar: Container(
color: Theme.of(context).primaryColor,
height: 50,
child: Center(
child: Text("Swipe me!"),
),
),
body: Container(
color: Colors.white,
height: 30,
child: Center(
child: Text(
"Hello! I'm a bottom sheet ",
style: Theme.of(context).textTheme.display1,
),
),
),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.stars),
onPressed: () {
_controller.isOpened ? _controller.hide() : _controller.show();
}),
);
}
}

Theme Data not applying in inherited classes

I have declared a theme in main.dart , and it works fine as long as the context is used in main.dart but when I use Theme.of(context).primaryColor in the child class context doesn't pickup the theme.
Main.dart
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Expenso',
theme: ThemeData(
primarySwatch: Colors.green,
accentColor: Colors.amber
),
home: Expenso(),
);
}
}
class Expenso extends StatefulWidget {
#override
_ExpensoState createState() => _ExpensoState();
}
class _ExpensoState extends State<Expenso> {
final List<Transaction> _transactions=[
];
void _addTransaction(String txTitle,double txAmount)
{
final newTx=Transaction(
title: txTitle,
amount: txAmount,
id: DateTime.now().toString(),
date: DateTime.now()
);
setState(() {
_transactions.add(newTx);
});
}
void _startAddNewTransaction(BuildContext ctx) {
showModalBottomSheet(
context: ctx,
builder: (_) {
return GestureDetector(
onTap: () {},
child: NewTransaction(_addTransaction),
behavior: HitTestBehavior.opaque,
);
},
);
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
backgroundColor:Theme.of(context).primaryColor,
title: Text('Expenso'),
actions: <Widget>[
IconButton(
icon: Icon(Icons.add),
onPressed: () => _startAddNewTransaction(context),
)
],
),
body:SingleChildScrollView(
child: Column(
//mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Container(
width: double.infinity,
height: 50,
child: Card(
color: Colors.blue,
child: Text('chart')
)
),
TransactionList(_transactions)
],
),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed:() => _startAddNewTransaction(context),
backgroundColor: Theme.of(context).accentColor,
),
)
);
}
}
transaction_list.dart
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import '../models/transaction.dart';
class TransactionList extends StatelessWidget {
final List<Transaction> tractn;
TransactionList(this.tractn);
#override
Widget build(BuildContext context) {
return Container(
height: 500,
child :tractn.isEmpty? Column(
children: <Widget>[
Text('No Transaction added yet'),
SizedBox(
height: 20,
),
Container(
height:300,
child: Image.asset('assets/Images/waiting.png',
fit: BoxFit.cover,),
)
],
): ListView.builder(
itemBuilder: (ctx,index){
return Card(
child: Row(
children: <Widget>[
Container(
margin: EdgeInsets.symmetric(
vertical: 10,
horizontal: 15,
),
decoration: BoxDecoration(border: Border.all(
color: Theme.of(context).primaryColor,
width: 2,
style: BorderStyle.solid
)
),
padding: EdgeInsets.all(10),
child: Text(
'₹ ${tractn[index].amount.toStringAsFixed(2)}',
style: TextStyle(
fontWeight: FontWeight.bold,
fontStyle: FontStyle.italic ,
fontSize: 20,
color: Colors.green,
),
),
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
tractn[index].title,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15,
color: Theme.of(context).primaryColor
),
),
Text(
DateFormat().format(tractn[index].date) ,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15,
color: Colors.grey
),),
Text(
tractn[index].id
)
],
)
],
),
);
},
itemCount: tractn.length,
)
);
}
}
Please guide me the way to implement the theme in inherited classes
I Agree with #Nolence comment.
If you are expecting to achieve the below result
Remove MaterialApp widget and make Scaffold as your primate return widget inside
class _ExpensoState
Sample Code:
import 'package:flutter/material.dart';
import 'package:flutter_app/Transaction.dart';
import 'transaction_list.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Expenso',
theme: ThemeData(
primarySwatch: Colors.green,
accentColor: Colors.amber
),
home: Expenso(),
);
}
}
class Expenso extends StatefulWidget {
#override
_ExpensoState createState() => _ExpensoState();
}
class _ExpensoState extends State<Expenso> {
final List<Transaction> _transactions=[
];
void _addTransaction(String txTitle,double txAmount)
{
final newTx=Transaction(
title: txTitle,
amount: txAmount,
id: DateTime.now().toString(),
date: DateTime.now()
);
setState(() {
_transactions.add(newTx);
});
}
void _startAddNewTransaction(BuildContext ctx) {
showModalBottomSheet(
context: ctx,
builder: (_) {
return GestureDetector(
onTap: () {},
child: NewTransaction(_addTransaction),
behavior: HitTestBehavior.opaque,
);
},
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor:Theme.of(context).primaryColor,
title: Text('Expenso'),
actions: <Widget>[
IconButton(
icon: Icon(Icons.add),
onPressed: () => _startAddNewTransaction(context),
)
],
),
body:SingleChildScrollView(
child: Column(
//mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Container(
width: double.infinity,
height: 50,
child: Card(
color: Colors.blue,
child: Text('chart')
)
),
TransactionList(_transactions)
],
),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed:() => _startAddNewTransaction(context),
backgroundColor: Theme.of(context).accentColor,
),
);
}
}
If this is not what you wanted, please elaborate your question or comment below.
In the build method of your Expenso widget you define another MaterialApp, which creates its own default theme (different to your first theme). Remove that MaterialApp widget and it should work.

Scaffold Drawer to showModalBottomSheet

At the homescreen of myApp() I have a stateless widget, it contains a MaterialApp and a Scaffold. Scaffold have a property of drawer and I passed I created a drawer, and one of the item in my drawer needs to open the showModalBottomSheet while closing the drawer. How can I achieve this? I've tried passing the context itself, and as globalKey.currentContext (after GlobalKey<ScaffoldState> globalKey = GlobalKey();) but the drawer sometimes closes, other time gives me a NoMethodFoundException (or something like that)
In short, how to have a Scaffold drawer that have one of the item, when tapped closes the drawer and showModalBottomSheet?
Current code:
class Timeline extends StatelessWidget {
#override
Widget build(BuildContext context) {
GlobalKey<ScaffoldState> homeScaffoldKey = GlobalKey();
return MaterialApp(
title: "Test",
theme: ThemeData(
appBarTheme: AppBarTheme(iconTheme: IconThemeData(color: Colors.black)),
),
home: Scaffold(
key: homeScaffoldKey,
drawer: showDrawer(homeScaffoldKey.currentContext),
backgroundColor: Colors.grey[100],
body: Stack(
children: <Widget>[
HomePageView(),
AppBar(
elevation: 0,
backgroundColor: Colors.transparent,
),
],
),
),
);
}
}
Drawer showDrawer(BuildContext context) {
void showCalendarsModalBottom() {
showModalBottomSheet(
context: context,
builder: (BuildContext builder) {
return ListView.builder(
itemCount: repo.calendars.length,
itemBuilder: (builder, index) {
return StatefulBuilder(
builder: (builder, StateSetter setState) => ListTile(
leading: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Checkbox(
value: repo.getIsEnabledCal(repo.getCal(index)),
onChanged: (value) {
setState(() {
repo.toggleCalendar(repo.getCal(index));
});
},
),
Container(
height: 14,
width: 14,
margin: EdgeInsets.only(left: 2, right: 6),
decoration: BoxDecoration(
color: Colors.redAccent,
shape: BoxShape.circle,
),
),
Text(
repo.getCal(index).name,
style: TextStyle(
fontSize: 16,
),
),
],
),
onTap: () {
setState(() {
repo.toggleCalendar(repo.getCal(index));
});
},
),
);
},
);
},
);
}
return Drawer(
child: ListView(
children: <Widget>[
DrawerHeader(
child: Align(
child: Text('Timeline', textScaleFactor: 2),
alignment: Alignment.bottomLeft,
),
),
ListTile(
title: Text('Dark Mode'),
onTap: () => Navigator.pop(context),
),
ListTile(
title: Text('Calenders'),
onTap: () {
Navigator.pop(context);
showCalendarsModalBottom();
},
)
],
),
);
}
Updated working code based on your code snippet:
You'll need to have statefulwidget that will help to pass the context from drawer to bottomsheet and pass the context as an argument in showCalendarModalBottomSheet() method.
void main() {
runApp(new MaterialApp(home: Timeline(), debugShowCheckedModeBanner: false));
}
class Timeline extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: "Test",
theme: ThemeData(
appBarTheme: AppBarTheme(iconTheme: IconThemeData(color: Colors.black)),
),
home: MyHomePage()
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
drawer: AppDrawer(),
backgroundColor: Colors.grey[100],
body: Stack(
children: <Widget>[
//HomePageView(),
AppBar(
elevation: 0,
backgroundColor: Colors.transparent,
)
],
)
);
}
Widget AppDrawer() {
return Drawer(
child: ListView(
children: <Widget>[
DrawerHeader(
child: Align(
child: Text('Timeline', textScaleFactor: 2),
alignment: Alignment.bottomLeft,
),
),
ListTile(
title: Text('Dark Mode'),
onTap: () => Navigator.pop(context),
),
ListTile(
title: Text('Calenders'),
onTap: () {
Navigator.of(context).pop();
showCalendarsModalBottom(context);
},
)
],
),
);
}
Future<Null> showCalendarsModalBottom(context) {
return showModalBottomSheet(context: context, builder: (context) => Container(
color: Colors.red,
// your code here
));
}
}
And the output is: When app drawer menu Calendar is tapped, it closes and opens the bottomsheet seamlessly. If you tap on app drawer again and repeat steps, you see smooth transition between drawer and bottomsheet. Hope this answers your question.