How to navigate to another tab from TabBarView page flutter - flutter

I have a page HomePageScreen() and it has a TabBarView with four different pages.
TabBarView(
physics: NeverScrollableScrollPhysics(),
controller: _tabController,
children: <Widget>[
PageOneScreen(),
PageTwoScreen(),
PageThreeScreen(context),
PageFourScreen(),
],
),
By default, the PageOneScreen() page shows in the HomePageScreen() and I can navigate to the other tabs quite fine.
I am trying to Navigator.popUntil(context, (route) => route.isFirst) from inside a different route and when it gets to PageOneScreen(), I want to navigate to tab 2 if a certain value in savedPrefrence = 2.
I have tried DefaultTabController.of(context).animateTo(1) on PageOneScreen() but it throws an error The method 'animateTo' was called on null. and I think it's because I don't have any tabcontroller reference in PageOneScreen().
How can I deal with this?

As you have defined a TabController, use it do switch between tabs like this:
_tabController.index = 2;
Considering that you want to navigate from inside PageOneScreen(), instantiate it with the controller, so it has access to it:
PageOneScreen(_tabController)

Related

When AutomaticKeepAliveClientMixin Widget is back on screen, how to refresh it?

I have a tab page with AutomaticKeepAliveClientMixin, which works well.
What I want is, when switch back to this page, I can choose refresh this page or not.
As far as I know, wantKeepAlive seems work on when widget is displayed.
I also checked life cycle of State. Method like initState, activate. None of them worked.
So my question is, Will there be any thing triggered when AutomaticKeepAliveClientMixin Widget is back on screen?
Or if AutomaticKeepAliveClientMixin can't do that, is there any other way to keep page state, and
Navigator.pop(context, false);
you can use this on screen
when you send to new screen
final return = Navigator.of(context).push(MaterialPageRoute<bool>());
if(return){
//
}else{
//
}
Move the state up from the page (tab) to parent and initiate refresh in onTap of TabBar.
TabBar(
onTap: (index) {
// TODO
},
controller: _controller,
tabs: const <Widget>[
...
],
),
For a more elegant solution take a look at Simple app state management.

How to make my tabbar synced with scroll when touched certain widget without package?

