Last active
October 30, 2022 06:19
-
-
Save Kurogoma4D/9146fec775c5e052eb72e6f7474a904d to your computer and use it in GitHub Desktop.
This file contains hidden or 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
import 'package:flutter/material.dart'; | |
void main() => runApp(MyApp()); | |
typedef ValueTransitionBuilder<T> = Widget Function( | |
BuildContext context, | |
T value, | |
Widget? child, | |
); | |
class AutoTransition<T> extends StatefulWidget { | |
const AutoTransition({ | |
super.key, | |
required this.property, | |
required this.duration, | |
this.curve = Curves.linear, | |
required this.builder, | |
this.child, | |
}); | |
final T property; | |
final Duration duration; | |
final Curve curve; | |
final ValueTransitionBuilder<T> builder; | |
final Widget? child; | |
@override | |
State<AutoTransition<T>> createState() => _AutoTransitionState(); | |
} | |
class _AutoTransitionState<T> extends State<AutoTransition<T>> | |
with SingleTickerProviderStateMixin { | |
late final _controller = | |
AnimationController(vsync: this, duration: widget.duration); | |
Animation<T>? _animation; | |
Animation<T> get _defaultAnimation => | |
Tween(begin: widget.property, end: widget.property).animate(_controller); | |
@override | |
void didUpdateWidget(covariant AutoTransition<T> oldWidget) { | |
super.didUpdateWidget(oldWidget); | |
final curved = CurvedAnimation( | |
parent: _controller, | |
curve: widget.curve, | |
); | |
_animation = | |
Tween(begin: oldWidget.property, end: widget.property).animate(curved); | |
_controller.forward(from: 0); | |
} | |
@override | |
Widget build(BuildContext context) { | |
final animation = _animation ?? _defaultAnimation; | |
return AnimatedBuilder( | |
animation: animation, | |
builder: (context, child) => | |
widget.builder(context, animation.value, child), | |
child: widget.child, | |
); | |
} | |
} | |
class MyApp extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return MaterialApp( | |
title: 'Flutter Demo', | |
debugShowCheckedModeBanner: false, | |
theme: ThemeData( | |
primarySwatch: Colors.blue, | |
), | |
home: const MyHomePage(), | |
); | |
} | |
} | |
class MyHomePage extends StatefulWidget { | |
const MyHomePage({ | |
Key? key, | |
}) : super(key: key); | |
@override | |
State<MyHomePage> createState() => _MyHomePageState(); | |
} | |
class _MyHomePageState extends State<MyHomePage> { | |
double someValue = 0.0; | |
void _setValue() { | |
setState(() { | |
someValue = someValue == 0.0 ? 1.0 : 0.0; | |
}); | |
} | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: AppBar( | |
title: const Text('Hello'), | |
), | |
body: Center( | |
child: GestureDetector( | |
onTap: _setValue, | |
child: AutoTransition<double>( | |
duration: const Duration(milliseconds: 300), | |
property: someValue, | |
builder: (context, value, _) => Container( | |
width: 100, | |
height: 100, | |
color: Colors.amber, | |
child: Center(child: Text(value.toStringAsFixed(3))), | |
), | |
), | |
), | |
), | |
); | |
} | |
} |
This file contains hidden or 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
import 'package:flutter/material.dart'; | |
void main() => runApp(const MyApp()); | |
typedef ValueTransitionBuilder<T> = Widget Function( | |
BuildContext context, | |
T value, | |
Widget? child, | |
); | |
class AutoTransition<T> extends StatefulWidget { | |
const AutoTransition({ | |
super.key, | |
required this.property, | |
required this.duration, | |
this.curve = Curves.linear, | |
required this.builder, | |
this.child, | |
}); | |
final T property; | |
final Duration duration; | |
final Curve curve; | |
final ValueTransitionBuilder<T> builder; | |
final Widget? child; | |
@override | |
State<AutoTransition<T>> createState() => _AutoTransitionState(); | |
} | |
class _AutoTransitionState<T, TTween extends Tween<T?>> | |
extends State<AutoTransition<T>> with SingleTickerProviderStateMixin { | |
late final _controller = | |
AnimationController(vsync: this, duration: widget.duration); | |
Animation<T?>? _animation; | |
Animation<T?> get _defaultAnimation => | |
_generateTween(widget.property, widget.property).animate(_controller); | |
@override | |
void didUpdateWidget(covariant AutoTransition<T> oldWidget) { | |
super.didUpdateWidget(oldWidget); | |
final curved = CurvedAnimation( | |
parent: _controller, | |
curve: widget.curve, | |
); | |
_animation = | |
_generateTween(oldWidget.property, widget.property).animate(curved); | |
_controller.forward(from: 0); | |
} | |
@override | |
Widget build(BuildContext context) { | |
final animation = _animation ?? _defaultAnimation; | |
return AnimatedBuilder( | |
animation: animation, | |
builder: (context, child) => | |
widget.builder(context, animation.value ?? widget.property, child), | |
child: widget.child, | |
); | |
} | |
TTween _generateTween(T begin, T end) { | |
final result = () { | |
if (begin is Color) { | |
return ColorTween(begin: begin, end: end as Color); | |
} | |
if (begin is Size) { | |
return SizeTween(begin: begin, end: end as Size); | |
} | |
return Tween<T>(begin: begin, end: end); | |
}(); | |
return result as TTween; | |
} | |
} | |
class MyApp extends StatelessWidget { | |
const MyApp({super.key}); | |
@override | |
Widget build(BuildContext context) { | |
return MaterialApp( | |
title: 'Flutter Demo', | |
debugShowCheckedModeBanner: false, | |
theme: ThemeData( | |
primarySwatch: Colors.blue, | |
), | |
home: const MyHomePage(), | |
); | |
} | |
} | |
class MyHomePage extends StatefulWidget { | |
const MyHomePage({ | |
Key? key, | |
}) : super(key: key); | |
@override | |
State<MyHomePage> createState() => _MyHomePageState(); | |
} | |
class _MyHomePageState extends State<MyHomePage> { | |
Size someSize = const Size(100, 100); | |
void _setValue() { | |
setState(() { | |
someSize += const Offset(10, 10); | |
}); | |
} | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: AppBar( | |
title: const Text('Hello'), | |
), | |
body: Center( | |
child: GestureDetector( | |
onTap: _setValue, | |
child: AutoTransition<Size>( | |
duration: const Duration(seconds: 1), | |
property: someSize, | |
builder: (context, value, _) => Container( | |
width: value.width, | |
height: value.height, | |
color: Colors.blue, | |
), | |
), | |
), | |
), | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment