有没有办法有条件地重建小部件
Is there a way to make a conditional rebuild of a widget
我正在尝试重新制作知更鸟number_change动画幻灯片
因为我想 运行 每次状态编号改变时的动画,我认为使用状态提供者会有所帮助。
我目前正在使用 Redux。
我正在使用 animatedList 添加和删除数字。
我将每个数字都列为 1-9 个垂直数字的列表,以实现上下滑动,但现在我有点卡在如何只重建发生变化的数字上。
即使 distinct: true
它们都连接到同一家商店。
我的小部件容器如下所示
class NumberColViewContainer extends StatelessWidget {
/// A bool to indicate that you have passed a set of 3 digits and starting a new one
final bool comma;
/// The [TextStyle] of the number
final TextStyle textStyle;
// The [Duration] the animation will take to slide the number into place
final Duration duration;
// The curve that is used during the animation
final Curve curve;
NumberColViewContainer(
{@required this.textStyle,
@required this.duration,
this.comma = false,
@required this.curve});
@override
Widget build(BuildContext context) {
return StoreConnector<AppState, _ViewModel>(
builder: (context, vm) {
return NumberColView(
animateTo: vm.position,
textStyle: textStyle,
duration: duration,
curve: curve,
comma: comma
);
},
converter: _ViewModel.fromStore,
distinct: true,
);
}
}
class _ViewModel {
_ViewModel({
this.position,
// this.store
});
final int position;
// final Store<AppState> store;
static _ViewModel fromStore(Store<AppState> store) {
return _ViewModel(
position: store.state.numberSlideEpicPositionState.position,
// store: store,
);
}
}
我的NumberColView
(列表位)到这个
class NumberColView extends StatefulWidget {
final int animateTo;
final bool comma;
final TextStyle textStyle;
final Duration duration;
final Curve curve;
NumberColView(
{@required this.animateTo,
@required this.textStyle,
@required this.duration,
this.comma = false,
@required this.curve})
: assert(animateTo != null && animateTo >= 0 && animateTo < 10);
@override
_NumberColState createState() => _NumberColState();
}
class _NumberColState extends State<NumberColView>
with SingleTickerProviderStateMixin {
ScrollController _scrollController;
double _elementSize = 0.0;
@override
void initState() {
super.initState();
_scrollController = new ScrollController();
WidgetsBinding.instance.addPostFrameCallback((_) {
_elementSize = _scrollController.position.maxScrollExtent / 10;
setState(() {});
_scrollController.animateTo(_elementSize * widget.animateTo,
duration: widget.duration, curve: widget.curve);
});
}
@override
void didUpdateWidget(NumberColView oldWidget) {
if (oldWidget.animateTo != widget.animateTo) {
_scrollController.animateTo(
_elementSize * widget.animateTo,
duration: widget.duration,
curve: widget.curve);
}
super.didUpdateWidget(oldWidget);
}
@override
Widget build(BuildContext context) {
// print(widget.animateTo);
return Row(
mainAxisSize: MainAxisSize.min,
children: [
IgnorePointer(
child: ConstrainedBox(
constraints: BoxConstraints(maxHeight: _elementSize),
child: SingleChildScrollView(
controller: _scrollController,
child: Column(
children: List.generate(10, (position) {
return Text(position.toString(), style: widget.textStyle);
}),
),
),
),
),
widget.comma
? Container(
child: Text(', ',
style:
TextStyle(fontSize: 16, fontWeight: FontWeight.bold)))
: Container(),
],
);
}
}
有人告诉我有一种方法可以在没有我的方法的情况下达到效果,但我找不到,所以如果有人知道更简单的其他方法,请分享
这里,就用一个setState
函数。
此函数通知框架此对象的内部状态已更改。
只需使用 statefulWidget
.
使用示例:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
var value = 0;
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Flutter is Awesome'),
),
body: Column(
children: [
Text('The new value : $value'),
OutlinedButton(
onPressed: () {
setState(() {
value++; // do your change here
});
},
child: Text('Tap to increase'))
],
)),
);
}
}
不要忘记执行 Hot restart
以确保它能正常工作。希望有用
您也可以使用 ValueListenableBuilder,在我看来这是一个更好的解决方案,因为您可以轻松地将它与其他状态管理集成 frameworks/arhitectures。
我正在尝试重新制作知更鸟number_change动画幻灯片
因为我想 运行 每次状态编号改变时的动画,我认为使用状态提供者会有所帮助。
我目前正在使用 Redux。
我正在使用 animatedList 添加和删除数字。
我将每个数字都列为 1-9 个垂直数字的列表,以实现上下滑动,但现在我有点卡在如何只重建发生变化的数字上。
即使 distinct: true
它们都连接到同一家商店。
我的小部件容器如下所示
class NumberColViewContainer extends StatelessWidget {
/// A bool to indicate that you have passed a set of 3 digits and starting a new one
final bool comma;
/// The [TextStyle] of the number
final TextStyle textStyle;
// The [Duration] the animation will take to slide the number into place
final Duration duration;
// The curve that is used during the animation
final Curve curve;
NumberColViewContainer(
{@required this.textStyle,
@required this.duration,
this.comma = false,
@required this.curve});
@override
Widget build(BuildContext context) {
return StoreConnector<AppState, _ViewModel>(
builder: (context, vm) {
return NumberColView(
animateTo: vm.position,
textStyle: textStyle,
duration: duration,
curve: curve,
comma: comma
);
},
converter: _ViewModel.fromStore,
distinct: true,
);
}
}
class _ViewModel {
_ViewModel({
this.position,
// this.store
});
final int position;
// final Store<AppState> store;
static _ViewModel fromStore(Store<AppState> store) {
return _ViewModel(
position: store.state.numberSlideEpicPositionState.position,
// store: store,
);
}
}
我的NumberColView
(列表位)到这个
class NumberColView extends StatefulWidget {
final int animateTo;
final bool comma;
final TextStyle textStyle;
final Duration duration;
final Curve curve;
NumberColView(
{@required this.animateTo,
@required this.textStyle,
@required this.duration,
this.comma = false,
@required this.curve})
: assert(animateTo != null && animateTo >= 0 && animateTo < 10);
@override
_NumberColState createState() => _NumberColState();
}
class _NumberColState extends State<NumberColView>
with SingleTickerProviderStateMixin {
ScrollController _scrollController;
double _elementSize = 0.0;
@override
void initState() {
super.initState();
_scrollController = new ScrollController();
WidgetsBinding.instance.addPostFrameCallback((_) {
_elementSize = _scrollController.position.maxScrollExtent / 10;
setState(() {});
_scrollController.animateTo(_elementSize * widget.animateTo,
duration: widget.duration, curve: widget.curve);
});
}
@override
void didUpdateWidget(NumberColView oldWidget) {
if (oldWidget.animateTo != widget.animateTo) {
_scrollController.animateTo(
_elementSize * widget.animateTo,
duration: widget.duration,
curve: widget.curve);
}
super.didUpdateWidget(oldWidget);
}
@override
Widget build(BuildContext context) {
// print(widget.animateTo);
return Row(
mainAxisSize: MainAxisSize.min,
children: [
IgnorePointer(
child: ConstrainedBox(
constraints: BoxConstraints(maxHeight: _elementSize),
child: SingleChildScrollView(
controller: _scrollController,
child: Column(
children: List.generate(10, (position) {
return Text(position.toString(), style: widget.textStyle);
}),
),
),
),
),
widget.comma
? Container(
child: Text(', ',
style:
TextStyle(fontSize: 16, fontWeight: FontWeight.bold)))
: Container(),
],
);
}
}
有人告诉我有一种方法可以在没有我的方法的情况下达到效果,但我找不到,所以如果有人知道更简单的其他方法,请分享
这里,就用一个setState
函数。
此函数通知框架此对象的内部状态已更改。
只需使用 statefulWidget
.
使用示例:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
var value = 0;
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Flutter is Awesome'),
),
body: Column(
children: [
Text('The new value : $value'),
OutlinedButton(
onPressed: () {
setState(() {
value++; // do your change here
});
},
child: Text('Tap to increase'))
],
)),
);
}
}
不要忘记执行 Hot restart
以确保它能正常工作。希望有用
您也可以使用 ValueListenableBuilder,在我看来这是一个更好的解决方案,因为您可以轻松地将它与其他状态管理集成 frameworks/arhitectures。