-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Feat: Add top gap for cupertino sheet #171348
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feat: Add top gap for cupertino sheet #171348
Conversation
|
It looks like this pull request may not have tests. Please make sure to add tests or get an explicit test exemption before merging. If you are not sure if you need tests, consider this rule of thumb: the purpose of a test is to make sure someone doesn't accidentally revert the fix. Ask yourself, is there anything in your PR that you feel it is important we not accidentally revert back to how it was before your fix? Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing.If you believe this PR qualifies for a test exemption, contact "@test-exemption-reviewer" in the #hackers channel in Discord (don't just cc them here, they won't see it!). The test exemption team is a small volunteer group, so all reviewers should feel empowered to ask for tests, without delegating that responsibility entirely to the test exemption group. |
|
I'm not sure the top gap should be set as a pixel value. Instead it might be better as a ratio of the screen height, from 0 to 1.0. So 0.5 would be half screen. That would be safer with looking correct across different screen sizes. |
3154d0a to
cd81ee1
Compare
MitchellGoodwin
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for putting this together. Overall I like the approach, but this causes a problem with stacking multiple sheets, that I mention below. I'm not sure how best to approach that.
In the future, we'll likely want to add detents to the sheet: #169832. I was wondering if we should not add a topGap value and leave that to be handled by the more complicated detents, but I think it would both be good to have a simple value to set, and this could function as an initial sheet size to open on when using detents. So I think we should continue with this for now.
| final bool enableDrag; | ||
|
|
||
| @override | ||
| final double? topGap; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we could make this a little friendlier. We can add a private _topGap value. The constructor sets _topGap to whatever user defined property, or leaves it null. Then this override only sets a getter topGap that returns _topGap ?? _kTopGapRatio. Then we can both just use topGap everywhere and if another bit of code looks at topGap than it will be a reliable source of truth.
Also, I think we don't want to expose a setter for now. In the future we will probably want to enable programmatically changing the top gap while the sheet is open and having it animate the difference, and leaving no open setter for now makes that easier.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pushed the change.
7dac230 to
92dec8d
Compare
MitchellGoodwin
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like the test is still failing.
But it looks like in SwiftUI the stacked view only happens with the default sheet height, or .large for them. All others have the previous page shown normally.
I think that simplifies what we need to do. If a user provides a topGap, then we don't want the previous route to transition at all, even if it matches our default. So I think we can do this:
- Create a private double? _topGap. The constructor sets _topGap to the user provided topGap, if provided. This lets us track if it's left as null.
- Add a topGap getter for providing programmatically which topGap to use.
double get topGap => _topGap ?? _kTopGapRatio- Add a
canTransitionFromoverride and have both it andcanTransitionToreturn false if _topGap != null
I think if we do all that, we can revert delegatedTransition to what it was before and not worry about it. It won't be used at all if exit transitions are blocked from the code above.
b92aa43 to
91fe520
Compare
|
@MitchellGoodwin Reverted the delegatedTransition Change and updated canTransition methods with topGap, but i think test are still failing, I tested it on device, looks fine but might have missed any edge case. |
MitchellGoodwin
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the update, I left some comments.
| Animation<double> secondaryAnimation, | ||
| bool allowSnapshotting, | ||
| Widget? child, | ||
| ) => CupertinoSheetTransition.delegateTransition( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this can be simplified to
_topGap != null ? null : CupertinoSheetTransition.delegateTransition;| if (this is CupertinoSheetRoute<dynamic>) { | ||
| return (this as CupertinoSheetRoute<dynamic>)._topGap == null; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we get this logic without the type casting?
| Widget? child, | ||
| ) { | ||
| Widget? child, { | ||
| double? topGap, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we won't use this transition if there is a topGap, then we can remove this and not handle it.
91fe520 to
6797926
Compare
|
Are there any updates on this? Could we get this merged at this point? |
|
@erkinovalim We still need review. |
aa3f128 to
a4f1b27
Compare
MitchellGoodwin
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry it took a while to get back to this. Approach looks good, I have some nitpick comments on the canTransitionTo and canTransitionFrom methods. Main thing left is adding a test.
a4f1b27 to
40a4bc9
Compare
|
@MitchellGoodwin could you review this please? |
MitchellGoodwin
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the updates. It looks like the top gap value isn't actually being used for the sheet itself. The topGap needs to be applied to the _stretchDragAnimation in order to be used. However, I'm not sure how stretching should work with a custom top gap. Either the value for the max stretch needs to adjust if a custom top gap is given, or stretching needs to be disabled with a custom top gap.
| bool get enableDrag; | ||
|
|
||
| /// The gap between the top of the screen and the top of the sheet as a ratio | ||
| /// of the screen height (0.0 to 1.0). Defaults to [_kTopGapRatio]. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Private variables won't be able to be seen by documentation.
| /// of the screen height (0.0 to 1.0). Defaults to [_kTopGapRatio]. | |
| /// of the screen height (0.0 to 1.0). Defaults to a value of 0.08. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, will update.
| double get topGap => _topGap ?? _kTopGapRatio; | ||
|
|
||
| @override | ||
| bool get hasCustomTopGap => _topGap != null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This maybe should be a private method. I'm not sure if it's useful outside of these classes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is used inside mixin. Here, we are just providing value. So, updated to private.
2c027e4 to
5d263d7
Compare
|
@MitchellGoodwin could you review this please? |
MitchellGoodwin
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apologies for the late review. Tested this locally and it lgtm. Left two comments, but other than that, I think this is good to go.
| if (this is CupertinoSheetRoute<dynamic> && _hasCustomTopGap) { | ||
| return false; | ||
| } | ||
| return nextRoute is _CupertinoSheetRouteTransitionMixin && !_hasCustomTopGap; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This check for !_hasCustomTopGap is redundant, because it already happens above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, will do.
5d263d7 to
c8f49ae
Compare
| this.enableDrag = true, | ||
| double? topGap, | ||
| }) : assert( | ||
| topGap == null || (topGap >= 0.0 && topGap <= 1.0), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if we should limit the topGap so that it is not able to be 1.0, or the gap is the whole screen height. That would mean that none of the sheet is visible. I don't know why somebody would do that, but if they did it would mean that the top most route is active, but not on the screen at all, which would be hacky and also seems like it would mess with accessibility. Maybe it should be a max of 0.9, or 0.95?
If they set the topgap to 0.0 though, so that the sheet is fullscreen, I think that's perfectly ok.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yaa, we can do 0.9 because even 10% will be too small.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the behavior like on swiftui?
c8f49ae to
a720971
Compare
| bool enableDrag = true, | ||
| double? topGap, | ||
| }) { | ||
| assert(topGap == null || (topGap >= 0.0 && topGap <= 1.0), 'topGap must be between 0.0 and 1.0'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need the check for < 0.9 here as well
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I should have updated this also. Pushing change now.
a720971 to
9f0fed7
Compare
9f0fed7 to
272df29
Compare
MitchellGoodwin
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, pending some documentation nits. Thank you so much for your patience on this one.
| /// It should be a value between 0.0 and 1.0, where 0.0 means no gap and 1.0 | ||
| /// means the sheet starts at the bottom. If not provided, defaults to 0.08 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| /// It should be a value between 0.0 and 1.0, where 0.0 means no gap and 1.0 | |
| /// means the sheet starts at the bottom. If not provided, defaults to 0.08 | |
| /// It should be a value between 0.0 and 0.9, where 0.0 means no gap and 0.9 | |
| /// means the sheet takes up only the bottom 10% of the screen. If not provided, defaults to 0.08 |
| /// This value should be between 0.0 and 1.0, where 0.0 means no gap (sheet | ||
| /// extends to the top of the screen) and 1.0 means the sheet starts at the | ||
| /// bottom of the screen. A value of 0.08 represents 8% of the screen height. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| /// This value should be between 0.0 and 1.0, where 0.0 means no gap (sheet | |
| /// extends to the top of the screen) and 1.0 means the sheet starts at the | |
| /// bottom of the screen. A value of 0.08 represents 8% of the screen height. | |
| /// This value should be between 0.0 and 0.9, where 0.0 means no gap (sheet | |
| /// extends to the top of the screen) and 0.9 means the sheet covers only the | |
| /// bottom 10% of the screen. A value of 0.08 represents 8% of the screen height. |
| duration: const Duration(microseconds: 1), | ||
| vsync: this, | ||
| ); | ||
| // Maintain the same stretch distance (0.008 of screen height) regardless of custom topGap |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| // Maintain the same stretch distance (0.008 of screen height) regardless of custom topGap | |
| // Maintain the same stretch distance (0.008 of screen height) regardless of custom topGap. |
| // Divide by stretchable range (when dragging upward at max extent). | ||
| upController.value -= | ||
| delta / (navigator.context.size!.height * (_kTopGapRatio - _kStretchedTopGapRatio)); | ||
| // Maintain the same stretch distance regardless of custom topGap |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| // Maintain the same stretch distance regardless of custom topGap | |
| // Maintain the same stretch distance regardless of custom topGap. |
272df29 to
e9bf03f
Compare
Feat: Add top gap for cupertino sheet
fixes: #169465
Pre-launch Checklist
///).