I have initialised my tab.
tabs = [
Tab(text: tr("detail")),
Tab(text: tr("store")),
Tab(text: tr("review")),
];
_tabController = TabController(
length: tabs.length,
vsync: this,
);
Then i have my widget wrap inside CustomScrollView
CustomScrollView(
controller: _scrollController,
slivers: [
SliverToBoxAdapter(child: Consumer<MyProvider>(
builder: (context, myProvider, child) {
return Column(
children: [
Widget1(),
Widget2(),
Widget3(),
Widget4(),
],
);
}))
]
I want to assign the tab index to certain widget, when scroll until the widget then my tab will switch too. I will need to manually assign an unique index to each widget and bind to my tab. When scrolling allow to scroll to widget not visible on screen also. How should i actually start to achieve that? thanks
Doing this without packages - simply copy the code you need from the package if you don't want dependency.
From what i understood you have 3 problems to solve
When scrolled to the bottom of page, switch the tab
There already is a great answer for the problem
Answer: https://stackoverflow.com/a/54539182/15106600
Do something when certain widget is displayed
There is the package for it to detect if widget is displayed ( remember it triggers when it starts being visible not the full height displayed)
Answer: https://pub.dev/packages/visibility_detector
Navigate to next tab
NavigatorController.animateTo()
Answer: https://api.flutter.dev/flutter/material/TabController-class.html

Flutter getx: separate each binding inside own binding when I don't use navigator

I am using getx. I have a main Page inside my application and mainBinding. Inside main page I have a Tabbar. Main Page has many pages that any pages loaded in this way:
child: TabBarView(
controller: controller.tabController,
physics: const NeverScrollableScrollPhysics(),
children: [
ReportOverallPage(),
Container(),
Container(),
Container(),
Container(),
Container(),....
],
),
As you can see ReportOverallPage() page not used of Navigator means not pushed into stack bay navigator so I cant create a binding for each pages.
each pages have own repository and controller. Now I have to add all controllers and repositories inside MainBinding.
class MainViewBinding implements Bindings {
#override
void dependencies() {
Get.lazyPut<MainViewController>(() => MainViewController());
Get.lazyPut<ReportController>(
() => ReportController(Get.find<ReportRepository>()));
Get.lazyPut<ReportRepository>(
() => ReportRepositoryImp(Get.find<RestClient>()));
.........
}
}
Now MainBainding has a long list of Putted class.How can I separate each binding class inside own binding class when I don't use navigator?
I'm afraid there's no straightforward way to do that. Because bindings are page specific (or navigation) you have to bind the dependencies with the page. Tabs aren't pages. Therefore you don't directly bind dependencies to them. You need to bind them with the containing page.
But one workaround could be you create separate binding class and then call the dependencies() method of each of them inside the dependencies() method of your MainBinding class.

flutter: Is it possible to use conditional statements in pageview?

I want to create a function that automatically moves to the next page when a certain condition is met using 'pageview'.
For example, if a=0 becomes a=1, it should automatically advance to the next page.
Instead of going to the next page by clicking a button in the pageview, is it possible to automatically go to the next page using a conditional statement?
Expanded(
child:
PageView.builder(
physics: NeverScrollableScrollPhysics(),
controller: _questionController.pageController,
onPageChanged: _questionController.updateTheQnNum,
itemCount: _questionController.questions.length,
itemBuilder: (context, index) => QuestionCard(
question: _questionController.questions[index],
myanswer: testtext,
),
)
),
This is part of my code. When a=1, it should advance to the next page, otherwise it should keep the current page.
There are two methods that can help you achieve it.
animateToPage
_questionController.pageController.animateToPage(pageIndex);
or
jumpToPage
_questionController.pageController.jumpToPage(pageIndex);
As the name suggests animateToPage will animate the transition from Page A to Page B where jumpToPage won't animate.
Make sure pageIndex is within the range.

Is it possible to disable a page when using PageView, Swiper or liquid_swiper?

I want to have the swiper effect in my app, I want to have 7 pages and move between the screens. I plan to have a form on every page.
For example, I am using Swiper package
Swiper(
itemBuilder: (BuildContext context, int index) {
return pagesWizzard[index]; //my 7 pages
},
itemCount: pagesWizzard.length,
pagination: new SwiperPagination(
margin: new EdgeInsets.all(5.0),
builder: new DotSwiperPaginationBuilder(
color: Colors.grey,
activeColor: Colors.blue)),
),
If I completed the form on page 1, I want to be able to slide the screen to go to page 2, and if I want I can go back and so on. If I have not completed the form on page 1, I should not be able to move to page 2 and higher.
Currently in: PageView, Swiper or liquid_swiper I can't find how to disable a page or multiple pages.
I would like you to guide me on how to do this.
Another question, is it a good practice to put my forms inside these components that allow swiping to navigate between screens? I ask about the issue of forms rendering and so on.
Another way on how to achieve this is passing a bool threw your form which checks if the formfields are filled in or not. If no, you prevent swiping to the next pages.
Using PageView with NeverscrollableScrollPhysics() and a PageController does the work for you.
// Outside build method
PageController controller = PageController();
// Inside build method
PageView(
controller: controller,
physics: NeverScrollableScrollPhysics(),
children: <Widget>[
// Add children
],
)
A good article for basic understanding of PageController can be found here: https://medium.com/flutter-community/a-deep-dive-into-pageview-in-flutter-with-custom-transitions-581d9ea6dded
With NeverscrollableScrollPhysics you block the swiping. Now wrap your children with a GestureDetector, and on swiping right you will check if your bool is true or not. If yes you will navigate to the next page with the PageController.
Example for GestureDetector
GestureDetector(onPanUpdate: (details) {
if (details.delta.dx > 0 && formFilled == true) {
pageController.jumpToPage(index);
// swiping in right direction
}
});