-
Notifications
You must be signed in to change notification settings - Fork 26.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add ability to disable
FloatingActionButton
scale and rotation anim…
…ations using `FloatingActionButtonAnimator.noAnimation` (#146126) fixes [[Proposal] Allow disabling the scaling animation of the FloatingActionButton](#145585) ### Using default `FloatingActionButton` animations ![ScreenRecording2024-04-02at16 19 03-ezgif com-video-to-gif-converter](https://github.com/flutter/flutter/assets/48603081/627ea564-7f60-4eb4-bed9-95c053ae2f56) ### Using `FloatingActionButtonAnimator.noAnimation` ![ScreenRecording2024-04-02at16 17 20-ezgif com-video-to-gif-converter](https://github.com/flutter/flutter/assets/48603081/d0a936ea-9e16-4225-8dc4-40a11ee8a975)
- Loading branch information
1 parent
098e7e7
commit 257df5e
Showing
5 changed files
with
362 additions
and
6 deletions.
There are no files selected for viewing
120 changes: 120 additions & 0 deletions
120
examples/api/lib/material/scaffold/scaffold.floating_action_button_animator.0.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
// Copyright 2014 The Flutter Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
import 'package:flutter/material.dart'; | ||
|
||
/// Flutter code sample for [Scaffold.floatingActionButtonAnimator]. | ||
void main() => runApp(const ScaffoldFloatingActionButtonAnimatorApp()); | ||
|
||
class ScaffoldFloatingActionButtonAnimatorApp extends StatelessWidget { | ||
const ScaffoldFloatingActionButtonAnimatorApp({super.key}); | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return const MaterialApp( | ||
home: ScaffoldFloatingActionButtonAnimatorExample(), | ||
); | ||
} | ||
} | ||
|
||
enum FabAnimator { defaultStyle, none } | ||
const List<(FabAnimator, String)> fabAnimatoregments = <(FabAnimator, String)>[ | ||
(FabAnimator.defaultStyle, 'Default'), | ||
(FabAnimator.none, 'None'), | ||
]; | ||
|
||
enum FabLocation { centerFloat, endFloat, endTop } | ||
const List<(FabLocation, String)> fabLocationegments = <(FabLocation, String)>[ | ||
(FabLocation.centerFloat, 'centerFloat'), | ||
(FabLocation.endFloat, 'endFloat'), | ||
(FabLocation.endTop, 'endTop'), | ||
]; | ||
|
||
class ScaffoldFloatingActionButtonAnimatorExample extends StatefulWidget { | ||
const ScaffoldFloatingActionButtonAnimatorExample({super.key}); | ||
|
||
@override | ||
State<ScaffoldFloatingActionButtonAnimatorExample> createState() => _ScaffoldFloatingActionButtonAnimatorExampleState(); | ||
} | ||
|
||
class _ScaffoldFloatingActionButtonAnimatorExampleState extends State<ScaffoldFloatingActionButtonAnimatorExample> { | ||
Set<FabAnimator> _selectedFabAnimator = <FabAnimator>{FabAnimator.defaultStyle}; | ||
Set<FabLocation> _selectedFabLocation = <FabLocation>{FabLocation.endFloat}; | ||
FloatingActionButtonAnimator? _floatingActionButtonAnimator; | ||
FloatingActionButtonLocation? _floatingActionButtonLocation; | ||
bool _showFab = false; | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return Scaffold( | ||
floatingActionButtonLocation: _floatingActionButtonLocation, | ||
floatingActionButtonAnimator: _floatingActionButtonAnimator, | ||
appBar: AppBar(title: const Text('FloatingActionButtonAnimator Sample')), | ||
body: Center( | ||
child: Column( | ||
mainAxisAlignment: MainAxisAlignment.center, | ||
children: <Widget>[ | ||
SegmentedButton<FabAnimator>( | ||
selected: _selectedFabAnimator, | ||
onSelectionChanged: (Set<FabAnimator> styles) { | ||
setState(() { | ||
_floatingActionButtonAnimator = switch (styles.first) { | ||
FabAnimator.defaultStyle => null, | ||
FabAnimator.none => FloatingActionButtonAnimator.noAnimation, | ||
}; | ||
_selectedFabAnimator = styles; | ||
}); | ||
}, | ||
segments: fabAnimatoregments | ||
.map<ButtonSegment<FabAnimator>>(((FabAnimator, String) fabAnimator) { | ||
final FabAnimator animator = fabAnimator.$1; | ||
final String label = fabAnimator.$2; | ||
return ButtonSegment<FabAnimator>(value: animator, label: Text(label)); | ||
}) | ||
.toList(), | ||
), | ||
const SizedBox(height: 10), | ||
SegmentedButton<FabLocation>( | ||
selected: _selectedFabLocation, | ||
onSelectionChanged: (Set<FabLocation> styles) { | ||
setState(() { | ||
_floatingActionButtonLocation = switch (styles.first) { | ||
FabLocation.centerFloat => FloatingActionButtonLocation.centerFloat, | ||
FabLocation.endFloat => FloatingActionButtonLocation.endFloat, | ||
FabLocation.endTop => FloatingActionButtonLocation.endTop, | ||
}; | ||
_selectedFabLocation = styles; | ||
}); | ||
}, | ||
segments: fabLocationegments | ||
.map<ButtonSegment<FabLocation>>(((FabLocation, String) fabLocation) { | ||
final FabLocation location = fabLocation.$1; | ||
final String label = fabLocation.$2; | ||
return ButtonSegment<FabLocation>(value: location, label: Text(label)); | ||
}) | ||
.toList(), | ||
), | ||
const SizedBox(height: 10), | ||
FilledButton.icon( | ||
onPressed: () { | ||
setState(() { | ||
_showFab = !_showFab; | ||
}); | ||
}, | ||
icon: Icon(_showFab ? Icons.visibility_off : Icons.visibility), | ||
label: const Text('Toggle FAB'), | ||
), | ||
], | ||
), | ||
), | ||
floatingActionButton: !_showFab | ||
? null | ||
: FloatingActionButton( | ||
onPressed: () {}, | ||
child: const Icon(Icons.add), | ||
), | ||
); | ||
} | ||
} |
60 changes: 60 additions & 0 deletions
60
examples/api/test/material/scaffold/scaffold.floating_action_button_animator.0_test.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
// Copyright 2014 The Flutter Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
import 'package:flutter/material.dart'; | ||
import 'package:flutter_api_samples/material/scaffold/scaffold.floating_action_button_animator.0.dart' as example; | ||
import 'package:flutter_test/flutter_test.dart'; | ||
|
||
void main() { | ||
testWidgets('FloatingActionButton animation can be customized', (WidgetTester tester) async { | ||
await tester.pumpWidget( | ||
const example.ScaffoldFloatingActionButtonAnimatorApp(), | ||
); | ||
|
||
expect(find.byType(FloatingActionButton), findsNothing); | ||
|
||
// Test default FloatingActionButtonAnimator. | ||
// Tap the toggle button to show the FAB. | ||
await tester.tap(find.text('Toggle FAB')); | ||
await tester.pump(); | ||
await tester.pump(const Duration(milliseconds: 100)); // Advance animation by 100ms. | ||
// FAB is partially animated in. | ||
expect(tester.getTopLeft(find.byType(FloatingActionButton)).dx, closeTo(743.8, 0.1)); | ||
|
||
await tester.pump(const Duration(milliseconds: 100)); // Advance animation by 100ms. | ||
// FAB is fully animated in. | ||
expect(tester.getTopLeft(find.byType(FloatingActionButton)).dx, equals(728.0)); | ||
|
||
// Tap the toggle button to hide the FAB. | ||
await tester.tap(find.text('Toggle FAB')); | ||
await tester.pump(); | ||
await tester.pump(const Duration(milliseconds: 100)); // Advance animation by 100ms. | ||
// FAB is partially animated out. | ||
expect(tester.getTopLeft(find.byType(FloatingActionButton)).dx, closeTo(747.1, 0.1)); | ||
|
||
await tester.pump(const Duration(milliseconds: 100)); // Advance animation by 100ms. | ||
// FAB is fully animated out. | ||
expect(tester.getTopLeft(find.byType(FloatingActionButton)).dx, equals(756.0)); | ||
|
||
await tester.pump(const Duration(milliseconds: 50)); // Advance animation by 50ms. | ||
// FAB is hidden. | ||
expect(find.byType(FloatingActionButton), findsNothing); | ||
|
||
// Select 'None' to disable animation. | ||
await tester.tap(find.text('None')); | ||
await tester.pump(); | ||
|
||
// Test no animation FloatingActionButtonAnimator. | ||
await tester.tap(find.text('Toggle FAB')); | ||
await tester.pump(); | ||
// FAB is immediately shown. | ||
expect(tester.getTopLeft(find.byType(FloatingActionButton)).dx, equals(728.0)); | ||
|
||
// Tap the toggle button to hide the FAB. | ||
await tester.tap(find.text('Toggle FAB')); | ||
await tester.pump(); | ||
// FAB is immediately hidden. | ||
expect(find.byType(FloatingActionButton), findsNothing); | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters