2

我正在尝试重新创建 robinhood 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(),
      ],
    );
  }
}

有些东西告诉我有一种方法可以在没有我的方法的情况下达到效果,但我找不到,所以如果有人知道另一种更简单的方法,请分享

4

2 回答 2

2

您也可以使用ValueListenableBuilder,从我的角度来看,这是一个更好的解决方案,因为您可以轻松地将它与其他状态管理框架/架构集成。

于 2021-02-09T09:46:20.940 回答
1

在这里,只是使用一个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以确保它会起作用。希望它会有用

于 2021-02-08T23:48:22.317 回答