【问题标题】:Is there a way to make a conditional rebuild of a widget有没有办法对小部件进行有条件的重建
【发布时间】:2021-02-06 17:28:59
【问题描述】:

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

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

【问题讨论】:

  • 哪种方法?动画还是状态管理?
  • 我可以使用 redux 创建动画,1. 我只想重建更改后的 digit 小部件。 2. 由于 redux 更多的是关于全局存储,它的可重用性和灵活性不高,我无法用简单的方法来实现整个小部件,例如 setState()@KabirouAgouda
  • 状态管理@KabirouAgouda

标签: flutter flutter-animation flutter-redux


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2019-06-27
      • 2020-10-29
      • 1970-01-01
      • 2017-04-27
      • 1970-01-01
      • 2020-04-24
      • 2010-12-01
      • 1970-01-01
      • 2020-06-10
      相关资源
      最近更新 更多