-
Notifications
You must be signed in to change notification settings - Fork 56
injected_tab_page_view_api
GIfatahTH edited this page Oct 2, 2021
·
1 revision
In Flutter to work with scrollable view, you use:
-
TabBarView
,TabBar
,TabController
andDefaultTabController
, or -
PageView
andpageController
.
InjectedTabPageView
state encapsulates the functionality of TabController and pageController to control tab and page views.
InjectedTabPageView injectTabPageView({
required int length,
int initialIndex = 0,
Duration duration = kTabScrollDuration,
Curve curve = Curves.ease,
bool keepPage = true,
double viewportFraction = 1.0,
})
-
length
: The number of tabs / pages to display. It can be dynamically changes later.// We start with 2 tabs final myInjectedTabPageView = RM.injectedTabPageView(length: 2); // Later on, we can extend or shrink the length of tab views. // Tab/page views are updated to display three views myInjectedTabPageView.length = 3 // Tab/page views are updated to display one view myInjectedTabPageView.length = 1
-
initialIndex
: The index of the tab / page to start with. -
duration
: The duration the tab / page transition takes. -
curve
: The duration the tab / page transition takes. -
keepPage
: Save the current page withPageStorage
and restore it if this controller's scrollable is recreated. It works only forPageView
not tabs -
viewportFraction
: The fraction of the viewport that each page should occupy. It works only forPageView
not tabs
InjectedTabPageView exposes the following api:
-
tabController
: get the associatedTabController
. -
pageController
: get the associatedPageController
. -
index
: get the current index of the active tab/page. When theindex
is set, The tab / page will animate to the target index. -
length
: get and dynamically set the length of views -
previousIndex
: The index of the previously selected tab / page. -
indexIsChanging
: True while we're animating frompreviousIndex
toindex
as a consequence of callinganimateTo
. -
animateTo
method:Immediately sets index andvoid animateTo( int index, { Duration duration = kTabScrollDuration, Curve curve = Curves.ease, })
previousIndex
and then plays the animation from its current value toindex
. -
nextView
method:Animates the controlled pages/tabs to the next page/tabvoid nextView()
-
previousView
method:Animates the controlled pages/tabs to the previous page/tabvoid previousView()
To listen to an InjectedTabPageView
, we use OnTabPageViewBuilder
:
OnTabPageViewBuilder({
// Optional, In most cases it can be omitted
listenTo: myInjectedTabPageView,
builder: (int currentIndex) {
return TabView( ... )
},
})
By default, OnTabPageBuilder
deduces the InjectedTabPageView
it must listen to. So listenTo parameter is optional.
The builder method exposes the currentIndex of the active tab / page.
First we define our injectedTabPage
final injectedTabPage = RM.injectTabPageView(
length: 3,
//Optional
initialIndex: 0,
curve: Curves.ease,
duration: Duration(milliseconds: 300),
viewportFraction: 1.0,
keepPage: true,
);
/// List of DataIcon to be used in pages an tabs
final icons = [
Icons.directions_car,
Icons.directions_transit,
Icons.directions_bike,
Icons.directions_boat,
Icons.directions_bus_filled,
];
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
// Display the active index
title: OnReactive(
() => Text(
'Page ${injectedTabPage.index} is displayed',
),
),
bottom: PreferredSize(
preferredSize: Size(0, 40),
child: Row(
children: [
IconButton(
onPressed: () {
// Go to the previous view
injectedTabPage.previousView();
},
icon: Icon(Icons.arrow_back_ios_rounded),
),
IconButton(
onPressed: () {
// Go to the next view
injectedTabPage.nextView();
},
icon: Icon(Icons.arrow_forward_ios_rounded),
),
Spacer(),
IconButton(
onPressed: () {
// Dynamically shrink the number of tabs / pages
if (injectedTabPage.length > 1) injectedTabPage.length--;
},
icon: Icon(Icons.cancel),
),
IconButton(
onPressed: () {
// Dynamically extend the number of tabs / pages
if (injectedTabPage.length < icons.length)
injectedTabPage.length++;
injectedTabPage.animateTo(injectedTabPage.length - 1);
},
icon: Icon(Icons.add_circle),
),
],
),
),
),
// In the body and the bottomNavigationBar we can use Tabs only or pages only or use both.
// The above code remains unchangeable.
body: _body() ,
bottomNavigationBar: _bottomNavigationBar(),
),
);
}
}
Here we use TabBarView
and TabBar
controlled by TabController
.
Widget _body(){
return OnTabPageViewBuilder(
builder: (_) => TabBarView(
controller: injectedTabPage.tabController,
children: icons
.getRange(0, injectedTabPage.length)
.map((icon) => Icon(icon, size: 50))
.toList(),
),
)
}
Widget __bottomNavigationBar(){
return OnTabPageViewBuilder(
builder: (index) {
return TabBar(
controller: injectedTabPage.tabController,
tabs: icons
.getRange(0, injectedTabPage.length)
.map((icon) => Icon(icon, color: Colors.blue))
.toList(),
);
},
),
}
Here we use PageView
controlled with a list of OutlinedButton
.
Widget _body(){
return OnTabPageViewBuilder(
builder: (_) => PageView.builder(
controller: injectedTabPage.pageController,
itemCount: injectedTabPage.length,
itemBuilder: (_, i) {
return Icon(
icons[i],
size: 50,
);
},
),
)
}
Widget __bottomNavigationBar(){
return OnTabPageViewBuilder(
listenTo: injectedTabPage,
builder: (index) {
return Row(
children: icons
.getRange(0, injectedTabPage.length)
.toList()
.asMap()
.map((i, icon) {
return MapEntry(
i,
OutlinedButton(
onPressed: () => injectedTabPage.index = i,
child: Transform.scale(
scale: animate(i == index ? 1.2 : 0.8, '$i')!,
child: Icon(icon),
),
style: OutlinedButton.styleFrom(
backgroundColor:
animate(i == index ? Colors.blue : null, '$i'),
primary: animate(
i != index ? Colors.blue : Colors.white,
'primary$i'),
),
),
);
})
.values
.toList(),
mainAxisAlignment: MainAxisAlignment.center,
);
},
),
}
Here we use PageView
controlled by TabBar
.
Widget _body(){
return OnTabPageViewBuilder(
builder: (_) => PageView.builder(
controller: injectedTabPage.pageController,
itemCount: injectedTabPage.length,
itemBuilder: (_, i) {
return Icon(
icons[i],
size: 50,
);
},
),
)
}
Widget __bottomNavigationBar(){
return OnTabPageViewBuilder(
builder: (index) {
return TabBar(
controller: injectedTabPage.tabController,
tabs: icons
.getRange(0, injectedTabPage.length)
.map((icon) => Icon(icon, color: Colors.blue))
.toList(),
);
},
),
}
Here we use PageView
controlled by TabBar
.
Widget _body(){
return OnTabPageViewBuilder(
builder: (_) => PageView.builder(
controller: injectedTabPage.pageController,
itemCount: injectedTabPage.length,
itemBuilder: (_, i) {
return Icon(
icons[i],
size: 50,
);
},
),
)
}
Widget __bottomNavigationBar(){
return OnTabPageViewBuilder(
listenTo: injectedTabPage,
builder: (index) {
return BottomNavigationBar(
currentIndex: index,
onTap: (i)=> injectedTabPage.index = i,
selectedItemColor: Colors.amber[800],
tabs: icons
.getRange(0, injectedTabPage.length)
.map((icon) =>
BottomNavigationBarItem(
icon: Icon(icon),
)
,)
.toList(),
);
},
),
}