有没有办法有条件地重建小部件

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。