如何使用Flutter在StreamBuilder中制作动画?

时间:2019-05-13 09:31:50

标签: dart flutter

为了测试BloC设计模式,我从基本的Flutter示例开始。 StreamBuilder内部的胺化(比例类型)不起作用。

这是项目的源代码:https://github.com/fabienbellanger/flutter_bloc_example

仅在加载小部件时启动动画,而不是在每次计数器更改时启动。

[编辑]我希望每次点击“ +”时,计数器的字体大小都会增加。加载主页后,它只能运行一次。

enter image description here

IncrementBloc

import 'dart:async';

import 'package:flutter_bloc_example/src/blocs/bloc_provider.dart';

class IncrementBloc implements BlocBase {
  final int _counterInitial = 0;

  int counter;

  ///
  /// Stream to handle the counter
  ///
  StreamController<int> _counterController = StreamController<int>.broadcast();
  StreamSink<int> get _inUpdate => _counterController.sink;
  Stream<int> get outCounter => _counterController.stream;

  ///
  /// Stream to handle the action on the counter
  ///
  StreamController<String> _actionController = StreamController<String>();
  StreamSink<String> get updateCounter => _actionController.sink;

  ///
  /// Constructor
  ///
  IncrementBloc() {
    counter = _counterInitial;
    _actionController.stream.listen(_handleLogic);
  }

  void dispose() {
    _actionController.close();
    _counterController.close();
  }

  void _handleLogic(String data) {
    if (data == 'add') {
      counter = counter + 1;
    } else {
      if (counter == 0) {
        counter = 0;
      } else {
        counter = counter - 1;
      }
    }

    _inUpdate.add(counter);
  }
}

CounterHomePage

import 'package:flutter/material.dart';
import 'package:flutter_bloc_example/src/blocs/bloc_provider.dart';
import 'package:flutter_bloc_example/src/blocs/increment_bloc.dart';
import 'package:flutter_bloc_example/src/blocs/navigation_bloc.dart';
import 'package:flutter_bloc_example/src/ui/pages/tabbar_page.dart';

///
/// CounterHome class
///
class CounterHome extends StatefulWidget {
  @override
  _CounterHomeState createState() => _CounterHomeState();
}

class _CounterHomeState extends State<CounterHome> {
  @override
  Widget build(BuildContext context) {
    final IncrementBloc _incrementBloc = BlocProvider.of<IncrementBloc>(context);

    return Center(
      child: StreamBuilder<int>(
          stream: _incrementBloc.outCounter,
          initialData: _incrementBloc.counter,
          builder: (BuildContext context, AsyncSnapshot<int> snapshot) {
            return Column(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                TextCounter(
                  counter: snapshot.data,
                ),
                RaisedButton(
                  color: Colors.orange,
                  textColor: Colors.white,
                  disabledColor: Colors.grey,
                  disabledTextColor: Colors.white70,
                  padding: const EdgeInsets.all(10.0),
                  child: const Text(
                    'Go to TabBar Page',
                    style: TextStyle(fontSize: 18.0),
                  ),
                  onPressed: () {
                    Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context) {
                      return BlocProvider<NavigationBloc>(
                        bloc: NavigationBloc(),
                        child: TabBarPage(),
                      );
                    }));
                  },
                ),
              ],
            );
          }),
    );
  }
}

class TextCounter extends StatefulWidget {
  final int counter;

  const TextCounter({Key key, this.counter}) : super(key: key);

  @override
  _TextCounterState createState() => _TextCounterState();
}

class _TextCounterState extends State<TextCounter> with SingleTickerProviderStateMixin {
  AnimationController _animationController;
  Animation<double> _animationSize;
  int counter;

  @override
  void initState() {
    super.initState();

    counter = widget.counter;

    _animationController = new AnimationController(
      duration: const Duration(milliseconds: 400),
      vsync: this,
    );

    _animationController.addListener(() {
      setState(() {});
    });

    _animationSize = new Tween(begin: 5.0, end: 70.0).animate(_animationController);

    _animationController.forward();
  }

  @override
  void didUpdateWidget(TextCounter oldWidget) {
    if (counter != widget.counter) {
      setState(() {
        counter = widget.counter;

        print('didUpdateWidget');
      });
    }
    super.didUpdateWidget(oldWidget);
  }

  @override
  void dispose() {
    _animationController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    double size = _animationSize?.value;

    return Text(
      counter.toString(),
      style: TextStyle(
        fontSize: size,
        color: Colors.blue,
      ),
    );
  }
}

1 个答案:

答案 0 :(得分:0)

要在streambuilder中制作过渡动画,这非常简单,您只需使用名为AnimatedSwitcher的小部件即可:

styled-components

这里,当AnimatedSwitcher的子项发生变化时,我们使用AnimatedSwitcher为过渡设置动画,默认动画为淡入淡出动画,但是您可以通过向小部件传递TransitionBuilder来轻松指定自己的动画作为参数