-
Notifications
You must be signed in to change notification settings - Fork 7.7k
[beta branch] Migrate animation sample #701
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,13 +5,13 @@ | |
import 'package:flutter/material.dart'; | ||
|
||
class TypewriterTween extends Tween<String> { | ||
TypewriterTween({String begin = '', String end}) | ||
TypewriterTween({String begin = '', String end = ''}) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's weird about this is that it doesn't seem to be possible to implement a class TypewriterTween extends Tween<String> {
late String _begin;
late String _end;
TypewriterTween({String begin = '', String end = ''}) : _begin = begin, _end = end;
@override
String get begin => _begin;
@override
String get end => _end;
@override
set begin(String s) => _begin = s;
@override
set end(String s) => _end = s;
@override
String lerp(double t) {
var cutoff = (end!.length * t).round();
return end!.substring(0, cutoff);
}
} But I can't seem to reproduce this in DartPad. This sample works just fine:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, this threw me a bit, as you probably saw. Tween takes a single type param, and then defines There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah T? is a subtype of T so it's not clear to me why this isn't working There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I thought the subtype relationship was the reverse ( |
||
: super(begin: begin, end: end); | ||
|
||
@override | ||
String lerp(double t) { | ||
var cutoff = (end.length * t).round(); | ||
return end.substring(0, cutoff); | ||
var cutoff = (end!.length * t).round(); | ||
return end!.substring(0, cutoff); | ||
} | ||
} | ||
|
||
|
@@ -26,8 +26,8 @@ class _CustomTweenDemoState extends State<CustomTweenDemo> | |
with SingleTickerProviderStateMixin { | ||
static const Duration _duration = Duration(seconds: 3); | ||
static const String message = loremIpsum; | ||
AnimationController controller; | ||
Animation<String> animation; | ||
late final AnimationController controller; | ||
late final Animation<String> animation; | ||
|
||
@override | ||
void initState() { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,23 +14,31 @@ class AnimatedListDemo extends StatefulWidget { | |
|
||
class _AnimatedListDemoState extends State<AnimatedListDemo> { | ||
final GlobalKey<AnimatedListState> _listKey = GlobalKey(); | ||
final listData = initialListData; | ||
final listData = [ | ||
UserModel(0, 'Govind', 'Dixit'), | ||
UserModel(1, 'Greta', 'Stoll'), | ||
UserModel(2, 'Monty', 'Carlo'), | ||
UserModel(3, 'Petey', 'Cruiser'), | ||
UserModel(4, 'Barry', 'Cade'), | ||
]; | ||
final initialListSize = 5; | ||
|
||
void addUser() { | ||
setState(() { | ||
var index = listData.length; | ||
listData.add( | ||
UserModel(firstName: 'New', lastName: 'Person'), | ||
UserModel(++_maxIdValue, 'New', 'Person'), | ||
); | ||
_listKey.currentState | ||
_listKey.currentState! | ||
.insertItem(index, duration: Duration(milliseconds: 300)); | ||
}); | ||
} | ||
|
||
void deleteUser(int index) { | ||
void deleteUser(int id) { | ||
setState(() { | ||
final index = listData.indexWhere((u) => u.id == id); | ||
var user = listData.removeAt(index); | ||
_listKey.currentState.removeItem( | ||
_listKey.currentState!.removeItem( | ||
index, | ||
(context, animation) { | ||
return FadeTransition( | ||
|
@@ -49,7 +57,7 @@ class _AnimatedListDemoState extends State<AnimatedListDemo> { | |
}); | ||
} | ||
|
||
Widget _buildItem(UserModel user, [int index]) { | ||
Widget _buildItem(UserModel user) { | ||
return ListTile( | ||
key: ValueKey<UserModel>(user), | ||
title: Text(user.firstName), | ||
|
@@ -59,7 +67,7 @@ class _AnimatedListDemoState extends State<AnimatedListDemo> { | |
), | ||
trailing: IconButton( | ||
icon: Icon(Icons.delete), | ||
onPressed: () => deleteUser(index), | ||
onPressed: () => deleteUser(user.id), | ||
), | ||
); | ||
} | ||
|
@@ -79,11 +87,11 @@ class _AnimatedListDemoState extends State<AnimatedListDemo> { | |
body: SafeArea( | ||
child: AnimatedList( | ||
key: _listKey, | ||
initialItemCount: initialListData.length, | ||
initialItemCount: 5, | ||
itemBuilder: (context, index, animation) { | ||
return FadeTransition( | ||
opacity: animation, | ||
child: _buildItem(listData[index], index), | ||
child: _buildItem(listData[index]), | ||
); | ||
}, | ||
), | ||
|
@@ -93,31 +101,15 @@ class _AnimatedListDemoState extends State<AnimatedListDemo> { | |
} | ||
|
||
class UserModel { | ||
const UserModel({this.firstName, this.lastName}); | ||
UserModel( | ||
this.id, | ||
this.firstName, | ||
this.lastName, | ||
); | ||
|
||
final int id; | ||
final String firstName; | ||
final String lastName; | ||
} | ||
|
||
List<UserModel> initialListData = [ | ||
UserModel( | ||
firstName: 'Govind', | ||
lastName: 'Dixit', | ||
), | ||
UserModel( | ||
firstName: 'Greta', | ||
lastName: 'Stoll', | ||
), | ||
UserModel( | ||
firstName: 'Monty', | ||
lastName: 'Carlo', | ||
), | ||
UserModel( | ||
firstName: 'Petey', | ||
lastName: 'Cruiser', | ||
), | ||
UserModel( | ||
firstName: 'Barry', | ||
lastName: 'Cade', | ||
), | ||
]; | ||
int _maxIdValue = 4; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could this be based off the length of the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe that would cause problems if items were repeatedly added and removed. For example:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ah, right. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm curious how nulls could be inserted this animation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While doing the conversion, this was a weird part for me as well.
ColorTween
is a glorified version ofTween<Color?>
, which does allow for a nullColor
value:https://github.com/flutter/flutter/blob/7c0300a3588d91542366d9efadda26fa2c9d9224/packages/flutter/lib/src/animation/tween.dart#L355
I thought about switching to
Tween<Color>
, but that would cause us to lose theColor
-specificlerp
function provided byColorTween
.In the case of this example, I don't expect the tween to ever produce a null value, but it looks like
MaterialButton
is perfectly happy to accept one and just use the default color in response:https://github.com/flutter/flutter/blob/88809aa24720705d1cd8de0bfc46faf932fe0b6e/packages/flutter/lib/src/material/material_button.dart#L180
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oof, the docs for
Tween
call this out:ColorTween and most subclasses allows null intentionally:
To me, this seems weird for users, but at least it's explicit now.