In my TabBar, there are up to 3 kinds of tabs of different widths.
"x月xx" has the widest width, "xx月" is the middle, "x月" has the narrowest width.
And when the tab state change from unselected to selected, it will become more wide because it add the prefix "xxxx年" to the title.
I can not set a specific value to tab width, because the tab title may change from "2020年11月" to "11月" if unselected.
My purpose is to center the selected tab on the screen.
The method animateTo of TabController only allows scrolling to an index but not a distance. So I copied the tabs.dart. I want to change the method _scrollToCurrentIndex() which uses a ScrollController to animate to an offset. There are many things(e.g. various TabOffsets, ScrollOffset, viewportWidth...) useful, but I still don' t know how to let scroll offset and padding work together.
I succeeded partly, that means, the selected tab will scroll to center, but the animation is strange.
In class _TabBarState extends State<TabBar> I found this in build function:
Widget tabBar = CustomPaint(
painter: _indicatorPainter,
child: _TabStyle(
// ...
child: _TabLabelBar(
onPerformLayout: _saveTabOffsets,
children: wrappedTabs,
),
),
);
In onPerformLayout: _saveTabOffsets I can get List<double> tabOffsets and double tabBarWidth. I use these to calculate the distance to scroll. But in this way, the problem is: when click a tab, it draws the indicator first, and after the indicator change from the last selected tab to the new selected tab, the tabBar scrolls to center it.
I am open to better ideas.
Related
I am trying to write a scroll pagination widget but What I am stuck some point due scroll controller. I am listening a scroll controller, if user scrolled the list to end of the listview I am sending a page request but it is not working because if first request response widgets height lesser than the view height, user can't scroll so scroll controller listener never triggering. For this problem, my question is how can I detect the scrolling is active or not ? (what I want is, if loaded page results widgets smaller than the list view height, send a new page request.)
Ruchit's answer is a good option, Or you could get the height of the widget and compare it to the screen height. That should work.
How to get the widget's height: How to get height of a Widget?
you can apply AlwaysScrollableScrollPhysics() to your gridview and it will always let the user scroll even if it has less height.
documentation: https://api.flutter.dev/flutter/widgets/AlwaysScrollableScrollPhysics-class.html
On iOS, tapping the status bar makes PrimaryScrollController go to the top:
https://flutter.dev/docs/resources/platform-adaptations#return-to-top
On iOS, tapping the OS status bar scrolls the primary scroll controller to the top position. There is no equivalent behavior on Android.
My PrimaryScrollController is attached to a ListView with reverse:true, so tapping the status bar makes it scroll to the bottom.
Docs say PrimaryScrollView handles ScrollAction if not handled by another scroll controller.
https://api.flutter.dev/flutter/widgets/PrimaryScrollController-class.html
If a ScrollAction is not handled by an otherwise focused part of the application, the ScrollAction will be evaluated using the scroll view associated with a PrimaryScrollController
How can I handle scroll actions myself so I can reverse the direction PrimaryScrollController goes when the status bar is tapped?
The easiest way to accomplish this is likely going to be reversing the items in your list instead of using the reverse: true flag of ListView.
For example:
ListView(
children: [
Container(),
Container(),
].reversed.toList(),
),
Trying to solve this any other way would get pretty involved. Since we don't have access to the StatusBar we can't override its behavior or listen for taps on it.
I have a brainer here. So I have a NestedScrollView with a header consisting of an image, and 3 tabs. Those 3 tabs, when scrolled, needs to be pinned to the top.
Visualization here:
Below I Have a tabView corresponding to tabs in a header. Those tabViews have dynamic height and all "tiles" are different. It's working. But I need to (onTap) change the tab and scroll to an element in the body of tab2.
Problem:
When trying to attach scroll controller to tab x body, the scrolling is independent from the global one.
When trying to use PrimaryScrollController.of(context) it works, but only on the first time. When I try to open it the second time I get ScrollController attached to multiple scroll views when switching to the different items (presented visualization can be multiplied for other items in the app). I tried to detach the current scroll position form the controller on dispose but I get another error.
Any ideas?
I have two Pages inside a vertical PageView.
PageView(
controller: pageController,
scrollDirection: Axis.vertical,
children: [
PageA(),
PageB(),
],
)
The lower page (B) contains the following:
Column
Row
...
Expanded
ListView
Card
Container
Row
...
Flexible
Padding
TextFormField
The problem occurs whenever I focus and unfocus the TextFormField.
Expetation: The Keyboard pops up and the Expanded ListView shrinks, so that the TextFormField is above the Keyboard. When the Keyboard is dismissed, the ListView should expand and the page should look as before.
What happens instead: When the Keyboard is dissmissed, the ListView expands back to its original size but the Page (B) stays offset above where the keyboard was and doesn't move back down. The end result is, that the page (B) is offset upwards ind thus partially offscreen and I have to scroll it manually back down.
The page B itself has a fixed size and once scrolled back down, it can't be offset upwards manually.
TL;DR: PageView pushes page partially off screen after dismissing keyboard.
Any help is apreciated and thanks in advance :D
Edit: Added Screenshot: Before, while and after editing the text field
Edit 2: I think it has something to do with the pageview itself and its scroll physics.
So I have a SingleChildScrollView() whose child is a Column() with different widgets inside it. I have 3 BUTTONS on the app bar. Each for 3 widgets I want to jump to.
When I press the button, I want the UI to automatically scroll to the mapped Widget. Just like we see that effect in websites.
How can I achieve this ?
You can create a ScrollController and pass it to the controller parameter of your scrolling widget. Then you can use the animateTo method to animate to an offset.
Ex.
ScrollController controller = ScrollController();
//In build
SingleChildScrollView(
controller: controller,
child: ...,
)
//In each button onPressed/onTap
controller.animateTo(offset);