Skip to content

Commit

Permalink
feat: add more drop-in replacements for Flutter widgets (#53)
Browse files Browse the repository at this point in the history
  • Loading branch information
blaugold authored Jun 19, 2023
1 parent 42a676f commit e79ac71
Show file tree
Hide file tree
Showing 12 changed files with 977 additions and 194 deletions.
9 changes: 9 additions & 0 deletions packages/fleet/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,17 +138,26 @@ The following drop-in replacements for Flutter framework widgets are provided
for animating with Fleet:

- FleetAlign
- FleetAspectRatio
- FleetCenter
- FleetColoredBox
- FleetColumn
- FleetConstrainedBox
- FleetContainer
- FleetDecoratedBox
- FleetFittedBox
- FleetFlex
- FractionalTranslation
- FleetFractionallySizedBox
- FleetLimitedBox
- FleetOpacity
- FleetOverflowBox
- FleetPadding
- FleetPositioned
- FleetPositionedDirectional
- FleetRow
- FleetSizedBox
- FleetSizedOverflowBox
- FleetSliverOpacity
- FleetSliverPadding
- FleetTransform
Expand Down
10 changes: 2 additions & 8 deletions packages/fleet/example/lib/hike_graph.dart
Original file line number Diff line number Diff line change
Expand Up @@ -113,14 +113,8 @@ class GraphCapsule extends StatelessWidget {
@override
Widget build(BuildContext context) {
final relativeRange = range.relativeTo(overallRange);
return Container(
height: height * relativeRange.magnitude,
width: 24,
decoration: ShapeDecoration(
shape: const StadiumBorder(),
color: color,
),
) //
return SizedBox(height: height * relativeRange.magnitude, width: 24)
.decoration(shape: const StadiumBorder(), color: color)
.offset(y: -height * relativeRange.min);
}
}
Expand Down
13 changes: 11 additions & 2 deletions packages/fleet/lib/fleet.dart
Original file line number Diff line number Diff line change
Expand Up @@ -38,31 +38,40 @@ export 'src/animation/parameter.dart'
OptionalAnimatableSize;
export 'src/common.dart' show Block;
export 'src/environment.dart' show EnvironmentKey, EnvironmentValueModifiers;
export 'src/widgets/basic_flutter_widgets.dart'
export 'src/widgets/flutter/basic.dart'
show
FleetAlign,
FleetAspectRatio,
FleetCenter,
FleetColoredBox,
FleetColumn,
FleetColumnApplyChildren,
FleetContainer,
FleetConstrainedBox,
FleetFittedBox,
FleetFlex,
FleetFlexApplyChildren,
FleetFractionalTranslation,
FleetFractionallySizedBox,
FleetIndexedStackApplyChildren,
FleetLimitedBox,
FleetOpacity,
FleetOverflowBox,
FleetPadding,
FleetPositioned,
FleetPositionedDirectional,
FleetRow,
FleetRowApplyChildren,
FleetSizedBox,
FleetSizedOverflowBox,
FleetSliverOpacity,
FleetSliverPadding,
FleetStackApplyChildren,
FleetTransform,
FleetWrapApplyChildren,
defaultHorizontalMainAxisSize,
defaultVerticalMainAxisSize;
export 'src/widgets/flutter/container.dart'
show FleetContainer, FleetDecoratedBox;
export 'src/widgets/opinionated_defaults.dart' show OpinionatedDefaults;
export 'src/widgets/uniform_padding.dart'
show Edge, Edges, UniformPadding, defaultUniformPadding;
230 changes: 216 additions & 14 deletions packages/fleet/lib/modifiers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ import 'package:flutter/widgets.dart';

import 'src/animation/animate.dart';
import 'src/animation/animation.dart';
import 'src/widgets/basic_flutter_widgets.dart';
import 'src/widgets/flutter/basic.dart';
import 'src/widgets/flutter/container.dart';

export 'src/widgets/basic_flutter_widgets.dart' show FleetFlexModifiers;
export 'src/widgets/flutter/basic.dart' show FleetFlexModifiers;
export 'src/widgets/opinionated_defaults.dart' show OpinionatedDefaultsModifier;
export 'src/widgets/uniform_padding.dart' show UniformPaddingModifiers;

Expand Down Expand Up @@ -78,6 +79,73 @@ extension BasicModifiers on Widget {
);
}

/// Scales and positions this widget within the available space according to
/// [fit]
@widgetFactory
Widget fit(
BoxFit fit, {
AlignmentGeometry alignment = Alignment.center,
Clip clipBehavior = Clip.none,
}) {
return FleetFittedBox(
fit: fit,
alignment: alignment,
clipBehavior: clipBehavior,
child: this,
);
}

/// Applies additional constraints to this widget.
@widgetFactory
Widget constraints({
double? minWidth,
double? maxWidth,
double? minHeight,
double? maxHeight,
BoxConstraints? constraints,
bool overflow = false,
AlignmentGeometry? alignment,
}) {
assert(
overflow || alignment == null,
'alignment can only be used with overflow',
);
assert(() {
_debugCheckParameterCombinations(modifier: 'constraints', [
{
'minWidth': minWidth,
'maxWidth': maxWidth,
'minHeight': minHeight,
'maxHeight': maxHeight
},
{'constraints': constraints}
]);
return true;
}());

if (overflow) {
return FleetOverflowBox(
minHeight: minHeight ?? constraints?.minHeight,
maxHeight: maxHeight ?? constraints?.maxHeight,
minWidth: minWidth ?? constraints?.minWidth,
maxWidth: maxWidth ?? constraints?.maxWidth,
alignment: alignment ?? Alignment.center,
child: this,
);
} else {
constraints ??= BoxConstraints(
minWidth: minWidth ?? 0,
maxWidth: maxWidth ?? double.infinity,
minHeight: minHeight ?? 0,
maxHeight: maxHeight ?? double.infinity,
);
return FleetConstrainedBox(
constraints: constraints,
child: this,
);
}
}

/// Applies tight size constraints to this widget.
@widgetFactory
Widget size({
Expand All @@ -87,7 +155,22 @@ extension BasicModifiers on Widget {
double? square,
bool? expand,
bool? shrink,
bool fractional = false,
bool overflow = false,
AlignmentGeometry? alignment,
}) {
assert(
!fractional || (expand == null && shrink == null),
'fractional cannot be used with expand or shrink',
);
assert(
!overflow || (expand == null && shrink == null),
'overflow cannot be used with expand or shrink',
);
assert(
overflow || alignment == null,
'alignment can only be used with overflow',
);
assert(() {
_debugCheckParameterCombinations(modifier: 'size', [
{'width': width, 'height': height},
Expand All @@ -104,14 +187,52 @@ extension BasicModifiers on Widget {
} else if (shrink ?? false) {
return FleetSizedBox.shrink(child: this);
} else {
return FleetSizedBox(
width: width ?? size?.width ?? square,
height: height ?? size?.height ?? square,
child: this,
);
width ??= size?.width ?? square;
height ??= size?.height ?? square;
if (fractional) {
return FleetFractionallySizedBox(
widthFactor: width,
heightFactor: height,
child: this,
);
} else if (overflow) {
return FleetSizedOverflowBox(
size: Size(width!, height!),
alignment: alignment ?? Alignment.center,
child: this,
);
} else {
return FleetSizedBox(
width: width,
height: height,
child: this,
);
}
}
}

/// Attempts to size the widget to a specific aspect ratio.
@widgetFactory
Widget aspectRatio(double aspectRatio) {
return FleetAspectRatio(
aspectRatio: aspectRatio,
child: this,
);
}

/// Limits this widget's size only when it's unconstrained.
@widgetFactory
Widget limit({
double maxHeight = double.infinity,
double maxWidth = double.infinity,
}) {
return FleetLimitedBox(
maxHeight: maxHeight,
maxWidth: maxWidth,
child: this,
);
}

/// Adds padding around this widget.
@widgetFactory
Widget padding({
Expand Down Expand Up @@ -255,15 +376,20 @@ extension BasicModifiers on Widget {
);
}

/// Translates this widget by [x] and [y] or an [offset].
/// Offsets this widget by [x] and [y] or an [offset].
@widgetFactory
Widget offset({
double? x,
double? y,
Offset? offset,
bool transformHitTests = true,
FilterQuality? filterQuality,
bool fractional = false,
}) {
assert(
!fractional || filterQuality == null,
'offset cannot be fractional and specify filterQuality.',
);
assert(() {
_debugCheckParameterCombinations(modifier: 'offset', [
{'x': x, 'y': y},
Expand All @@ -272,12 +398,22 @@ extension BasicModifiers on Widget {
return true;
}());

return FleetTransform.translate(
offset: offset ?? Offset(x ?? 0, y ?? 0),
transformHitTests: transformHitTests,
filterQuality: filterQuality,
child: this,
);
offset ??= Offset(x ?? 0, y ?? 0);

if (fractional) {
return FleetFractionalTranslation(
translation: offset,
transformHitTests: transformHitTests,
child: this,
);
} else {
return FleetTransform.translate(
offset: offset,
transformHitTests: transformHitTests,
filterQuality: filterQuality,
child: this,
);
}
}

/// Scales this widget by [xy] for both the x and y axis or [x] and [y]
Expand Down Expand Up @@ -423,6 +559,72 @@ extension BasicModifiers on Widget {
}
}

/// Extension-based widget modifiers, which use Fleet's drop-in replacements for
/// [DecoratedBox].
extension DecorationModifiers on Widget {
/// Paints a decoration either after (default) or before this widget.
@widgetFactory
Widget decoration({
// Common parameters for all decorations
Color? color,
DecorationImage? image,
Gradient? gradient,
List<BoxShadow>? shadows,
// BoxDecoration specific parameters
BoxBorder? border,
BorderRadiusGeometry? borderRadius,
BlendMode? backgroundBlendMode,
BoxShape? boxShape,
// ShapeDecoration specific parameters
ShapeBorder? shape,
// DecoratedBox parameters
Decoration? decoration,
DecorationPosition position = DecorationPosition.background,
}) {
assert(() {
_debugCheckParameterCombinations(modifier: 'decoration', [
{
'border': border,
'borderRadius': borderRadius,
'backgroundBlendMode': backgroundBlendMode,
'boxShape': boxShape,
},
{'shape': shape}
]);
return true;
}());

if (decoration == null) {
if (shape != null) {
decoration = ShapeDecoration(
shape: shape,
color: color,
image: image,
gradient: gradient,
shadows: shadows,
);
} else {
decoration = BoxDecoration(
color: color,
image: image,
gradient: gradient,
boxShadow: shadows,
border: border,
borderRadius: borderRadius,
shape: boxShape ?? BoxShape.rectangle,
backgroundBlendMode: backgroundBlendMode,
);
}
}

return FleetDecoratedBox(
decoration: decoration,
position: position,
child: this,
);
}
}

void _debugCheckParameterCombinations(
List<Map<String, Object?>> groups, {
required String modifier,
Expand Down
Loading

0 comments on commit e79ac71

Please sign in to comment.