Have TabBar indicator properly follow tabController animation value#57799
Have TabBar indicator properly follow tabController animation value#57799giantsol wants to merge 2 commits intoflutter:masterfrom giantsol:tabcontroller_animation
Conversation
| if (controller.indexIsChanging) { | ||
| // The user tapped on a tab, the tab controller's animation is running. | ||
| final Rect targetRect = indicatorRect(size, controller.index); | ||
| _currentRect = Rect.lerp(targetRect, _currentRect ?? targetRect, _indexChangeProgress(controller)); |
There was a problem hiding this comment.
it was lerping between targetRect and _currentRect, in which _currentRect was getting updated every frame. Thus it moved faster than intended.
|
I think we should definitely do something about 2 and 3. Do you have plan to fix those two? I have not look into it deeper. but if they are different cause, i am ok with separating out to different pr. We need more discussion on whether the gesture can interrupt the animation. From the look of the tab bar code, it seems like we are disallowing that. |
|
Fixing 2 and 3 needs more look into it. I've been looking at it but paused because I thought I needed your opinions first. But surely, they have different causes and it'd be nice if I can shoot out a separate PR for fixing 2 and 3 together :) If your intentions were not to make gestures interrupt the animation, I can just revert my second commit. Should I do so? |
We can have more discussion on whether the gesture should interrupt the animation. If there is no use case that we should change the behavior, we should leave it as is. |
Sure, the reasoning behind me changing that behavior was, after I fixed indicator to properly follow the given duration, it took so long for the indicator to start responding to gesture. If I called animateTo with say duration of 10 seconds, indicator won't respond to gesture for that long time. That looked unnecessary for me, so I thought 'why not let the gesture interrupt ongoing animation?' |
|
It looks fine because the page view warping is fast and usually finish before the gesture happens. However, that is something we should fix at some point. Once we fix that, user will more likely to interrupt the page warping. That will become a problem because the page will reorder its children during warping. We need to figure out what should we do when user interrupts it. |
|
I see the point. The problem you mentioned will be apparent when we fix page warping to follow the given duration. I guess the first thing I'm gonna try is the first path you've mentioned i.e. directly reorder the children back. We will see the skew, but this skew looks inevitable whatever paths we take. It will have to appear at one point of time. I have to try it out and see how unnatural it looks. If it looks too unnatural, I think keeping the original behavior (i.e. gesture not interrupting animation) is also fine, if it looks better than sudden skewing. I think it will become clearer after I test it out. If I could do that as a separate PR, I think it'd be better I revert the second commit for now and only merge indicator fix. What do you think? |
|
Hold on. Without any code change, page warping was already being interrupted by user gesture. Because when user starts dragging the TabBarView, previous So there was already a skew in TabBarView, and the behavior I've changed only made TabBar's scroll position and indicator to move in accordance with TabBarView's scroll position. Previously, only TarBarView's animation would get interrupted. Now, TabBarView and TabBar's animation all together will get interrupted, which looks quite reasonable to me now. |
chunhtai
left a comment
There was a problem hiding this comment.
Interesting, I didnt realize the we only block gesture on tabbar but not on pageview. I really do no have a good answer whether or not we should allow it on both or disable it on both. I am a bit concern about the skew, and we should find a good way to smooth it if we want to allow it, otherwise we should disable.
| strokeWidth: indicatorWeight, | ||
| p1: const Offset(2476.0, indicatorY), | ||
| p2: const Offset(2574.0, indicatorY), | ||
| p1: const Offset(midIndicatorLeft, indicatorY), |
There was a problem hiding this comment.
This might be a breaking change, you will need to follow the breaking change protocol. https://github.com/flutter/flutter/wiki/Tree-hygiene#handling-breaking-changes
There was a problem hiding this comment.
Since it is likely fixing 2 and 3 might be a breaking change as well due to failing test, It may be good to try to fix them first and see if they are indeed breaking change and group them together if they are
|
Understood! I guess then I'd better close this PR and write a breaking change proposal first. After accepted, I'll send a PR grouping them all together. |
Description
There are three parts that move in
TabBarandTabBarViewwhen we calltabController.animateTo():Currently, none of them properly follow the duration and curve given to
tabController.animateTo(). Whether we should change 2 and 3's behavior needs a consensus, I believe, but 1 was definitely a bug. There was a code intended to make the indicator followtabController.animation.valuebut it wasn't exactly working as intended. So that's what I've tried to fix here.Reproducible code
Before
Just looking at the indicator, I've given 3 seconds duration to the animation, but indicator moves much faster than that. Although it looks like the animation has finished early, when we drag the TabBarView, indicator doesn't respond because it's actually still in animation.
After
Now the indicator properly follows the animation value.
Actually, if you look at the second gif, there's one more behavior I've changed here: e7c9efc. Previously, while
tabControlleris in animation, dragging theTabBarViewdoesn't interfere, i.e.tabControllerkeeps animating. But I personally thought this could look more like a bug. Rather, if user starts dragging,tabController's animation should stop and follow that value. If this change looks inappropriate, I'm happy to revert it.Related Issues
#55625
#19143
Tests
I've modified one existing test and also added a new one, but it's not actually a breaking change.. The one I've modified was actually giving a false positive, i.e. giving ok sign to improperly acting logic. You can check it here: 304b1cf
So I'll first say no to is it breaking change? checkbox below. Please tell me if there's an issue :)
Checklist
Before you create this PR confirm that it meets all requirements listed below by checking the relevant checkboxes (
[x]). This will ensure a smooth and quick review process.///).flutter analyze --flutter-repo) does not report any problems on my PR.Breaking Change
Did any tests fail when you ran them? Please read Handling breaking changes.