Skip to content
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

Integrate some widgets with painter #79

Closed
wants to merge 12 commits into from
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*___Generated_by_IDEA___*/

package com.example.example;

/* This stub is only used by the IDE. It is NOT the BuildConfig class actually packed into the APK */
public final class BuildConfig {
public final static boolean DEBUG = Boolean.parseBoolean(null);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/*___Generated_by_IDEA___*/

package com.example.example;

/* This stub is only used by the IDE. It is NOT the Manifest class actually packed into the APK */
public final class Manifest {
}
7 changes: 7 additions & 0 deletions example/android/app/src/main/gen/com/example/example/R.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/*___Generated_by_IDEA___*/

package com.example.example;

/* This stub is only used by the IDE. It is NOT the R class actually packed into the APK */
public final class R {
}
9 changes: 2 additions & 7 deletions flutter_spinkit.iml
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,15 @@
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/lib" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/.dart_tool" />
<excludeFolder url="file://$MODULE_DIR$/.idea" />
<excludeFolder url="file://$MODULE_DIR$/.pub" />
<excludeFolder url="file://$MODULE_DIR$/build" />
<excludeFolder url="file://$MODULE_DIR$/example/.dart_tool" />
<excludeFolder url="file://$MODULE_DIR$/example/.pub" />
<excludeFolder url="file://$MODULE_DIR$/example/build" />
</content>
<orderEntry type="jdk" jdkName="Android API 25 Platform" jdkType="Android SDK" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Dart Packages" level="project" />
<orderEntry type="library" name="Dart SDK" level="project" />
<orderEntry type="library" name="Flutter Plugins" level="project" />
<orderEntry type="library" name="Dart Packages" level="project" />
</component>
</module>
66 changes: 50 additions & 16 deletions lib/src/double_bounce.dart
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';

class SpinKitDoubleBounce extends StatefulWidget {
const SpinKitDoubleBounce({
Key key,
this.color,
@required this.color,
this.size = 50.0,
this.itemBuilder,
this.duration = const Duration(milliseconds: 2000),
this.controller,
}) : assert(!(itemBuilder is IndexedWidgetBuilder && color is Color) && !(itemBuilder == null && color == null),
'You should specify either a itemBuilder or a color'),
}) : assert(color != null),
assert(size != null),
super(key: key);

final Color color;
final double size;
final IndexedWidgetBuilder itemBuilder;
final Duration duration;
final AnimationController controller;

Expand All @@ -32,9 +30,9 @@ class _SpinKitDoubleBounceState extends State<SpinKitDoubleBounce> with SingleTi
super.initState();

_controller = (widget.controller ?? AnimationController(vsync: this, duration: widget.duration))
..addListener(() => setState(() {}))
..repeat(reverse: true);
_animation = Tween(begin: -1.0, end: 1.0).animate(CurvedAnimation(parent: _controller, curve: Curves.easeInOut));
_animation =
Tween(begin: -1.0, end: 1.0).animate(CurvedAnimation(parent: _controller, curve: Curves.easeInOut));
}

@override
Expand All @@ -46,18 +44,54 @@ class _SpinKitDoubleBounceState extends State<SpinKitDoubleBounce> with SingleTi
@override
Widget build(BuildContext context) {
return Center(
child: Stack(
children: List.generate(2, (i) {
return Transform.scale(
scale: (1.0 - i - _animation.value.abs()).abs(),
child: SizedBox.fromSize(size: Size.square(widget.size), child: _itemBuilder(i)),
child: AnimatedBuilder(
animation: _animation,
builder: (context, _) {
return CustomPaint(
size: Size.square(widget.size),
painter: DoubleBouncePainter(
color: widget.color,
opacity: 0.6,
doubleBounceSize: _animation.value.abs() * widget.size,
),
);
}),
},
),
);
}
}

class DoubleBouncePainter extends CustomPainter {
DoubleBouncePainter({
@required this.doubleBounceSize,
@required double opacity,
@required Color color,
}) : _doubleBouncePaint = Paint()
..color = color.withOpacity(opacity)
..style = PaintingStyle.fill
..isAntiAlias = true;

final double doubleBounceSize;
final Paint _doubleBouncePaint;

@override
void paint(Canvas canvas, Size size) {
final centerX = size.width / 2.0;
final centerY = size.height / 2.0;
canvas.drawCircle(
Offset(centerX, centerY),
doubleBounceSize / 2,
_doubleBouncePaint,
);
canvas.drawCircle(
Offset(centerX, centerY),
size.longestSide / 2 - (doubleBounceSize / 2),
_doubleBouncePaint,
);
}

Widget _itemBuilder(int index) => widget.itemBuilder != null
? widget.itemBuilder(context, index)
: DecoratedBox(decoration: BoxDecoration(shape: BoxShape.circle, color: widget.color.withOpacity(0.6)));
@override
bool shouldRepaint(DoubleBouncePainter oldDelegate) {
return oldDelegate.doubleBounceSize != doubleBounceSize;
}
}
68 changes: 48 additions & 20 deletions lib/src/pulse.dart
Original file line number Diff line number Diff line change
@@ -1,39 +1,39 @@
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';

class SpinKitPulse extends StatefulWidget {
const SpinKitPulse({
Key key,
this.color,
@required this.color,
this.size = 50.0,
this.itemBuilder,
this.duration = const Duration(seconds: 1),
this.controller,
}) : assert(!(itemBuilder is IndexedWidgetBuilder && color is Color) && !(itemBuilder == null && color == null),
'You should specify either a itemBuilder or a color'),
}) : assert(color != null),
assert(size != null),
super(key: key);

final Color color;
final double size;
final IndexedWidgetBuilder itemBuilder;
final Duration duration;
final AnimationController controller;

