BottomNavigationBar page change causing StreamBuilder data reload - flutter

Inside BottomNavigation I have 2 page. 1st Page loading data from the network and showing in SliverList and In another page showing static list data.
After moving from 1st to 2nd page then 1st page all network data are gone. I have used PageStorageKey but still, it's not working. but the 2nd page never reloaded.
Why is 1st page not saving its state which has StreamBuilder?
My code:
Bottom Navigation Page:
class MainActivity extends StatefulWidget {
#override
_MainActivityState createState() => _MainActivityState();
}
class _MainActivityState extends State<MainActivity> {
final Key keyHome = PageStorageKey('pageHome');
final Key keyChat = PageStorageKey('pageChat');
int currentTab = 0;
HomePage home;
Chat chat;
List<Widget> pages;
Widget currentPage;
final PageStorageBucket bucket = PageStorageBucket();
#override
void initState(){
home = HomePage(
key: keyHome,
);
chat = Chat(
key: keyChat,
);
pages = [home, chat];
currentPage = home;
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: PageStorage(
child: currentPage,
bucket: bucket,),
//Bottom Navigation Bar added
bottomNavigationBar: BottomNavigationBar(
currentIndex: currentTab,
onTap: (int index){
setState(() {
currentTab = index;
currentPage = pages[index];
});
},
type: BottomNavigationBarType.fixed,
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(icon: Icon(Icons.home), title: Text('Home')),
BottomNavigationBarItem(icon: Icon(Icons.chat), title: Text('Chat')),
BottomNavigationBarItem(
icon: Icon(Icons.payment), title: Text('Pay')),
BottomNavigationBarItem(
icon: Icon(Icons.account_circle), title: Text('Me')),
],
//currentIndex: _selectedIndex,
fixedColor: Colors.deepPurple,
),
);
}
}
Home Page:
class HomePage extends StatefulWidget {
HomePage({
Key key,
}) : super(key: key);
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage>{
#override
Widget build(BuildContext context) {
final NewsCatalogBlog newsBloc = BlocProvider.of<NewsCatalogBlog>(context);
//bloc.fetchAllNews();
return Scaffold(
appBar: PreferredSize(child: HomePageGradientAppBar(),
preferredSize: const Size.fromHeight(100.0),),
body: StreamBuilder(
stream: newsBloc.outNewsList,
builder: (context, AsyncSnapshot<List<Data>> snapshot) {
Widget newsList;
newsList = new SliverList(
delegate: new SliverChildBuilderDelegate((context,index){
print("$index");
return NewsListRow(snapshot.data, newsBloc, index);
},
childCount: (snapshot.data == null ? 0 : snapshot.data.length) + 30),
);
return new CustomScrollView(
slivers: <Widget>[
SliverToBoxAdapter(child: TabPanel(),),
SliverToBoxAdapter(child: UrlButtonPanel(),),
SliverToBoxAdapter(child: ChatNowAd(),),
newsList,
],
);
},
),
);
}
}
Chat Page:
class Chat extends StatelessWidget {
Chat({
Key key,
}): super (key: key);
#override
Widget build(BuildContext context) {
return ListView.builder(
itemExtent: 250.0,
itemCount: 20,
itemBuilder: (context, index) => Container(
padding: EdgeInsets.all(10.0),
child: Material(
elevation: 4.0,
borderRadius: BorderRadius.circular(5.0),
color: index % 2 == 0 ? Colors.cyan : Colors.deepOrange,
child: Center(
child: Text('Mir{$index}'),
),
),
),
);
}
}

Better way is to use IndexedStack instead of PageStorage or AutomaticKeepAliveClientMixin.
class _MainActivityState extends State<MainActivity> {
int _selectedPage = 0;
List<Widget> pageList = List<Widget>();
#override
void initState() {
pageList.add(HomePage());
pageList.add(ChatPage());
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: IndexedStack(
index: _selectedPage,
children: pageList,
),
//Bottom Navigation Bar added
bottomNavigationBar: BottomNavigationBar(
.....
**IndexedStack Widget is sub-class of Stack Widget
It shows single child from list of provided Childs.
Its size as big as largest child.
It keep state of all Childs.**

Related

Why doesn't BottomNavigatorBarItem currentIndex get updated?

I am new to flutter and I did find similar questions on SO but am too novice to understand the nuance so apologies if this question is too similar to an already asked one.
I have a BottomNavigationBar which has 3 icons (Home, Play and Create) which should navigate between these 3 routes/pages.
main.dart
routes: {
"/home": (context) => MyHomePage(title: "STFU"),
"/play": (context) => Play(),
"/create": (context) => Create(),
"/settings": (context) => Settings(),
},
I extracted my navbar into a custom class so my 3 separate pages could use it:
bottom-nav.dart
class MyBottomNavBar extends StatefulWidget {
MyBottomNavBar({
Key? key,
}) : super(key: key);
#override
State<MyBottomNavBar> createState() => _MyBottomNavBarState();
}
class _MyBottomNavBarState extends State<MyBottomNavBar> {
int _selectedIndex = 0;
void _onTapped(int index) => {
print("_onTapped called with index = $index"),
setState(
() => _selectedIndex = index,
)
};
#override
Widget build(BuildContext context) {
return BottomNavigationBar(
backgroundColor: Colors.orangeAccent[100],
currentIndex: _selectedIndex,
onTap: (value) => {
print("value is $value"),
// find index and push that
_onTapped(value),
if (value == 0)
{Navigator.pushNamed(context, "/home")}
else if (value == 1)
{Navigator.pushNamed(context, "/play")}
else if (value == 2)
{Navigator.pushNamed(context, "/create")}
},
items: [
BottomNavigationBarItem(label: "Home", icon: Icon(Icons.home_filled)),
BottomNavigationBarItem(
label: "Play", icon: Icon(Icons.play_arrow_rounded)),
BottomNavigationBarItem(label: "Create", icon: Icon(Icons.create)),
],
);
}
}
so now i just set this MyBottomNavBar class to the bottomNavigationBar property of the Scaffold widget my inside Home page, Play page and Create page for eg.
home.dart
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Home"),
),
body: Column(
children: [
Container(
padding: EdgeInsets.all(20.00),
child: Text("inside home"),
),
],
),
bottomNavigationBar: MyBottomNavBar(),
);
}
}
play.dart
class Play extends StatefulWidget {
const Play({super.key});
#override
State<Play> createState() => _PlayState();
}
class _PlayState extends State<Play> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text("inside play page"),
SizedBox(
height: 30.00,
),
Text("some text"),
],
),
),
bottomNavigationBar: MyBottomNavBar(),
);
}
}
The nav bar buttons work to switch between pages but for some reason the currentIndex value isn't getting updated and stays at 0 (i.e on the "Home" icon). When I debug it I can see _selectedIndex getting updated inside inside the _onTapped function which should update the currentIndex value but it doesn't appear to do so. Any help would be appreciated
What you have here is three different pages with their separate BottomNavBar class instance. Instead you should have a shared Scaffold and one bottomNavBar so that when you navigate bottomNavbar state does not reset.
You can use PageView to do this.
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
void initState() {
super.initState();
}
List<Widget> pages = const [Home(), Play(), Create()];
final _pageController = PageController();
int _selectedIndex = 0;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
bottomNavigationBar: BottomNavigationBar(
currentIndex: _selectedIndex,
onTap: (index) {
_pageController.jumpToPage(index);
_selectedIndex = index;
setState(() {});
},
items: const [
BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Home'),
BottomNavigationBarItem(icon: Icon(Icons.play_arrow), label: 'Play'),
BottomNavigationBarItem(icon: Icon(Icons.create), label: 'Create'),
],
backgroundColor: Colors.greenAccent,
),
body: PageView(
controller: _pageController,
children: pages,
),
);
}
}
class Home extends StatelessWidget {
const Home({super.key});
#override
Widget build(BuildContext context) {
return const Placeholder();
}
}
class Play extends StatelessWidget {
const Play({super.key});
#override
Widget build(BuildContext context) {
return const Placeholder();
}
}
class Create extends StatelessWidget {
const Create({super.key});
#override
Widget build(BuildContext context) {
return const Placeholder();
}
}

How to show navigation bar on page which doesn't belong to this bar?

edit: SOLUTION
i used package custom_navigator
In navigation bar I have 2 pages to redirect, but I want to navigate to third page and still want to see navigation bar (this one with 2 pages) there.
Is it possible to do? Do I have to make my own navigation bar for this page?
class Bar extends StatefulWidget {
#override
BarState createState() => BarState();
}
class BarState extends State<Bar> {
int tabIndex = 0;
List<Widget> pages = [
FirstPage(),
SecondPage(),
];
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: PreferredSize(
preferredSize: Size.fromHeight(kToolbarHeight),
child: SafeArea(
child: BottomNavigationBar(
iconSize: 25,
elevation: 4.0,
items: <BottomNavigationBarItem>[
barItem(Icons.message),
barItem(Icons.camera_enhance),
barItem(Icons.person),
],
currentIndex: tabIndex,
onTap: (int index) {
setState(() {
tabIndex = index;
});
},
),
)),
body: Container(
child: pages.elementAt(tabIndex),
),
);
}
}
this is what i try:
List<Widget> pages = [
Container(
color: Colors.green,
child: Center(
child: ElevatedButton(
onPressed: state
),
),
),
SecondPage(),
ThirdPage()
];
state() {
tabIndex = 2;
setState(() {
});
}
The simplest way, if you don't mind it animating would be to init an AppBar in your navigator and pass it to the pages and they would use it in there scaffold.
class MyFlow extends StatefulWidget {
const MyFlow({Key? key}) : super(key: key);
#override
_MyFlowState createState() => _MyFlowState();
}
class _MyFlowState extends State<MyFlow> {
#override
Widget build(BuildContext context) {
final appBar = AppBar();
return Navigator(
onPopPage: (route, result) => true,
pages: [
MaterialPage(child: PageOne(appBar: appBar)),
MaterialPage(child: PageTwo(appBar: appBar)),
MaterialPage(child: PageThree(appBar: appBar)),
],
);
}
}
class PageOne extends StatelessWidget {
const PageOne({Key? key, required this.appBar}) : super(key: key);
final AppBar appBar;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: appBar,
);
}
}

Flutter: Child Widget's looses state when parent's sate changes

I am learning Flutter and struggling with some state management issue.
I have a HomeScreen widget which contains Scaffold and a BottomNavigationBar. To switch pages based on the selected tab in BottomNavigationBar I am using PageView with PageController. Here is how the build method of HomeScreen widget looks:
#override
Widget build(BuildContext context) {
return Scaffold(
extendBodyBehindAppBar: _currentIndex == 2,
appBar: AppBar(...properties),
body: PageView(
controller: _pageController,
children: _pages,
),
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[...items],
currentIndex: _currentIndex,
onTap: _onItemTapped, //This changes state _currentIndex and calls the method _pageController.jumpToPage(_currentIndex);
),
);
}
_currentIndex initially is 0.
_pages is a list containing 3 widgets.
_pageController is simple PageController with initialPage set to 0.
If you notice I am using a property extendBodyBehindAppBar: _currentIndex == 2 which is using _currentIndex state and this is causing issue.
When I tap on the last Tab on the BottomNavigationBar the state the _currentIndex changes to 2 and thus the extendBodyBehindAppBar is set as true which makes entire Scaffold rebuild itself and the state of the PageView is lost.
If comment out the line extendBodyBehindAppBar: _currentIndex == 2, then even if the Scaffold rebuilds the state of the PageView widget is preserved.
As of my understanding the Flutter should keep the state of child Widgets even if the parent rebuilds because the WidgetTree is not changed or re-arranged. I tried using Key on PageView but nothing worked.
Any help is very much appreciated.
refer to Lucas Salton Cardinali post on medium
you need to use PageStorage to persit the state of the child you need after being destroyed.
here the example retrieved from the same page:
import 'package:flutter/material.dart';
// ...
void main() => runApp(MyApp());
// ...
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final List<Widget> pages = <Widget>[
ColorBoxPage(
key: PageStorageKey('pageOne'),
),
ColorBoxPage(
key: PageStorageKey('pageTwo'),
)
];
int currentTab = 0;
final PageStorageBucket _bucket = PageStorageBucket();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Persistence Example"),
),
body: PageStorage(
child: pages[currentTab],
bucket: _bucket,
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: currentTab,
onTap: (int index) {
setState(() {
currentTab = index;
});
},
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'page 1',
),
BottomNavigationBarItem(
icon: Icon(Icons.settings),
label: 'page2',
),
],
),
);
}
}
class ColorBoxPage extends StatelessWidget {
ColorBoxPage({
Key? key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return ListView.builder(
itemExtent: 250.0,
itemBuilder: (context, index) => Container(
padding: EdgeInsets.all(10.0),
child: Material(
color: index % 2 == 0 ? Colors.cyan : Colors.deepOrange,
child: Center(
child: Text(index.toString()),
),
),
),
);
}
}

Flutter: Nested routing with persistent BottomNavigationBar but without building the unselected pages unnecessarily

Throughout the internet and stackoverflow I've searched and seen a lot of solutions to the problem of nested navigation with a persistent BottomNavigationBar for Flutter apps. Some of them using Navigators with IndexedStack or PageView and so on and so forth. All of them work just fine except that they will unnecessarily build the unselected tabs (sometimes even rebuilding all of them every time you switch tabs) thus making the solution not performatic. I did finally come up with a solution to that – as I was struggling with this problem myself.
The solution is very basic but hopefully you will be able to build upon it and adapt it. It achieves the following:
nests navigation while persisting the BottomNavigationBar
does not build a tab unless it has been selected
preserves the navigation state
preserves the scroll state (of a ListView, for example)
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
home: MyApp(),
));
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
List<Widget> _pages;
List<BottomNavigationBarItem> _items = [
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: "Home",
),
BottomNavigationBarItem(
icon: Icon(Icons.messenger_rounded),
label: "Messages",
),
BottomNavigationBarItem(
icon: Icon(Icons.settings),
label: "Settings",
)
];
int _selectedPage;
#override
void initState() {
super.initState();
_selectedPage = 0;
_pages = [
MyPage(
1,
"Page 01",
MyKeys.getKeys().elementAt(0),
),
// This avoid the other pages to be built unnecessarily
SizedBox(),
SizedBox(),
];
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: WillPopScope(
onWillPop: () async {
return !await Navigator.maybePop(
MyKeys.getKeys()[_selectedPage].currentState.context,
);
},
child: IndexedStack(
index: _selectedPage,
children: _pages,
),
),
bottomNavigationBar: BottomNavigationBar(
items: _items,
currentIndex: _selectedPage,
onTap: (index) {
setState(() {
// now check if the chosen page has already been built
// if it hasn't, then it still is a SizedBox
if (_pages[index] is SizedBox) {
if (index == 1) {
_pages[index] = MyPage(
1,
"Page 02",
MyKeys.getKeys().elementAt(index),
);
} else {
_pages[index] = MyPage(
1,
"Page 03",
MyKeys.getKeys().elementAt(index),
);
}
}
_selectedPage = index;
});
},
),
);
}
}
class MyPage extends StatelessWidget {
MyPage(this.count, this.text, this.navigatorKey);
final count;
final text;
final navigatorKey;
#override
Widget build(BuildContext context) {
// You'll see that it will only print once
print("Building $text with count: $count");
return Navigator(
key: navigatorKey,
onGenerateRoute: (RouteSettings settings) {
return MaterialPageRoute(
builder: (BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(this.text),
),
body: Center(
child: RaisedButton(
child: Text(this.count.toString()),
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (ctx) => MyCustomPage(count + 1, text)));
},
),
),
);
},
);
},
);
}
}
class MyCustomPage extends StatelessWidget {
MyCustomPage(this.count, this.text);
final count;
final text;
#override
Widget build(BuildContext parentContext) {
return Scaffold(
appBar: AppBar(
title: Text(this.text),
),
body: Column(
children: [
Expanded(
child: Container(
child: ListView.builder(
itemCount: 15,
itemBuilder: (context, index) {
return Container(
width: double.infinity,
child: Card(
child: Center(
child: RaisedButton(
child: Text(this.count.toString() + " pos($index)"),
onPressed: () {
Navigator.of(parentContext).push(MaterialPageRoute(
builder: (ctx) =>
MyCustomPage(count + 1, text)));
},
),
),
),
);
},
),
),
),
],
),
);
}
}
class MyKeys {
static final first = GlobalKey(debugLabel: 'page1');
static final second = GlobalKey(debugLabel: 'page2');
static final third = GlobalKey(debugLabel: 'page3');
static List<GlobalKey> getKeys() => [first, second, third];
}

