flutter - 水平列表视图动画
问题描述
我正在尝试创建一个类似列表视图的列表视图,我得到的东西还不错,但它不像运球时那么流畅。
我猜这是因为我调用 setState 的次数太多,并且它在动画期间更新了树,但我不知道如何使它更平滑,也许只调用一次 setState。我正在使用继承的小部件通过我的树传递我的状态,这是我的编辑状态的定义
void onChangeIndex (int newIndex) {
fadeText(_index, newIndex);
changePosition(newIndex);
}
void fadeText(int oldIndex,int newIndex) async {
setState(() {
_visible[oldIndex] = !_visible[oldIndex];
});
await Future.delayed(Duration(milliseconds: 300));
setState(() {
_visible[newIndex] = !_visible[newIndex];
debugPrint(_visible[oldIndex].toString());
});
}
void changePosition(newIndex) async {
await Future.delayed(Duration(milliseconds: 50));
setState(() {
_index = newIndex;
_scrollController.animateTo((_index)*320.0, duration: Duration(milliseconds: 800), curve: Curves.fastOutSlowIn);
});
}
这部分在我拖动列表视图时被调用,它的工作是滚动列表视图并为我的文本设置动画
这是我的列表视图中包含的卡片,如果结构混乱,我很抱歉,我对扑腾还很陌生。
GestureDetector(
child: Padding(
padding: EdgeInsets.all(6.0),
child: Card(
elevation: 0.0,
color: Colors.transparent,
child: Container(
width: 295.0,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Row(
children:<Widget>[
Expanded(
child:
Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(15.0)),
),
elevation: 5.0,
child: ClipRRect(
borderRadius: BorderRadius.circular(10.0),
child: Image.asset('images/paris.jpg', fit: BoxFit.contain),
),
)
),
]
),
Row(
children: <Widget>[
Expanded(
child: AnimatedOpacity(
opacity: StateManager.of(context).visible[widget.index] ? 1.0 : 0.0,
duration: Duration(milliseconds: 300),
child: Container(
height: 24.0,
child: Padding(
padding: const EdgeInsets.only(
left: 8.0
),
child: Text(
"Paris, France",
style: TextStyle(
color: Color.fromRGBO(0,0,0,0.9),
fontSize: 24.0,
fontWeight: FontWeight.bold,
),
),
)
)
)
),
],
),
Row(
children: <Widget>[
Expanded(
child: AnimatedOpacity(
opacity: StateManager.of(context).visible[widget.index] ? 1.0 : 0.0,
duration: Duration(milliseconds: 300),
child: Container(
height: 30.0,
child: Padding(
padding: const EdgeInsets.only(
left: 8.0
),
child: Text(
"Visiter ou bien aller au travail à vélo facilement grâce aux nombreux parkings à vélo présent dans cette ville.",
style: TextStyle(
color: Color.fromRGBO(0,0,0,0.7),
fontSize: 12.0,
fontWeight: FontWeight.bold,
),
),
)
)
)
),
],
),
])),
// shape: RoundedRectangleBorder(
// borderRadius: BorderRadius.all(Radius.circular(15.0)),
// ),
),
),
onHorizontalDragEnd: (details) {
var cardIndex = StateManager.of(context).index;
if(details.velocity.pixelsPerSecond.dx > 0) {
if(cardIndex>0) {
StateManager.of(context).onChangeIndex(cardIndex-1);
}
}else if(details.velocity.pixelsPerSecond.dx < 0){
if(cardIndex<2) {
StateManager.of(context).onChangeIndex(cardIndex+1);
}
}
},
);
如果您知道如何改进设置状态以使动画更流畅的方式,那将对我有很大帮助。
解决方案
首先,在通话setState
后使用await
是不好的。如果小部件由于用户导航到不同的页面而不再存在,则会引发异常。相反,这是在 Flutter 中创建交错(延迟)动画的方法。
这是一个由PageController
. 文本淡入淡出动画的控制器可以在项目的状态中找到:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Playground',
home: DestinationsPage(),
);
}
}
class DestinationsPage extends StatefulWidget {
@override
_DestinationsPageState createState() => _DestinationsPageState();
}
class _DestinationsPageState extends State<DestinationsPage> {
PageController _pageController;
int _selectedPage = 0;
@override
void initState() {
super.initState();
_pageController = PageController(
initialPage: 0,
viewportFraction: 0.8,
)..addListener(_updateSelectedPage);
}
void _updateSelectedPage() {
final closestPage = _pageController.page.round();
final isClosestPageSelected = (_pageController.page - closestPage).abs() < 0.2;
final selectedPage = isClosestPageSelected ? closestPage : null;
if (_selectedPage != selectedPage) {
setState(() {
_selectedPage = selectedPage;
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Destinations')),
body: PageView.builder(
controller: _pageController,
itemBuilder: (context, index) {
return _DestinationItem(
page: index,
selected: (index == _selectedPage),
);
},
),
);
}
}
class _DestinationItem extends StatefulWidget {
// some content, in this case just
final int page;
// indicates that the page is selected and that the text should be visible
final bool selected;
const _DestinationItem({Key key, this.page, this.selected}) : super(key: key);
@override
_DestinationItemState createState() => _DestinationItemState();
}
class _DestinationItemState extends State<_DestinationItem> with SingleTickerProviderStateMixin<_DestinationItem> {
AnimationController _textTransitionController;
@override
void initState() {
super.initState();
_textTransitionController = AnimationController(
vsync: this,
duration: Duration(milliseconds: 400),
value: widget.selected ? 1.0 : 0.0,
);
}
@override
void didUpdateWidget(_DestinationItem oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.selected != oldWidget.selected) {
if (widget.selected) {
_textTransitionController.forward();
} else {
_textTransitionController.reverse();
}
}
}
@override
void dispose() {
// important call, otherwise throws error if the PageView destroys
// the widget while the fade transition is still running
_textTransitionController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.symmetric(horizontal: 8.0),
child: Column(
children: <Widget>[
Container(
height: 200.0,
color: Colors.orange,
margin: EdgeInsets.symmetric(horizontal: 8.0),
child: Center(
child: Text('Image ${widget.page}'),
),
),
SizedBox(height: 16.0),
FadeTransition(
opacity: _textTransitionController,
child: Text(
'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.'),
)
],
),
);
}
}
推荐阅读
- javascript - 鼠标悬停模拟触发工具提示 - JQuery Mobile / Javascript
- ruby-on-rails - Rails Action Mailer 未显示带有布局的正文
- python - 使用 python 从 tr balise 导入数据
- docker - 如何有条件地拉取 Docker 镜像的最新标签,而不是使用缓存版本?
- cv2 - 如何消除错误:“ImportError:DLL 加载失败:找不到指定的模块。” 在 jupyter notebook 中导入 cv2 时
- c# - Page.OnAppearing 中的 Xamarin.Forms Page.DisplayAlert
- c# - 处理 Blazor 时,在 CefSharp WinForms 中处理自定义标题的最佳方法是什么?
- testing - 它是运行 infinispan-server 10 的新 arquillian 容器吗?
- sql-server - SSIS派生列从字符串中删除文本,只保留数值
- intellij-idea - 包结构的 IntelliJ 设置