@override
_SpinKitPulseState createState() => _SpinKitPulseState();
}

class _SpinKitPulseState extends State<SpinKitPulse> with SingleTickerProviderStateMixin {
class _SpinKitPulseState extends State<SpinKitPulse>
with SingleTickerProviderStateMixin {
AnimationController _controller;
Animation<double> _animation;

@override
void initState() {
super.initState();

_controller = (widget.controller ?? AnimationController(vsync: this, duration: widget.duration))
..addListener(() => setState(() {}))
_controller = (widget.controller ??
AnimationController(vsync: this, duration: widget.duration))
..repeat();

_animation = CurveTween(curve: Curves.easeInOut).animate(_controller);
}

Expand All @@ -46,20 +46,48 @@ class _SpinKitPulseState extends State<SpinKitPulse> with SingleTickerProviderSt
@override
Widget build(BuildContext context) {
return Center(
child: Opacity(
opacity: 1.0 - _animation.value,
child: Transform.scale(
scale: _animation.value,
child: SizedBox.fromSize(
child: AnimatedBuilder(
animation: _animation,
builder: (context, _) {
return CustomPaint(
size: Size.square(widget.size),
child: _itemBuilder(0),
),
),
painter: PulsePainter(
color: widget.color,
opacity: 1.0 - _animation.value,
pulseSize: _animation.value * widget.size,
),
);
},
),
);
}

Widget _itemBuilder(int index) => widget.itemBuilder != null
? widget.itemBuilder(context, index)
: DecoratedBox(decoration: BoxDecoration(shape: BoxShape.circle, color: widget.color));
}

class PulsePainter extends CustomPainter {
PulsePainter({
@required this.pulseSize,
@required double opacity,
@required Color color,
}) : _pulsePaint = Paint()
..color = color.withOpacity(opacity)
..style = PaintingStyle.fill
..isAntiAlias = true;



final double pulseSize;
final Paint _pulsePaint;


@override
void paint(Canvas canvas, Size size) {
final centerX = size.width / 2.0;
final centerY = size.height / 2.0;
canvas.drawCircle(Offset(centerX, centerY), pulseSize/2, _pulsePaint);
}

@override
bool shouldRepaint(PulsePainter oldDelegate) {
return oldDelegate.pulseSize != pulseSize;
}
}
78 changes: 65 additions & 13 deletions lib/src/pumping_heart.dart
Original file line number Diff line number Diff line change
@@ -1,24 +1,21 @@
import 'dart:math' as math show pow;

import 'package:flutter/material.dart' show Icons;
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';

class SpinKitPumpingHeart extends StatefulWidget {
const SpinKitPumpingHeart({
Key key,
this.color,
@required this.color,
this.size = 50.0,
this.itemBuilder,
this.duration = const Duration(milliseconds: 2400),
this.controller,
}) : assert(!(itemBuilder is IndexedWidgetBuilder && color is Color) && !(itemBuilder == null && color == null),
'You should specify either a itemBuilder or a color'),
}) : assert(color != null),
assert(size != null),
super(key: key);

final Color color;
final double size;
final IndexedWidgetBuilder itemBuilder;
final Duration duration;
final AnimationController controller;

Expand All @@ -34,9 +31,10 @@ class _SpinKitPumpingHeartState extends State<SpinKitPumpingHeart> with SingleTi
void initState() {
super.initState();

_controller = (widget.controller ?? AnimationController(vsync: this, duration: widget.duration))..repeat();
_animation = Tween(begin: 1.0, end: 1.25)
.animate(CurvedAnimation(parent: _controller, curve: const Interval(0.0, 1.0, curve: SpinKitPumpCurve())));
_controller = (widget.controller ?? AnimationController(vsync: this, duration: widget.duration))
..repeat();
_animation = Tween(begin: 1.0, end: 1.25).animate(
CurvedAnimation(parent: _controller, curve: const Interval(0.0, 1.0, curve: SpinKitPumpCurve())));
}

@override
Expand All @@ -47,12 +45,66 @@ class _SpinKitPumpingHeartState extends State<SpinKitPumpingHeart> with SingleTi

@override
Widget build(BuildContext context) {
return ScaleTransition(scale: _animation, child: _itemBuilder(0));
return ScaleTransition(
scale: _animation,
child: CustomPaint(
size: Size.square(widget.size),
painter: HeartPainter(
color: widget.color,
),
),
);
}
}

class HeartPainter extends CustomPainter {
HeartPainter({
@required Color color,
}) : _heartPaint = Paint()
..color = color
..style = PaintingStyle.fill
..isAntiAlias = true;

final Paint _heartPaint;

@override
void paint(Canvas canvas, Size size) {
final double width = size.width;
final double height = size.height;

final Path heartPath = Path();

Widget _itemBuilder(int index) => widget.itemBuilder != null
? widget.itemBuilder(context, index)
: Icon(Icons.favorite, color: widget.color, size: widget.size);
//creating heart left half
heartPath.moveTo(0.5 * width, height * 0.15);
heartPath.cubicTo(
0.2 * width,
height * -0.2,
-0.2 * width,
height * 0.3,
0.1 * width,
height * 0.6,
);
heartPath.lineTo(0.5 * width, height);

//creating heart left half
heartPath.moveTo(0.5 * width, height * 0.15);
heartPath.cubicTo(
0.8 * width,
height * -0.2,
1.2 * width,
height * 0.3,
0.9 * width,
height * 0.6,
);
heartPath.lineTo(0.5 * width, height);

canvas.drawPath(heartPath, _heartPaint);
}

@override
bool shouldRepaint(HeartPainter oldDelegate) {
return oldDelegate._heartPaint != _heartPaint;
}
}

class SpinKitPumpCurve extends Curve {
Expand Down
Loading