Reputation: 5884
I have a PageView
used with a BottomNavigationBar
so that I can have swipeable and tappable tabs with a bottom bar rather than the normal navigation bar. Then I have two tabs/pages you can swipe between. One has a form with 4 UI elements and the other has no UI elements yet. Everything works fine but the performance of the PageView
is very bad.
When I swipe between pages it is extremely slow and jumpy at first, definitely not the 60 frames per second promised by Flutter. Probably not even 30. After swiping several times though the performance gets better and better until its almost like a normal native app.
Below is my page class that includes the PageView
, BottomNavigationBar
, and logic connecting them. does anyone know how I can improve the performance of the PageView
?
class _TabbarPageState extends State<TabbarPage> {
int _index = 0;
final controller = PageController(
initialPage: 0,
keepPage: true,
);
final _tabPages = <Widget>[
StartPage(),
OtherPage(),
];
final _tabs = <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.play_arrow),
title: Text('Start'),
),
BottomNavigationBarItem(
icon: Icon(Icons.accessibility_new),
title: Text('Other'),
)
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: PageView(
controller: controller,
children: _tabPages,
onPageChanged: _onPageChanged,
),
bottomNavigationBar: BottomNavigationBar(
items: _tabs,
onTap: _onTabTapped,
currentIndex: _index,
),
floatingActionButton: _index != 1
? null
: FloatingActionButton(
onPressed: () {},
tooltip: 'Test',
child: Icon(Icons.add),
),
);
}
void _onTabTapped(int index) {
controller.animateToPage(
index,
duration: Duration(milliseconds: 300),
curve: Curves.ease,
);
setState(() {
_index = index;
});
}
void _onPageChanged(int index) {
setState(() {
_index = index;
});
}
}
Upvotes: 8
Views: 4731
Reputation: 31
Try this hack, Apply viewportFraction to your controller with value 0.99(it can be 0.999 or 0.9999 hit and try until you get desired result)
final controller = PageController(
viewportFraction: 0.99 );
Upvotes: 3
Reputation: 95
I am new to flutter, please tell me if this is wrong.
Have the same problem, here is my effort. Wors for me.
class HomePage extends StatefulWidget {
@override
State createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
var _currentIndex = 1;
var _pageController = PageController(initialPage: 1);
var _todoPage, _inProgressPage, _donePage, _userPage;
@override
void initState() {
this._currentIndex = 1;
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: PageView.builder(
controller: this._pageController,
onPageChanged: (index) {
setState(() {
this._currentIndex = index.clamp(0, 3);
});
},
itemCount: 4,
itemBuilder: (context, index) {
if (index == 0) return this.todoPage();
if (index == 1) return this.inProgressPage();
if (index == 2) return this.donePage();
if (index == 3) return this.userPage();
return null;
},
),
bottomNavigationBar: buildBottomNavigationBar(),
);
}
Widget buildBottomNavigationBar() {
return BottomNavigationBar(
showUnselectedLabels: false,
items: [
BottomNavigationBarItem(title: Text("待办"), icon: Icon(Icons.assignment)),
BottomNavigationBarItem(title: Text("进行"), icon: Icon(Icons.blur_on)),
BottomNavigationBarItem(title: Text("完成"), icon: Icon(Icons.date_range)),
BottomNavigationBarItem(title: Text("我的"), icon: Icon(Icons.account_circle)),
],
currentIndex: this._currentIndex,
onTap: (index) {
setState(() {
this._currentIndex = index.clamp(0, 3);
});
_pageController.jumpToPage(this._currentIndex);
},
);
}
Widget todoPage() {
if (this._todoPage == null) this._todoPage = TodoPage();
return this._todoPage;
}
Widget inProgressPage() {
if (this._inProgressPage == null) this._inProgressPage = InProgressPage();
return this._inProgressPage;
}
Widget donePage() {
if (this._donePage == null) this._donePage = DonePage();
return this._donePage;
}
Widget userPage() {
if (this._userPage == null) this._userPage = UserPage();
return this._userPage;
}
}
I just cache the pages that pageview hold. this REALLY smooth my pageview a lot, like native. but would prevent hotreload (ref: How to deal with unwanted widget build?),.
Upvotes: 0
Reputation: 1115
Sorry but Günter's answer didn't helped me! You have to set physics: AlwaysScrollableScrollPhysics() And your performance increases.
Worked for me 👍
Upvotes: 3
Reputation: 657288
Ensure you performance test with profile or release builds only. Evaluating performance with debug builds is completely meaningless.
Upvotes: 3