How to Automatically Scroll down when expanding ExpansionTile - flutter

I am making my first Flutter App; enjoying it thus far. One annoying thing that I can not quite put my finger on, is that I have some ExpandedTiles, like so:
However, when the tile is expanded, the screen stays in the same position; like so:
What I would like, is if the app is scrolled down aa little bit when the ExpandedView is expanded.
I found this previous question, How to scroll an ExpansionTile / Listview when a tile is expanded? but that is a little different in that it just creates a list of the same items every time. I want the same functionality, but for 3 or 4 unique lists.
Widget build(BuildContext context) {
final title = 'Lunch Menu';
return MaterialApp(
title: title,
home: Scaffold(
appBar: AppBar(
title: Text(title),
),
body:
ListView(
children:
<Widget>[
ListTile(
subtitle: Image.asset('assets/images/lunch-logo.jpg'),
title: ElevatedButton(
child: Text('Back'),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => HomeRoute()),
);
},
),
),
ListTile(
//leading: Image.asset('assets/images/lunch-logo.jpg'),
subtitle: Text('Enjoy our Lunch Options!',
style: TextStyle(
fontSize: 18.0,
color: Colors.blue,
fontWeight: FontWeight.w600,
) ,
textAlign: TextAlign.center ,
),
),
ExpansionTile(
leading: Text(
'Starters',
style: TextStyle(
fontSize: 18.0,
color: Colors.blue,
fontWeight: FontWeight.w600,
),
),
children:<Widget>[ ListTile(
leading: Image.asset('assets/images/food/image1.png'),
title: Text('Title1'),
isThreeLine: true,
subtitle: Text('Description 1') ,
),ListTile(
leading: Image.asset('assets/images/food/image2.png'),
title: Text('Title2'),
isThreeLine: true,
subtitle: Text('Description2') ,
),
Would appreciate if someone can give me a pointer on how to implement the scroll controller correctly.

You can create your own ScrollController and pass it to ListView, then when ExpansionTile expands, use onExpansionChanged to animate the controller and scroll a bit down
class ListViewExample extends StatefulWidget {
ListViewExample({Key key}) : super(key: key);
#override
_ListViewExampleState createState() => _ListViewExampleState();
}
class _ListViewExampleState extends State<ListViewExample> {
final ScrollController scroll = ScrollController();
#override
void dispose() {
scroll.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return ListView(
controller: scroll,
children: [
ListTile(
subtitle: Image.asset('assets/images/lunch-logo.jpg'),
title: ElevatedButton(
child: Text('Back'),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => HomeRoute()),
);
},
),
),
ListTile(
//leading: Image.asset('assets/images/lunch-logo.jpg'),
subtitle: Text('Enjoy our Lunch Options!',
style: TextStyle(
fontSize: 18.0,
color: Colors.blue,
fontWeight: FontWeight.w600,
) ,
textAlign: TextAlign.center ,
),
),
ExpansionTile(
leading: Text(
'Starters',
style: TextStyle(
fontSize: 18.0,
color: Colors.blue,
fontWeight: FontWeight.w600,
),
),
onExpansionChanged: (value) {
if (value)
scroll.animateTo(120, //this is a hardcoded value, would need some tweaking
duration: const Duration(milliseconds: 300),
curve: Curves.linear);
},
children: [
... //Your widgets
],
)
],
);
}
}
onExpansionChanged returns true when its expanding and false when collapsing, you can use those values and check the scroll offset to know if you need to animate the scroll to move downward

try this if you use listview and other scrollable, very helpfully
https://medium.com/flutter-community/flutter-how-to-scroll-an-expansiontile-when-it-is-expanded-ad706cfb80a6

Related

I'm trying to navigate using the bottom bar but i get an error saying (Fix Bottom Overflowed By infinity Pixels) And then the whole app crashes

I've tried to change the child from column to other types but still it didn't work. I'm not sure what's causing the error here but I'm suspecting its the screens[_currentindex] placement. Also when i click on one of the items in the bottom bar. The background color (dark blue) doesn't change to the color of my desired page. but current content disappears.
class _MyStatefulWidgetState extends State<focalPointProfile> {
**int _currentIndex = 0;**
Widget build(BuildContext context) {
**final List<Widget> screens = [
dashboardScreen(),
focalPointProfile(),
mentorRegistrationScreen(), ];**
return Scaffold(
resizeToAvoidBottomInset: false,
endDrawer: drawer(),
appBar: AppBar(
actions: [
Builder(
builder: (context) => IconButton(
icon: Icon((Icons.settings), color: Colors.green,),
onPressed: () => Scaffold.of(context).openEndDrawer(),
tooltip: MaterialLocalizations.of(context).openAppDrawerTooltip,
),
),
],
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
elevation: 1,
),
backgroundColor: Colors.blueGrey[800],
body: SafeArea(
minimum: const EdgeInsets.only(top: 100),
child: Column(
children: <Widget>[
Text(
name,
style: TextStyle(
fontSize: 40.0,
color: Colors.white,
fontWeight: FontWeight.bold,
fontFamily: "Source Sans Pro",
),
),
Text(
position,
style: TextStyle(
fontSize: 30,
color: Colors.blueGrey[200],
letterSpacing: 2.5,
fontWeight: FontWeight.bold,
fontFamily: "Source Sans Pro"),
),
SizedBox(
height: 20,
width: 200,
child: Divider(
color: Colors.white,
),
),
// we will be creating a new widget name info carrd
buildTextField(email, Icons.web),
**screens[_currentIndex],**
],
),
),
**bottomNavigationBar: NavigationBar(
height: 50,
selectedIndex: _currentIndex,
onDestinationSelected: (index) => setState(() => _currentIndex = index),
destinations: const [
NavigationDestination(icon: Icon(Icons.home), label: 'home'),
NavigationDestination(icon: Icon(Icons.person), label: 'profile'),
NavigationDestination(icon: Icon(Icons.add), label: 'Add Mentor'),
],
),**
);
}
class _MyStatefulWidgetState extends State<focalPointProfile>
cant be the same as here
**final List<Widget> screens = [
dashboardScreen(),
focalPointProfile(),
mentorRegistrationScreen(), ];
You can read it here.
https://api.flutter.dev/flutter/widgets/StatefulWidget-class.html

Flutter - Exception Caught by multiple widgets

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

SliverAppBar title doesn't fade if style applied in Flutter

I want to have the title in my SliverAppBar fade in the default way however it stops working once I apply style to the text. You can see how it behave with and without TextStyle. Nothing else changes.
No style
Style applied
Here's the code with style applied:
class FeedScreen extends StatelessWidget {
static const routeName = "/feed_screen";
#override
Widget build(BuildContext context) {
return ViewModelBuilder<WhosHereScreenViewModel>.reactive(
disposeViewModel: false,
initialiseSpecialViewModelsOnce: true,
viewModelBuilder: () => locator<WhosHereScreenViewModel>(),
builder: (context, model, child) {
return Scaffold(
backgroundColor: Colors.white,
body: model.isBusy == true
? Center(child: CircularProgressIndicator())
: CustomScrollView(slivers: [
SliverAppBar(
brightness: Brightness.light,
backgroundColor: Colors.white,
title: Text(
'miit',
style: TextStyle(
fontFamily: 'Changa',
fontWeight: FontWeight.w600,
fontSize: 36.0,
color: Colors.black87),
),
titleSpacing: -4.0,
leading: IconButton(
icon: Image.asset('assets/images/new_logo.png'),
onPressed: () {},
),
floating: true,
actions: [
Padding(
padding: const EdgeInsets.only(right: 12.0),
//TODO build filter functionality
child: IconButton(
icon: Icon(Mdi.accountDetailsOutline,
color: Colors.black87, size: 30.0),
onPressed: null),
)
],
),
Just pass text style not in Text widget in title, but in titleTextStyle.
title: Text('miit'),
titleTextStyle: TextStyle(
fontFamily: 'Changa',
fontWeight: FontWeight.w600,
fontSize: 36.0,
color: Colors.black87),

How to move to different navigation tabs

I am a beginner, just started learning flutter recently and i took a project as a challenge am stuck at this point. I have a separate widget file for my bottom navigator bar, and am using the bottom nav bar in my home screen. so how can i switch to different tabs to display different widgets. My code code below only display's home tab widget which is in the HomeScreen body. Assuming i want to display different widget for each tab how can i achieve that?
//Bottom Navbar widget
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:foodbyte/widgets/PopularFoodsWidget.dart';
class BottomNavBarWidget extends StatefulWidget {
#override
_BottomNavBarWidgetState createState() => _BottomNavBarWidgetState();
}
class _BottomNavBarWidgetState extends State<BottomNavBarWidget> {
int _currentIndex = 0;
#override
Widget build(BuildContext context) {
return BottomNavigationBar(
currentIndex: _currentIndex,
selectedItemColor: Colors.lightBlue,
type: BottomNavigationBarType.fixed,
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
title: Text(
'Home',
),
backgroundColor: Colors.blueAccent,
),
BottomNavigationBarItem(
icon: Icon(Icons.search),
title: Text(
'Search',
),
backgroundColor: Colors.blueAccent,
),
BottomNavigationBarItem(
icon: Icon(Icons.shopping_basket),
title: Text(
'Orders',
),
backgroundColor: Colors.blueAccent,
),
BottomNavigationBarItem(
icon: Icon(FontAwesomeIcons.user),
title: Text(
'Account',
),
backgroundColor: Colors.blueAccent,
),
],
onTap: (index) {
setState(() {
_currentIndex = index;
});
},
);
}
}
//HomeScreen
//This is my homescreen where am using the bottom nav bar widget
import 'package:flutter/material.dart';
import 'package:foodbyte/screens/categories.dart';
import 'package:foodbyte/widgets/top_menus.dart';
import 'package:foodbyte/widgets/BottomNavBarWidget.dart';
class Home extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Color(0xFFFAFAFA),
elevation: 0,
title: Text(
"Welcome to my prototype app!",
style: TextStyle(
color: Color(0xFF3a3737),
fontSize: 16,
fontWeight: FontWeight.w500),
),
brightness: Brightness.light,
actions: <Widget>[
IconButton(
icon: Icon(
Icons.notifications_none,
color: Color(0xFF3a3737),
),
onPressed: () {
// Navigator.push(context, ScaleRoute(page: SignInPage()));
})
],
),
// appBar: buildSearchBar(context),
body: Padding(
padding: const EdgeInsets.fromLTRB(10.0, 0, 10.0, 0),
child: ListView(
children: <Widget>[
buildCategoryRow('Bottom Nav', context),
SizedBox(height: 10.0),
TopMenus(),
],
),
),
bottomNavigationBar: BottomNavBarWidget(),
);
}
buildCategoryRow(String category, BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
"$category",
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.w800,
),
),
FlatButton(
child: Text(
"See all (9)",
style: TextStyle(
color: Theme.of(context).accentColor,
),
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) {
return Categories();
},
),
);
},
),
],
);
}
}
You can create list of screens or widgets as you like.
List _widgets[Widget1,Widget2,Widget3];
since you have _currentIndex, you can use it to show your desired screen in scafold body.
Scafold:...
body:_widgets[_currentIndex]
Your logic is wrong
you are using the bottom navigation bar on the home screen that is no a good way.
What you need is to use the Scaffold widget in the bottom nav bar class and pass the Indexed Stack widget to the body of its scaffold and use the children parameter of IndexStack and paste your Screens Names inside children widget.
and pass your bottom navigation bar widget to the bottom navigation bar parameter of this scaffold.

Flutter ListView itembuilder won't show anything. Why?

I wanted to display multiple ListTiles using the ListView.itembuilder in Flutter. I did it, but the screen is still blank. Tried hot reloading as well as running the app twice. What's wrong in the code?
P.S: The List is going to appear in my TabBarView that I created earlier. Also posting the snipper of the TabBarView.
ListView code:
class SportBets extends StatefulWidget {
#override
_SportBetsState createState() => _SportBetsState();
}
class _SportBetsState extends State<SportBets> {
final sportList = [
"Basketball",
"Football",
"Volleyball",
];
#override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: sportList.length,
itemBuilder: (context, index){
ListTile(
title: Text(sportList[index], style: TextStyle(fontSize: 20.0, color: Colors.black),),
trailing: IconButton(
icon: Icon(Icons.arrow_forward_ios),
color: Colors.blue,
onPressed: (){}
),
leading: CircleAvatar(child: Icon(Icons.wb_sunny),radius: 18.0,),
);
}
);
}
}
TabBarView Code:
body: TabBarView(
children: <Widget>[
Center(
child: Text(
"Highlights Page here",
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20),
),
),
Center(
child: Text(
"Casino Page here",
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20),
),
),
Center(
child: Text(
"Promotions Page here",
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20),
),
),
SportBets(),
],
),
Some errors you need to fix
Add a `return` statement in the `itemBuilder` of `ListView`
Wrap your `TabBarView` with a `DefaultTabContoller` and set `DefaultTabContoller`'s length as 4 as you have 4 tabs.