How to reduce the white space beside the drawer icon in Flutter? - flutter

In my flutter project, I have set one custom drawer.
Here's code for custom drawer-
class AppDrawer extends StatelessWidget {
#override
Widget build(BuildContext context) {
double defaultScreenWidth = 400.0;
double defaultScreenHeight = 810.0;
ScreenUtil.instance = ScreenUtil(
width: defaultScreenWidth,
height: defaultScreenHeight,
allowFontScaling: true,
)..init(context);
return SizedBox(
width: MediaQuery.of(context).size.width * 0.70,
child: Drawer(
child: Container(
color: Colors.black87,
child: ListView(
padding: EdgeInsets.zero,
children: <Widget>[
SizedBox(height: ScreenUtil.instance.setHeight(30),),
_createDrawerItem(
icon: Icons.keyboard_arrow_right,
text: 'English to Bangla',
onTap: () =>
Navigator.pushReplacementNamed(context, Routes.englishToBangla)),
Padding(
padding: EdgeInsets.only(left:ScreenUtil.instance.setWidth(20), right: ScreenUtil.instance.setWidth(20)),
child: Divider(
height: ScreenUtil.instance.setHeight(10),
color: Colors.grey,
),
),
],
),
),
),
);
}
Widget _createHeader() {
return DrawerHeader(
margin: EdgeInsets.zero,
padding: EdgeInsets.zero,
decoration: BoxDecoration(
image: DecorationImage(
fit: BoxFit.fill,
image: AssetImage('path/to/header_background.png'))),
child: Stack(children: <Widget>[
Positioned(
bottom: 12.0,
left: 16.0,
child: Text("Flutter Step-by-Step",
style: TextStyle(
color: Colors.white,
fontSize: 20.0,
fontWeight: FontWeight.w500))),
]));
}
Widget _createDrawerItem(
{IconData icon, String text, GestureTapCallback onTap}) {
return ListTile(
title: Padding(
padding: EdgeInsets.only(left: ScreenUtil.instance.setWidth(10)),
child: Row(
children: <Widget>[
Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.teal
),
child: Icon(icon, color: Colors.white,)
),
Padding(
padding: EdgeInsets.only(left: ScreenUtil.instance.setWidth(10)),
child: Text(text, style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold, fontSize: ScreenUtil.instance.setSp(14) ),),
)
],
),
),
onTap: onTap,
);
}
}
Here's code for the toolBar which is shown beside the drawer icon-
class SearchAppBar extends StatefulWidget implements PreferredSizeWidget {
final PatternCallback onPatternSelected;
SearchAppBar(this.onPatternSelected, {Key key})
: preferredSize = Size.fromHeight(90),
super(key: key);
#override
final Size preferredSize; // default is 56.0
#override
_SearchAppBarState createState() => _SearchAppBarState();
}
class _SearchAppBarState extends State<SearchAppBar> {
TextEditingController _searchTextController = TextEditingController();
#override
Widget build(BuildContext context) {
double defaultScreenWidth = 400.0;
double defaultScreenHeight = 810.0;
ScreenUtil.instance = ScreenUtil(
width: defaultScreenWidth,
height: defaultScreenHeight,
allowFontScaling: true,
)..init(context);
return Container(
color: Colors.white,
child: Row(
children: <Widget>[
Expanded(
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(3),
),
child: Theme(
data:
Theme.of(context).copyWith(primaryColor: Color(0xFFff9900)),
child: TextFormField(
autofocus: false,
style: TextStyle(fontSize: ScreenUtil.instance.setSp(18)),
keyboardType: TextInputType.text,
controller: _searchTextController,
decoration: InputDecoration(
border: InputBorder.none,
hintText: 'Search for any word you want',
hintStyle:
TextStyle(fontSize: ScreenUtil.instance.setSp(16)),
contentPadding: EdgeInsets.symmetric(
vertical: 14,
horizontal: 10),
),
onChanged: (String value) {
widget.onPatternSelected(value);
},
),
),
),
),
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(0),
),
child: InkWell(onTap: (){
if(_searchTextController.text.isNotEmpty) {
Navigator.of(context).push(MaterialPageRoute(builder: (context)=>WordDetailScreen(_searchTextController.text.toLowerCase())));
}
},
child: Icon(Icons.search, color: Colors.blue,))),
SizedBox(width: 15)
],
),
);
}
}
And then, in the class where I want to use this drawer, I have called inside Scaffold like below-
drawer: AppDrawer()
But the problem is this causing a white space beside the drawer icon like below image-
And I am having no idea from where this extra padding or margin is happening. So, I need a solution to reduce this extra white space beside the drawer icon.

