mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00

* Add support to move the fab between positions. * Motion demo for the FAB works between center and end floating. * Add a Material curve to the offset animation. * Move the fab position into an object * Updates to docs * Updates to docs * Fix a lint on the bottom sheet type * Add a ScaffoldGeometry class * Improve the documentation * Improve the documentation * Add a fab motion animator * Add position and scale animations * FAB entrance and motion animations work * Get started on FAB motion * Make fab animation work properly. * Change the fab animator to be stored in the state of the scaffold. * Add a layout test * Fix spacing being off * Fix the entrance/exit animation test. * Add a textDirection to the layout delegate. * Fix const constructor lint checks * Add toStrings for the fab positioner/animator * Add a toString for CurveTween * Change the fab motion demo icon to a simple add icon. * Add tests and a custom fab positioner to the demo. * Do not start the fab's motion animation when the fab is null. * Adjust the code to pass the new tests. * Rename for in response to Hans' comment. * Revert the tabs fab demo * Use timeDilation, and clean up the animation code a little. * Clean up the prelayout geometry docs and ctr order * Cleanup fab transition widget code * Clean up comments on Scaffold, add cross-references between the two geometries * Explain the fab motion animation scheduling better * Add a const to the fab motion demo * Make the fab animation never jank by keeping track of where to move the fab to in the future. * Add a default fab positioner constant * Add space after comma in the demo * Add boilerplate dartdoc to all const constructors * Comment improvement * Rename 'fabSize' to 'floatingActionButtonSize' * Rename 'fabSize' to 'floatingActionButtonSize' * Rename 'fabSize' to 'floatingActionButtonSize' * Clean up the prelayout geometry object's dartdoc * Clean up the prelayout geometry object's dartdoc * Remove extraneous comment * Change possessive uses of Scaffold's to use dartdoc-compatible [Scaffold]'s * Rename the horizontalFabPadding to an expansion * Clean up controller cleanup and setState usage * Animate instead of lerp * Make the fab position animation use offsets instead of animations * Streamline the fab motion demo * Set up the animator to start from a reasonable place when interrupting animations. * Doc cleanup on the new animation interruption * Expand some uses of fab and clean up constants * Expand remaining public uses of fab to floating action button * Expand remaining public uses of fab to floating action button * Expand on the documentation for the fab positioner and animator * Refactor animations to broadcast the position properly. * Add the ability to turn on and off the fab to the motion demo. * Remove unused code * Change the fab animator to animate even when the fab is exitting. * Remove extra positioner. * Apps -> Applications in docs * Explain the scale animation. * Name the child parameter in the animated builder * RTL before LTR * Wrap the AppBar in the example code * const the fab motion demo name * Start a test against animation jumps * Test for jumps in the fab motion animation * Dont initialize values to null * Use constants, fix spacing from some of Hans' comments * Clarify the relationship between fab positioners and prelayout geometries * Explain the fab animmator a bit better * Explain the animation progress in the fab animation * Explain the animation restart better * Explain the animation restart better * Explain the prelayout geometry better * Explain that height is a vertical distance. * Explain the horizontal fab padding * Update the scaffold size description to explain what happens when a wild keyboard appears * Remove print statements * Update the scaffold geometry with information about it being available at paint time. * In one step of a transition * Explain how the top-start fab positioner works * Explain how the top-start fab positioner works * Refactor the scaffold layout to just pass a padding instead of a bottom, top, start and end. * Refactor the scaffold layout to just pass a padding instead of a bottom, top, start and end. * Action buttons with with custom positioners. * Add a rotation animation example. * Use a swap animation to show swapping between two different animations. * Use a swap animation to show swapping between two different animations. * Add an example for the size animations. * 2018 copyright * Extra empty line * Return new Scaffold * Extra blank line fix * All its contents have been laid out * Position the fab * Explain what the scaffold geometry is for. * Move asserts to different lines * The scaffoldsize will not * Initial rename of FabPositioners to FloatingActionButtonLocation * Rename comments in example to refer to location instead of positioner. * Rename fabpositioner to location in tests and in the scaffold field * Finish removing references to positioner in scaffold code. * Split the fab location and animation out into a separate file. * Make things more private * Import foundation instead of meta * Const curve instead of final.
148 lines
5.8 KiB
Dart
148 lines
5.8 KiB
Dart
// Copyright 2018 The Chromium 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';
|
|
|
|
const String _explanatoryText =
|
|
"When the Scaffold's floating action button location changes, "
|
|
'the floating action button animates to its new position';
|
|
|
|
class FabMotionDemo extends StatefulWidget {
|
|
static const String routeName = '/material/fab-motion';
|
|
|
|
@override
|
|
_FabMotionDemoState createState() {
|
|
return new _FabMotionDemoState();
|
|
}
|
|
}
|
|
|
|
class _FabMotionDemoState extends State<FabMotionDemo> {
|
|
static const List<FloatingActionButtonLocation> _floatingActionButtonLocations = const <FloatingActionButtonLocation>[
|
|
FloatingActionButtonLocation.endFloat,
|
|
FloatingActionButtonLocation.centerFloat,
|
|
const _TopStartFloatingActionButtonLocation(),
|
|
];
|
|
|
|
bool _showFab = true;
|
|
FloatingActionButtonLocation _floatingActionButtonLocation = FloatingActionButtonLocation.endFloat;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final Widget floatingActionButton = _showFab
|
|
? new Builder(builder: (BuildContext context) {
|
|
// We use a widget builder here so that this inner context can find the Scaffold.
|
|
// This makes it possible to show the snackbar.
|
|
return new FloatingActionButton(
|
|
backgroundColor: Colors.yellow.shade900,
|
|
onPressed: () => _showSnackbar(context),
|
|
child: const Icon(Icons.add),
|
|
);
|
|
})
|
|
: null;
|
|
return new Scaffold(
|
|
appBar: new AppBar(
|
|
title: const Text('FAB Location'),
|
|
// Add 48dp of space onto the bottom of the appbar.
|
|
// This gives space for the top-start location to attach to without
|
|
// blocking the 'back' button.
|
|
bottom: const PreferredSize(
|
|
preferredSize: const Size.fromHeight(48.0),
|
|
child: const SizedBox(),
|
|
),
|
|
),
|
|
floatingActionButtonLocation: _floatingActionButtonLocation,
|
|
floatingActionButton: floatingActionButton,
|
|
body: new Center(
|
|
child: new Column(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: <Widget>[
|
|
new RaisedButton(
|
|
onPressed: _moveFab,
|
|
child: const Text('MOVE FAB'),
|
|
),
|
|
new Row(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: <Widget>[
|
|
const Text('Toggle FAB'),
|
|
new Switch(value: _showFab, onChanged: _toggleFab),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
void _moveFab() {
|
|
setState(() {
|
|
_floatingActionButtonLocation = _floatingActionButtonLocations[(_floatingActionButtonLocations.indexOf(_floatingActionButtonLocation) + 1) % _floatingActionButtonLocations.length];
|
|
});
|
|
}
|
|
|
|
void _toggleFab(bool showFab) {
|
|
setState(() {
|
|
_showFab = showFab;
|
|
});
|
|
}
|
|
|
|
void _showSnackbar(BuildContext context) {
|
|
Scaffold.of(context).showSnackBar(const SnackBar(content: const Text(_explanatoryText)));
|
|
}
|
|
}
|
|
|
|
// Places the Floating Action Button at the top of the content area of the
|
|
// app, on the border between the body and the app bar.
|
|
class _TopStartFloatingActionButtonLocation extends FloatingActionButtonLocation {
|
|
const _TopStartFloatingActionButtonLocation();
|
|
|
|
@override
|
|
Offset getOffset(ScaffoldPrelayoutGeometry scaffoldGeometry) {
|
|
// First, we'll place the X coordinate for the Floating Action Button
|
|
// at the start of the screen, based on the text direction.
|
|
double fabX;
|
|
assert(scaffoldGeometry.textDirection != null);
|
|
switch (scaffoldGeometry.textDirection) {
|
|
case TextDirection.rtl:
|
|
// In RTL layouts, the start of the screen is on the right side,
|
|
// and the end of the screen is on the left.
|
|
//
|
|
// We need to align the right edge of the floating action button with
|
|
// the right edge of the screen, then move it inwards by the designated padding.
|
|
//
|
|
// The Scaffold's origin is at its top-left, so we need to offset fabX
|
|
// by the Scaffold's width to get the right edge of the screen.
|
|
//
|
|
// The Floating Action Button's origin is at its top-left, so we also need
|
|
// to subtract the Floating Action Button's width to align the right edge
|
|
// of the Floating Action Button instead of the left edge.
|
|
final double startPadding = kFloatingActionButtonMargin + scaffoldGeometry.minInsets.right;
|
|
fabX = scaffoldGeometry.scaffoldSize.width - scaffoldGeometry.floatingActionButtonSize.width - startPadding;
|
|
break;
|
|
case TextDirection.ltr:
|
|
// In LTR layouts, the start of the screen is on the left side,
|
|
// and the end of the screen is on the right.
|
|
//
|
|
// Placing the fabX at 0.0 will align the left edge of the
|
|
// Floating Action Button with the left edge of the screen, so all
|
|
// we need to do is offset fabX by the designated padding.
|
|
final double startPadding = kFloatingActionButtonMargin + scaffoldGeometry.minInsets.left;
|
|
fabX = startPadding;
|
|
break;
|
|
}
|
|
// Finally, we'll place the Y coordinate for the Floating Action Button
|
|
// at the top of the content body.
|
|
//
|
|
// We want to place the middle of the Floating Action Button on the
|
|
// border between the Scaffold's app bar and its body. To do this,
|
|
// we place fabY at the scaffold geometry's contentTop, then subtract
|
|
// half of the Floating Action Button's height to place the center
|
|
// over the contentTop.
|
|
//
|
|
// We don't have to worry about which way is the top like we did
|
|
// for left and right, so we place fabY in this one-liner.
|
|
final double fabY = scaffoldGeometry.contentTop - (scaffoldGeometry.floatingActionButtonSize.height / 2.0);
|
|
return new Offset(fabX, fabY);
|
|
}
|
|
}
|