Foil
Wrap a widget with Foil
, providing a rainbow shimmer
that twinkles as the accelerometer moves.
Consider holographic PokΓ©mon trading cards, some credit cards,
or an oil slick on the road.
π Table of Contents
Getting Started
Wrap a widget by providing it as Foil.child
.
Use any gradient
of choice and determine the blendMode
to mask the gradient
onto the child in different ways. Default is BlendMode.srcATop
which will
reveal the child through the gradient if the gradient has opacity or if
Foil.opacity
is provided a non-1.0
value.
- Use
BlendMode.srcIn
to paint only the gradient and use the child as a mask.
Flag isUnwrapped
toggles this Foil
's invisibility. Default is false.
When this value is changed, the gradient will smoothly animate to a disabled
state, leaving only the child
behind.
class Example extends StatelessWidget {
const Example({Key? key}): super(key: key);
@override
Widget build(BuildContext context) => FittedBox(
child: Foil(
child: const Text(
'FOIL',
style: TextStyle(fontWeight: FontWeight.w900)
),
),
);
}
Quickstart
Plop an instance of this
const Example()
in a runningListView
you've got open in a code editor.
Run terminal commandflutter pub add foil
.
import 'package:foil/foil.dart'
Accelerometer
This trading card is wrapped in twoFoil
widgets offering different gradients!
Further widget transformation provided by package:xl.
Disable this Foil
's reaction to accelerometer sensor motion by
useSensor: false
. Default is true
.
- In this case, you may want to employ a
Roll
withCrinkle
s.
Influence the intensity of this Foil
's reaction to accelerometer motion
by providing a speed
and custom Scalar
property Foil.scalar
.
- Default is
Scalar.identity
which has both ahorizontal
andvertical
multiplier of+1.0
.
Transitioning
Control how rapidly this Foil
transforms its gradient with Foil.speed
and define the animation curve
. Defaults are 150ms
and Curves.ease
.
Furthermore, provide Foil.duration to dictate how long intrinsic animations of gradient will take. Foil.duration is also used if isUnwrapped is made true as the duration over which Foil.gradient will lerp to an appropriately-Typed transparent gradient for tweening. There is hard-coded recognition for linear, radial, and sweep gradients, as well as the additional Steps variants this package provides. Falls back to a transparent LinearGradient if Type cannot be matched. Override with Foil.unwrappedGradient . Click images to view full size. |
---|
Upon completion of any tween to a new
gradient
, thisFoil
will callonEnd
, an optional void callback.
Advanced Usage
Roll
s
Wrap any Foil
(or many of them!) in a Roll
higher in the widget tree
to provide some inherited properties.
A gradient provided by an ancestral Roll
may be used by as a Foil.gradient
if one is not explicitly perscribed in the Foil
.
- If neither an ancestral
Roll
nor aFoil
dictates its owngradient
, then the default isFoils.linearLooping
. - A descendent that provides its own
Foil.gradient
will override theRoll.gradient
.
One day a
Roll
will also provide the option to "cut" any descendentFoil
from a single shared gradient sheet that covers a space the size of theRoll
.
Roll
s can also serve to provide animation properties to a descendent Foil
,
regardless of whether its serving its gradient.
Crinkle
s
These animations are in addition to any accelerometer sensors data
already animating the Foil
unless Foil.useSensors: false
.
Crinkle.smooth
is a non-animated presetCrinkle.crawling
is a very slow moving presetCrinkle.twinkling
is a little bit fasterCrinkle.vivacious
is highly-animated- Build your own or opt to
Crinkle.copyWith
a preset
isAnimated
,shouldReverse
flags- Use
period
to determine the animation loopDuration
- The
scalar
property can be used to invert, scale, or negate axes
(this is aScalar
object like aFoil
uses to scale its sensors data)
TransformGradient
This is the definition of a function
that takes in a scaled double x
and double y
and returns a GradientTransform
object. That object is used when a Foil
's
gradient shader is drawn by calling its transform()
method.
To provide a custom transformation as Crinkle.transform
, extend that class
and override transform()
, returning some Matrix4
, such as the default
for this package:
class TranslateGradient extends GradientTransform {
/// The default [TransformGradient] for `Foil`.
/// This class's [transform] method considers [TextDirection] and
/// will consider positive values as translation to the right if `ltr`
/// and translate left for positive values if `rtl`.
const TranslateGradient({required this.percentX, required this.percentY});
final double percentX, percentY;
/// Returning `null` here is equivalent to returning `Matrix4.identity`.
@override
Matrix4? transform(Rect bounds, {TextDirection? textDirection}) =>
Matrix4.translationValues(
(textDirection == TextDirection.rtl ? -1.0 : 1.0) * bounds.width * percentX,
bounds.height * percentY,
0.0,
);
}
Extra Goodies
This package also comes with some other offerings.
Some expand on Gradient
functionality, and others make them simpler to use.
Up first is named Foil.sheet
which functions like a self-contained
Foil
+ AnimatedContainer
. Stylized by a Sheet
which simply wraps
parameters for the AnimatedContainer
.
Steps
The basic premise of a gradient is to gradate between colors.
Consider new Steps
to be extensions of Gradient
s,
one each for linear, radial, and sweep,
where the colors do not gradate but instead hard-transition. Like steps!
RadialSteps
are great for making rainbows.
|SweepSteps
|RadialSteps
|LinearSteps
|
GradientUtils
Extensions
Along with the three new variety of Gradient
, this package
provides π copyWith()
methods for each existing Flutter type.
final copy = RadialGradient( colors: [. . .], stops: [. . .], center: const Alignment(0, 0), ).copyWith(center: const Alignment(-2, -2));
Even the superclass
Gradient
may be copied, providedthis
is a standard linear, radial, or sweep gradient, or one of the three new steps gradients (falls back to a standard linear gradient). Provides every potential copyable parameter from the varieties. Most useful in a scenario where a common parameter likecolors
ortransform
is to be applied to some arbitraryGradient
.
This makes it a cinch to pick out pre-rolled Foils
yet tweak them for specific scenarios--such as changing
start and end points while maintaining the list of colors.
What are Foils
?
Foils
Finally, this package is bundled with a selection of pre-defined gradients.
One such pre-rolled Foils.oilslick
has opacity within each Color
.
- But consider that the
Foil
constructor accepts an overriding
opacity
parameter for semi-transparent appearance even without
Gradient.colors
that have opacity.
Find other options like Foils.gymClassParachute
and Foils.sitAndSpin
,
then tweak them to your liking with the π Gradient.copyWith()
methods.
There is even a literal rainbow decal gradient made with the new RadialSteps type. Click image to view full size. |
---|
Reference
π API Documentation
Foil
Demo: π·ββοΈ source code, π² built APK
π£οΈ Roadmap
- Make available a
Roll
ofFoil
feature such that a developer could
deploy a single gradient sheet in a region and mask that single gradient to any
childFoil
widgets.Roll
s are implemented now, but only offer to pass aGradient
to
descendentFoil
s--not to mask them from the same gradient.
- If this package's
Gradient
support expands further, much of that functionality could be forked to an independent package. - Custom
GradientTransform
s will be investigated, for example: to deformFoils.oilslick
.
π Bugs
- Potential optimizations for
GradientTween
ing withinlerp()
, especially with the newSteps
style gradients. - Because this package's
copyWith()
method for the superclassGradient
is used when applyingCrinkle
transformation, the returned gradient is limited by the hard-coded return types of thecopyWith
method; that is to say: the three FlutterGradient
s and the threeSteps
gradients added by this package.- If a bespoke
Gradient
type is used for someFoil
that is wrapped in aRoll
whoseCrinkle
provides animation, that gradient will become aLinearGradient
with the appropriate colors at least. - In this scenario, until this bug is patched, consider transforming the
gradient prior to providing it to your
Crinkle
-animatedFoil
in order to maintain the bespokeGradient
.
- If a bespoke
Libraries
- foil
- Wrap a widget with
Foil
, providing a rainbow shimmer that twinkles as the accelerometer moves as well as tons of additional neat gradient features.