Flutter Setstate called multiple times (GestureDetector & PageView)

basically I have a swiping screen with elements, where user is able to swipe in left or right direction. When the user is swiping, im calling some functions. Im using GestureDetector for gesture recognitions and PageView.Custom for my items. Probably ListView.Custom does also work, but it doesn't fix my issue I have.
I need a PageController, because I have to control the navigation programatically. And I think the PageController maybe is the reason behind my issue that my functions are called multiple times. How to fix it? Does somebody know why setstate is called that often and what to do to prevent it?
Im providing you a fully working example (minified version) with a print on the swiping right actions, where you can see that its beeing called multiple times.
import 'package:flutter/gestures.dart';
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(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int currentIndex = 0;
#override
Widget build(BuildContext context) {
// Page selector for tab list
void _selectPage(int index) {
print('page index: $index');
setState(() {
currentIndex = index;
});
}
// Routes list for tab navigation Android
final List<Widget> _pages = [
ScreenA(),
ScreenB(func: _selectPage),
];
return Scaffold(
appBar: AppBar(),
body: _pages[currentIndex],
bottomNavigationBar: SafeArea(
child: BottomNavigationBar(
onTap: _selectPage,
iconSize: 22,
currentIndex: currentIndex,
type: BottomNavigationBarType.fixed,
items: [
BottomNavigationBarItem(
backgroundColor: Theme.of(context).primaryColor,
icon: Icon(Icons.description),
label: 'ScreenA',
),
BottomNavigationBarItem(
backgroundColor: Theme.of(context).primaryColor,
icon: Icon(Icons.ac_unit_outlined),
label: 'ScreenB'),
],
),
),
);
}
}
class ScreenA extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
child: Text('HOME'),
);
}
}
class ScreenB extends StatefulWidget {
Function func;
ScreenB({Key key, #required this.func})
: super(key: key);
#override
_ScreenBState createState() => _ScreenBState();
}
class _ScreenBState extends State<ScreenB> {
_ScreenBState();
var _controller = PageController();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: [
IconButton(
icon: Icon(Icons.access_alarm_sharp),
onPressed: () async {
widget.func(0);
},
),
],
),
body: PageView.custom(
dragStartBehavior: DragStartBehavior.start,
controller: _controller,
physics: NeverScrollableScrollPhysics(),
scrollDirection: Axis.horizontal,
childrenDelegate: SliverChildBuilderDelegate((ctx, pageIndex) =>
GestureDetector(
onPanUpdate: (details) async {
if (details.delta.dx < 0) {
_controller.nextPage(
duration: Duration(milliseconds: 200),
curve: Curves.easeInOut);
print('function called');
}
},
child: Center(
child: Container(
width: 200,
height: 200,
color: Colors.red,
child: Text('hi')))))),
);
}
}
Thanks in advance!
The problem is that you are using the onPanUpdate method, which is triggered every time a user drags their finger either right or left. You should use the onPanEnd method, which is only triggered when the user's finger is off the screen after dragging either left or right. The function below will work fine.
onPanEnd: (details) async { if (details.velocity.pixelsPerSecond.dx < 0) { _controller.nextPage( duration: Duration(milliseconds: 200), curve: Curves.easeInOut); print('function called'); } }
Please write this function out of widget build function
// Page selector for tab list
void _selectPage(int index) {
print('page index: $index');
setState(() {
currentIndex = index;
});
}
like this
import 'package:flutter/gestures.dart';
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(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int currentIndex = 0;
// Page selector for tab list
void _selectPage(int index) {
print('page index: $index');
setState(() {
currentIndex = index;
});
}
// Routes list for tab navigation Android
final List<Widget> _pages = [
ScreenA(),
ScreenB(func: _selectPage),
];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: _pages[currentIndex],
bottomNavigationBar: SafeArea(
child: BottomNavigationBar(
onTap: _selectPage,
iconSize: 22,
currentIndex: currentIndex,
type: BottomNavigationBarType.fixed,
items: [
BottomNavigationBarItem(
backgroundColor: Theme.of(context).primaryColor,
icon: Icon(Icons.description),
label: 'ScreenA',
),
BottomNavigationBarItem(
backgroundColor: Theme.of(context).primaryColor,
icon: Icon(Icons.ac_unit_outlined),
label: 'ScreenB'),
],
),
),
);
}
}
class ScreenA extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
child: Text('HOME'),
);
}
}
class ScreenB extends StatefulWidget {
Function func;
ScreenB({Key key, #required this.func})
: super(key: key);
#override
_ScreenBState createState() => _ScreenBState();
}
class _ScreenBState extends State<ScreenB> {
_ScreenBState();
var _controller = PageController();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: [
IconButton(
icon: Icon(Icons.access_alarm_sharp),
onPressed: () async {
widget.func(0);
},
),
],
),
body: PageView.custom(
dragStartBehavior: DragStartBehavior.start,
controller: _controller,
physics: NeverScrollableScrollPhysics(),
scrollDirection: Axis.horizontal,
childrenDelegate: SliverChildBuilderDelegate((ctx, pageIndex) =>
GestureDetector(
onPanUpdate: (details) async {
if (details.delta.dx < 0) {
_controller.nextPage(
duration: Duration(milliseconds: 200),
curve: Curves.easeInOut);
print('function called');
}
},
child: Center(
child: Container(
width: 200,
height: 200,
color: Colors.red,
child: Text('hi')))))),
);
}
}