You can use Transform.translate to move the search bar to the left:
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: Builder(builder: (context) {
return IconButton(
icon: Icon(Icons.menu),
onPressed: () => Scaffold.of(context).openDrawer(),
);
}),
title: Transform.translate(
offset: Offset(-30.0, 0.0),
child: Text('this is the title') // here you can put the search bar
),
),
drawer: Drawer(
),
);
}

Just add a property called "titleSpacing" in your AppBar Tag,
Sample
appBar: AppBar(
titleSpacing: 0, //Add this line to your code
title: Text(widget.title),
leading: Icon(Icons.android),
),

Related

Bottom overflowed by 11 pixels

I'm having bottom overflowed by pixels flutter when showing keyboard, i tried SingleChildSCrollView and still couldn't find the solution for it. my aim to make the Get.defaultDialog scrollable.
here my code :
class AddCard extends StatelessWidget {
final homeCtrl = Get.find<HomeController>();
AddCard({super.key});
#override
Widget build(BuildContext context) {
final icons = getIcons();
var squareWidth = Get.width - 12.0.wp;
return Container(
width: squareWidth / 2,
height: squareWidth / 2,
margin: EdgeInsets.all(3.0.wp),
child: InkWell(
onTap: () async {
await Get.defaultDialog(
titlePadding: EdgeInsets.symmetric(vertical: 5.0.wp),
radius: 5,
title: 'Task Type',
content: Form(
key: homeCtrl.formKey,
child: Column(
children: [
Padding(
padding: EdgeInsets.symmetric(horizontal: 3.0.wp),
child: TextFormField(
controller: homeCtrl.editCtrl,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'title',
),
validator: (value) {
if (value == null || value.trim().isEmpty) {
return 'Please enter your task title';
}
return null;
},
),
),
Padding(
padding: EdgeInsets.symmetric(vertical: 5.0.wp),
child: Wrap(
spacing: 2.0.wp,
children: icons
.map((e) => Obx(() {
final index = icons.indexOf(e);
return ChoiceChip(
selectedColor: Colors.grey[200],
pressElevation: 0,
backgroundColor: Colors.white,
label: e,
selected: homeCtrl.chipIndex.value == index,
onSelected: (bool selected) {
homeCtrl.chipIndex.value =
selected ? index : 0;
},
);
}))
.toList(),
),
),
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: blue,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
minimumSize: const Size(150, 40),
),
onPressed: () {
if (homeCtrl.formKey.currentState!.validate()) {
int icon =
icons[homeCtrl.chipIndex.value].icon!.codePoint;
String color =
icons[homeCtrl.chipIndex.value].color!.toHex();
var task = Task(
title: homeCtrl.editCtrl.text,
icon: icon,
color: color,
);
}
},
child: const Text("Confirm"),
),
],
),
));
},
child: DottedBorder(
color: Colors.grey[400]!,
dashPattern: const [8, 4],
child: Center(
child: Icon(
Icons.add,
size: 10.0.wp,
color: Colors.grey,
),
)),
),
);
}
}
The widget that makes the error is the Get.defaultDialog().
There are two ways:
You can use the resizeToAvoidBottomInset property on the Scaffold widget.
You can use ListView instead Column:
onTap: () async {
await Get.defaultDialog(
radius: 5,
titlePadding: EdgeInsets.symmetric(vertical: 5.0),
title: Text('Task Type'),
content: SizedBox(
height: 500,//your height
width: 300, //your width
child:
Form(
child: ListView(
children: [
Padding(
padding: EdgeInsets.symmetric(horizontal: 3.0),
child: TextFormField(
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'title',
),
),
),
Padding(
padding: EdgeInsets.symmetric(vertical: 5.0),
child: Wrap(
spacing: 2.0,
children: List.generate(//replace with your content
100,
(index) => Container(
height: 20,
width: 50,
padding: EdgeInsets.all(20),
color: Colors.red,
))),
),
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blue,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
minimumSize: const Size(150, 40),
),
onPressed: () {},
child: const Text("Confirm"),
),
],
),
),
),
),
);
It`s important to give your dialog a fixed height and width, in this defined area it's possible to make a scrollable widget work.
If your aim is to make the dialog scrollable, Use ListView with defined height.
Further for your SizedBox to work as expected in case of any overplexes use the Flexible widget
Try the code structure:
GetDialog
|_Flexible
|_SizedBox 👈Define proper height and width here
|_ListView
I can't really understand your question well because you only posted part of the codes, but try wrapping your Scaffold body with SingleChildScrollView.
maybe you're using the SingleChildScrollView at a wrong place.

Flutter -Widget Text, not updating when value change even with SetState

I have created a container. His child is a text.
When I tap on the container/text, it display a modal and a Picker.
Then, the user can select a value. Press the confirm button and my text widget should change to display the value selected by the user.
But in my case, it is not updating the value of the text widget. I have used that in the past and it was working very well. But here it is not and I do not see why. I am on this since 8:00. A little help would be appreciated. Many thanks.
int valuePickerUnitSelected =0;
String unitCount = '';
int unitCountInt;
String goal = "";
List <String> unitForHabits = ['Count', 'Minute(s)','Hour(s)','Gramme(s)', 'Pound(s)'];
class AddingHabitDetails extends StatefulWidget {
const AddingHabitDetails({Key key}) : super(key: key);
#override
_AddingHabitDetailsState createState() => _AddingHabitDetailsState();
}
class _AddingHabitDetailsState extends State<AddingHabitDetails> {
BuildContext get ctx => null;
#override
Widget build(BuildContext context) {
return Scaffold(
//drawer: new MyMenu(), //TODO a remettre
appBar: new AppBar(
title: new Text('Habits'),
),
body: Column(
children: [
titleZone('Name'),
textFieldHabits('Habit name', context),
titleZone('Goals'),
FlatButton(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (unitCount.length < 2 )...[
Container(
width: 65,
decoration: BoxDecoration(
border: Border.all(color: Colors.blue,
),
color: Colors.blue,
borderRadius: BorderRadius.all(Radius.circular(20))),
child:
Center(child: Text(
'Time', style: TextStyle(color: Colors.black,))))
]
else
...[
Container(
width: 65,
decoration: BoxDecoration(
border: Border.all(color: Colors.blue,),
color: Colors.blue,
borderRadius: BorderRadius.all(
Radius.circular(20))),
child: Center(
child: Text(
unitCount, style: TextStyle(color: Colors.black,))))
],
],
),
onPressed: () {
setState(() {
showModalBottomSheet(
context: context,
builder: (BuildContext context) {
return ShowPickerUnite(unitForHabits);
});
},
);
},
),
//ChipGoalV3(ctx),// ChipGoal(),
textFieldHabits('Goals', context),
titleZone('Frequency'),
textFieldHabits('Frequency', context),
titleZone('Time Range'),
titleZone('Reminder'),
titleZone('Habits Term'),
],
),
);
}
}
//########################################################################
class ShowPickerUnite extends StatefulWidget {
List<String> myListUnit;
ShowPickerUnite(this.myListUnit, {Key key}) : super(key: key);
#override
_ShowPickerUniteState createState() => _ShowPickerUniteState(
myListUnit);
}
class _ShowPickerUniteState extends State<ShowPickerUnite> {
List <String> myListUnit;
_ShowPickerUniteState(this.myListUnit);
#override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Container(
decoration: BoxDecoration(
color: Color(0xffffffff),
border: Border(
bottom: BorderSide(
color: Color(0xffffffff),
width: 0.0,
),
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
CupertinoButton(
child: Text('Cancel'),
onPressed: () {
Navigator.of(context).pop();
},
padding: const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 5.0,
),
),
DefaultTextStyle(
style: TextStyle(
fontSize: 16.0,
color: Colors.black,
fontWeight: FontWeight.bold),
child: Text('Select what you want'),
),
// Text('Energy Needed', style: TextStyle(fontSize: 12.0, color: Colors.black),
// ),
CupertinoButton(
child: Text('Confirm'),
onPressed: () {
setState(() {
unitCount = unitForHabits[valuePickerUnitSelected];
print(unitCount);
});
Navigator.of(context).pop();
},
padding: const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 5.0,
),
),
],
),
),
Container(
//width: 360,
height: 200,
decoration:BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(15.0)),
),
child: CupertinoPicker(
backgroundColor: Colors.white ,
useMagnifier: true,
magnification: 1.3,
scrollController: FixedExtentScrollController(initialItem: 0),
itemExtent: 25,
children: [
for (String name in myListUnit)
Center(
child:Text(name)),
],
onSelectedItemChanged: (value) {
setState(() {
valuePickerUnitSelected = value;
// taskEnergy = myListEnergy[valuePickerEnergySelected];
// taskNewValue ['task_Energy'] = taskEnergy;
});
}))
]);
}
}
Widget inputNameHabit (){
return Padding(
padding: const EdgeInsets.all(8.0),
child: Text ('Name Habits',style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold),),
);
}
Widget titleZone (String _titleName){
return Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Text ( _titleName,
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold),),
],
),
);
}
Widget textFieldHabits (String item,context){
return TextField(
decoration: InputDecoration(
hintText: item,
filled: true,
fillColor: Colors.grey[300],
border: OutlineInputBorder(
borderSide: BorderSide.none,
borderRadius: BorderRadius.circular(50)
),
),
onTap: (){
Navigator.push(context,
MaterialPageRoute(
builder: (context) => HabitGoalUnitSelection(), //TODO MODIFIER route selon source
),
);
},);
}
Wait for the dialog to finish and then call setState to update the UI.
Modify this way
onPressed: () async {
await showModalBottomSheet(
context: context,
builder: (BuildContext context) {
return ShowPickerUnite(unitForHabits);
});
setState(() {});

How can I search the button I made in ListView with Search Bar?

I created a button shape called 'VocabularyWordsButton' and when I try it under a ListView it works just fine. But when I make 100 buttons under ListView, I want to find them via Search Bar. But I don't know how to do it somehow.
What I want to do: I want to distinguish the buttons by filtering the word 'englishWord' among the buttons listed below. When I enter the word in 'englishWord' in Search Bar, I want the buttons containing that word to be filtered.
If I do something like below, only the texts inside are listed, not the button I made.
VocabularyWordsButton.dart
import 'package:being_moroccan/AdHelper.dart';
import 'package:flutter/material.dart';
import 'package:audioplayers/audioplayers.dart';
import 'package:sizer/sizer.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';
import 'package:easy_localization/easy_localization.dart';
class VocabularyWordsButton extends StatefulWidget {
VocabularyWordsButton(
{required this.englishWord,
required this.trasncribedWord,
required this.arabicWord,
required this.sound});
final String englishWord;
final String trasncribedWord;
final String arabicWord;
final String sound;
#override
_VocabularyWordsButtonState createState() => _VocabularyWordsButtonState();
}
class _VocabularyWordsButtonState extends State<VocabularyWordsButton> {
AdHelper adHelper = AdHelper();
#override
void didChangeDependencies() {
// TODO: implement didChangeDependencies
super.didChangeDependencies();
adHelper.myLargeBanner.load();
}
bool _canShowButton = true;
void hideWidget() {
setState(() {
_canShowButton = !_canShowButton;
});
}
final AudioCache _audioCache = AudioCache(
prefix: 'audio/',
fixedPlayer: AudioPlayer()..setReleaseMode(ReleaseMode.STOP),
);
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: !_canShowButton
? Column(
children: [
Container(
height: 195.h / 6,
decoration: BoxDecoration(
color: Colors.transparent,
borderRadius: BorderRadius.all(Radius.circular(20)),
),
child: Container(
height: 100,
child: Column(
children: [
Container(
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
borderRadius:
BorderRadius.all(Radius.circular(20))),
child: Center(
child: TextButton(
onPressed: () {
hideWidget();
},
child: Container(
width: MediaQuery.of(context).size.width,
child: Center(
child: Text(
widget.englishWord,
style: TextStyle(
fontSize: 30.sp / 2,
color: Colors.white),
),
),
),
),
),
),
ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all<Color>(
Colors.transparent),
shape: MaterialStateProperty.all<
RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius:
BorderRadius.all(Radius.circular(20)),
),
),
),
onPressed: () {
print('cal');
_audioCache.play('${widget.sound}.mp3');
},
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(2.0),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
'TRANSCRIBED'.tr(),
style: TextStyle(
fontSize: 25.sp / 2,
),
),
Container(
width:
MediaQuery.of(context).size.width /
2,
height: 60.h / 7,
child: Center(
child: Text(
widget.trasncribedWord,
style: TextStyle(
fontSize: 25.sp / 2,
),
),
),
),
],
),
),
Padding(
padding: const EdgeInsets.all(2.0),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
'ARABIC'.tr(),
style: TextStyle(
fontSize: 25.sp / 2,
),
),
Container(
width:
MediaQuery.of(context).size.width /
2,
height: 60.h / 7,
child: Center(
child: Text(
widget.arabicWord,
style: TextStyle(
fontSize: 25.sp / 2,
),
),
),
),
],
),
),
],
),
),
),
],
),
),
),
Container(
height: 100,
child: AdWidget(ad: adHelper.myLargeBanner),
),
],
)
: Container(
width: MediaQuery.of(context).size.width / 2,
decoration: BoxDecoration(
color: Colors.grey.withOpacity(0.1),
borderRadius: BorderRadius.all(Radius.circular(20))),
child: Center(
child: ElevatedButton(
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all<Color>(Colors.transparent),
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(20)),
),
),
),
onPressed: () {
hideWidget();
},
child: Container(
width: MediaQuery.of(context).size.width,
child: Center(
child: Text(
widget.englishWord,
style:
TextStyle(fontSize: 30.sp / 2, color: Colors.white),
),
),
),
),
),
),
);
}
}
DictionaryScreen.dart
import 'package:sizer/sizer.dart';
import 'package:flutter/material.dart';
import 'package:easy_localization/easy_localization.dart';
import 'VocabularyWords/VocabularyWordsButton.dart';
class DictionaryScreen extends StatefulWidget {
static const String id = 'Dictionary_Screen';
const DictionaryScreen({Key? key}) : super(key: key);
#override
_DictionaryScreenState createState() => _DictionaryScreenState();
}
class _DictionaryScreenState extends State<DictionaryScreen> {
TextEditingController editingController = TextEditingController();
// final duplicateItems = List<String>.generate(10000, (i) => "Item $i");
// var items = List<String>();
List<VocabularyWordsButton> words = [
VocabularyWordsButton(
englishWord: 'To pray'.tr(),
trasncribedWord: 'Sella',
arabicWord: 'صْلّى',
sound: 'Sella',
),
VocabularyWordsButton(
englishWord: 'To prefer'.tr(),
trasncribedWord: 'Feddel',
arabicWord: 'فْضّلْ',
sound: 'Feddel',
)
];
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(),
body: Container(
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
onChanged: (value) {
setState(() {});
},
controller: editingController,
decoration: InputDecoration(
labelText: "Search",
hintText: "Search",
prefixIcon: Icon(Icons.search),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(25.0)))),
),
),
Expanded(
child: ListView.builder(
shrinkWrap: true,
itemCount: words.length,
itemBuilder: (context, index) {
if (editingController.text.isEmpty) {
return ListTile(
title: Text('${words[index].englishWord} '),
);
} else if (words[index]
.englishWord
.toLowerCase()
.contains(editingController.text)) {
return ListTile(
title: Text('${words[index].englishWord} '),
);
} else {
return Container();
}
}),
),
],
),
),
);
}
}

Why does a change in state of a child bottom sheet trigger a rebuild of parent widget?

I have a Scaffold screen (ListsScreen).
Which has a Button(AddNewListButton) that opens up a Modal Bottom Sheet (ListScreenBottomSheetWidget).
Bottom Sheet has TextField (ListTitleInputTextFieldWidget).
When i tap the TextField to open the keyboard, the parent screen rebuilds itself, due to which ofcourse all its child widgets are rebuilt as well.
Why is this happening? I was under the impression that state changes only rebuild themselves or their children, not their parents. And i also added const constructors almost everywhere to avoid rebuilds but this is still happening.
The Parent ListsScreen:
class ListsScreen extends StatelessWidget {
const ListsScreen();
static const routeName = '/lists-screen';
#override
Widget build(BuildContext context) {
final user = Provider.of<AuthProvider>(context, listen: false).getUser;
print('stateless rebuilding');
return Scaffold(
appBar: AppBar(
centerTitle: false,
title: Text(
'${user['name']}\'s Lists',
style: TextStyle(
color: Theme.of(context).primaryColorLight,
),
),
actions: <Widget>[
const SignOutButton(),
],
),
body: Center(
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
children: <Widget>[
SizeConfig.smallDevice
? const SizedBox(
height: 30,
)
: const SizedBox(
height: 40,
),
SizeConfig.smallDevice
? Text(
'Welcome to TODOS',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20,
color: Colors.grey[700],
),
)
: Text(
'Welcome to TODOS',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 25,
color: Colors.grey[700],
),
),
SizeConfig.smallDevice
? const SizedBox(
height: 30,
)
: const SizedBox(
height: 40,
),
const AddNewListButton(),
SizeConfig.smallDevice
? const SizedBox(
height: 30,
)
: const SizedBox(
height: 40,
),
const UserListsListViewWidget(),
],
),
),
),
);
}
}
class SignOutButton extends StatelessWidget {
const SignOutButton();
Future<void> _submitRequest(BuildContext context) async {
_showLoadingAlert(context);
try {
await Provider.of<AuthProvider>(context, listen: false)
.submitLogOutRequest();
Navigator.of(context).pop();
Navigator.of(context).pushReplacementNamed(LoginScreen.routeName);
} on HttpExceptions catch (error) {
Navigator.of(context).pop();
_showErrorDialogue(error.getErrorList, context);
}
}
void _showErrorDialogue(List<dynamic> errorMessages, BuildContext context) {
showDialog(
context: context,
builder: (ctx) => Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0),
),
child: ErrorListWidget(errorMessages: errorMessages),
),
);
}
void _showLoadingAlert(BuildContext context) {
showDialog(
context: context,
builder: (ctx) => const LoadingWidget(),
);
}
#override
Widget build(BuildContext context) {
return FlatButton(
onPressed: () => _submitRequest(context),
child: Row(
children: <Widget>[
Text(
'Sign Out',
style: TextStyle(
color: Theme.of(context).primaryColorLight,
),
),
Icon(
Icons.exit_to_app,
color: Theme.of(context).primaryColorLight,
),
],
),
);
}
}
class AddNewListButton extends StatelessWidget {
const AddNewListButton();
void _modalBottomSheetMenu(BuildContext context) {
showModalBottomSheet(
context: context,
backgroundColor: Colors.transparent,
isScrollControlled: true,
builder: (builder) {
return const ListScreenBottomSheetWidget();
},
);
}
#override
Widget build(BuildContext context) {
return RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5),
),
elevation: 10,
color: Theme.of(context).primaryColor,
onPressed: () => _modalBottomSheetMenu(context),
child: Text(
'+ Add List',
style: TextStyle(
color: Colors.white,
fontSize: SizeConfig.smallDevice ? 10 : 15,
),
),
);
}
}
The Modal Bottom Sheet:
import 'package:flutter/material.dart';
import 'package:todo_spicotech/helpers/size_config.dart';
class ListScreenBottomSheetWidget extends StatelessWidget {
const ListScreenBottomSheetWidget();
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
FocusScopeNode currentFocus = FocusScope.of(context);
if (!currentFocus.hasPrimaryFocus) {
currentFocus.unfocus();
}
currentFocus.unfocus();
},
child: Container(
margin: const EdgeInsets.all(20.0),
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom,
),
child: Material(
borderRadius: BorderRadius.all(Radius.circular(15)),
elevation: 10,
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
SizeConfig.smallDevice
? Text(
'Create a new List',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20,
color: Colors.grey[700],
),
)
: Text(
'Create a new List',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 25,
color: Colors.grey[700],
),
),
SizeConfig.smallDevice
? const SizedBox(
height: 20,
)
: const SizedBox(
height: 30,
),
const ListTitleInputTextFieldWidget(),
SizeConfig.smallDevice
? const SizedBox(
height: 20,
)
: const SizedBox(
height: 30,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
InkWell(
borderRadius: BorderRadius.circular(5),
onTap: () {
Navigator.of(context).pop();
},
child: Ink(
padding: EdgeInsets.all(10),
child: const Text('CANCEL'),
),
),
RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5),
),
elevation: 10,
color: Theme.of(context).primaryColor,
onPressed: () {},
child: Text(
'Create',
style: TextStyle(
color: Colors.white,
fontSize: SizeConfig.smallDevice ? 10 : 15,
),
),
),
],
),
],
),
),
),
),
);
}
}
class ListTitleInputTextFieldWidget extends StatefulWidget {
const ListTitleInputTextFieldWidget();
#override
_ListTitleInputTextFieldWidgetState createState() => _ListTitleInputTextFieldWidgetState();
}
class _ListTitleInputTextFieldWidgetState extends State<ListTitleInputTextFieldWidget> {
#override
Widget build(BuildContext context) {
return TextFormField(
decoration: const InputDecoration(
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.lightBlue,
),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.lightBlue,
),
),
labelText: 'List Title',
contentPadding: EdgeInsets.all(10),
),
);
}
}
when you call showModalBottomSheet , it actually use Navigator inside
return Navigator.of(context, rootNavigator: useRootNavigator).push(_ModalBottomSheetRoute<T>(
builder: builder,
source code of showModalBottomSheet https://github.com/flutter/flutter/blob/17079f26b54c8517678699a0cefe5f7bfec67b3f/packages/flutter/lib/src/material/bottom_sheet.dart#L635
Flutter teams' reply of issue Pages on Navigator stack rebuild when a new page is pushed https://github.com/flutter/flutter/issues/11655#issuecomment-348287396
This is working as intended. In general, you should assume that all widgets can rebuild at any time, that they don't is mostly just an optimisation.
In particular, routes will rebuild because their navigator state has changed so they might need to update how they draw back buttons and the like.

adding ListView.builder

I'm trying to make the displayAccoutList() scrollable.
I've tried to use ListView but it didn't work. I'm thinking to use ListView.builder but I don't know how to create data for accountItems()
enter code here`import 'package:flutter/material.dart';
import 'app_drawer.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Accounts',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Account(),
);
}
}
class Account extends StatefulWidget {
#override
_AccountState createState() => _AccountState();
}
class _AccountState extends State<Account> {
Card topArea() =>
Card(
margin: EdgeInsets.all(10.0),
elevation: 1.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(50.0))),
child: Container(
decoration: BoxDecoration(
gradient: RadialGradient(
colors: [Color(0xFFFF5722), Color(0xFFFF5722)])),
padding: EdgeInsets.all(5.0),
// color: Color(0xFF015FFF),
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
IconButton(
icon: Icon(
Icons.arrow_back,
color: Colors.white,
),
onPressed: () {},
),
Text("Savings",
style: TextStyle(color: Colors.white, fontSize: 20.0)),
IconButton(
icon: Icon(
Icons.arrow_forward,
color: Colors.white,
),
onPressed: () {},
)
],
),
Center(
child: Padding(
padding: EdgeInsets.all(5.0),
child: Text(r"£ " "100,943.33",
style: TextStyle(color: Colors.white, fontSize: 24.0)),
),
),
SizedBox(height: 35.0),
],
)),
);
#override
Widget build(BuildContext context) {
return Scaffold(
drawer: AppDrawer(),
appBar: AppBar(
iconTheme: IconThemeData(
color: Colors.grey, //change your color here
),
backgroundColor: Colors.white,
elevation: 0.0,
title: Text(
"Accounts",
style: TextStyle(color: Colors.black),
),
centerTitle: true,
actions: <Widget>[
IconButton(
icon: Icon(
Icons.search,
color: Colors.grey,
),
onPressed: () {},
)
],
),
body: Container(
color: Colors.white,
child: Column(
children: <Widget>[
topArea(),
SizedBox(
height: 40.0,
child: Icon(Icons.refresh,
size: 35.0,
color: Color(0xFFFF5722),
),
),
displayAccoutList()
],
),
),
bottomNavigationBar: BottomAppBar(
elevation: 0.0,
child: Container(
margin: EdgeInsets.symmetric(vertical: 20.0),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
FlatButton(
padding:
EdgeInsets.symmetric(vertical: 12.0, horizontal: 30.0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(0.0)),
color: Color(0xFFFF5722),
// borderSide: BorderSide(color: Color(0xFF015FFF), width: 1.0),
onPressed: () {},
child: Text("ACTIVITY"),
),
OutlineButton(
padding:
EdgeInsets.symmetric(vertical: 12.0, horizontal: 28.0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(0.0)),
borderSide: BorderSide(color: Color(0xFFFF5722), width: 1.0),
onPressed: () {},
child: Text("STATEMENTS"),
),
OutlineButton(
padding:
EdgeInsets.symmetric(vertical: 12.0, horizontal: 28.0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(0.0)),
borderSide: BorderSide(color: Color(0xFFFF5722), width: 1.0),
onPressed: () {},
child: Text("DETAILS"),
)
],
),
),
)
);
}
}
Container accountItems(String item, String charge, String dateString,
String type,
{Color oddColour = Colors.white}) =>
Container(
decoration: BoxDecoration(color: oddColour),
padding:
EdgeInsets.only(top: 20.0, bottom: 20.0, left: 5.0, right: 5.0),
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(item, style: TextStyle(fontSize: 16.0)),
Text(charge, style: TextStyle(fontSize: 16.0))
],
),
SizedBox(
height: 10.0,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(dateString,
style: TextStyle(color: Colors.grey, fontSize: 14.0)),
Text(type, style: TextStyle(color: Colors.grey, fontSize: 14.0))
],
),
],
),
);
displayAccoutList() {
return Container(
margin: EdgeInsets.all(15.0),
child: Column(
children: <Widget>[
accountItems("M KING", r"+ £ 4,946.00", "15-07-19", "Credit",
oddColour: const Color(0xFFF7F7F9)),
accountItems(
"Gordon Street Tenants", r"+ £ 5,428.00", "15-07-19", "Credit"),
accountItems("Amazon EU", r"+ £ 746.00", "15-07-19", "Credit",
oddColour: const Color(0xFFF7F7F9)),
accountItems(
"Floww LTD", r"+ £ 5,526.00", "15-07-19", "Credit"),
accountItems(
"KLM", r"- £ 2,500.00", "10-07-19", "Payment",
oddColour: const Color(0xFFF7F7F9)),
],
),
);
`
The other page app_drawer.dart
`
import 'package:flutter/material.dart';
class AppDrawer extends StatefulWidget {
#override
_AppDrawerState createState() => _AppDrawerState();
}
class _AppDrawerState extends State<AppDrawer> {
#override
Widget build(BuildContext context) {
return SizedBox(
width: 160.0,
child: Drawer(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: 50.0),
child: FlatButton.icon(
icon: Icon(
Icons.arrow_back,
color: Colors.grey,
),
onPressed: null,
label: Text("Back",
style: TextStyle(
fontWeight: FontWeight.w400,
fontSize: 16.0,
color: Colors.black)),
color: Colors.black,
),
),
buildMenuItem(Icons.account_balance, "ACCOUNTS",
opacity: 1.0, color: Color(0xFFFF6E40)),
Divider(),
buildMenuItem(Icons.compare_arrows, "TRANSFER"),
Divider(),
buildMenuItem(Icons.receipt, "STATEMENTS"),
Divider(),
buildMenuItem(Icons.attach_money, "PAYMENTS"),
Divider(),
buildMenuItem(Icons.sentiment_satisfied, "INVESTMENTS"),
Divider(),
buildMenuItem(Icons.phone, "SUPPORT"),
Divider()
],
),
),
);
}
Opacity buildMenuItem(IconData icon, String title,
{double opacity = 0.3, Color color = Colors.black}) {
return Opacity(
opacity: opacity,
child: Center(
child: Column(
children: <Widget>[
SizedBox(
height: 20.0,
),
Icon(
icon,
size: 50.0,
color: color,
),
SizedBox(
height: 10.0,
),
Text(title,
style: TextStyle(
fontWeight: FontWeight.w500, fontSize: 14.0, color: color)),
SizedBox(
height: 10.0,
),
],
),
),
);
}
}
`
To able to scroll through the section and have unlimited amount of transaction
I think this is what you are going for.
In this snippet, I defined Language as a class with attributes language and rating.
Then I created a list of languages in the stateless widget TheList.
Finally, I used the listView.builder to map the list for its length and display text that shows the attributes of the languages.
Let me know if you have any questions!
import 'package:flutter/material.dart';
class Language {
const Language({this.language,this.rating});
final String language;
final String rating;
}
class TheList extends StatelessWidget {
// Builder methods rely on a set of data, such as a list.
final List<Language> _languages = [
const Language(language: "flutter", rating: "amazing"),
const Language(language: "javascript", rating: "stellar"),
const Language(language: "java", rating: "sucks"),
];
// First, make your build method like normal.
// Instead of returning Widgets, return a method that returns widgets.
// Don't forget to pass in the context!
#override
Widget build(BuildContext context) {
return _buildList(context);
}
// A builder method almost always returns a ListView.
// A ListView is a widget similar to Column or Row.
// It knows whether it needs to be scrollable or not.
// It has a constructor called builder, which it knows will
// work with a List.
ListView _buildList(context) {
return ListView.builder(
// Must have an item count equal to the number of items!
itemCount: _languages.length,
// A callback that will return a widget.
itemBuilder: (context, index) {
// In our case, a Language and its rating for each language in the list.
return Text(_languages[index].language + ": " + _languages[index].rating);
},
);
}
}