为了测试BloC设计模式,我从基本的Flutter示例开始。在StreamBuilder中的缩放类型动画不起作用。
这是项目的源代码: https://github.com/fabienbellanger/flutter_bloc_example。
动画仅在小部件加载时启动,而不是每次计数器更改时都启动。
[编辑] 我希望每次点击“+”时,计数器的字体大小都会增长。它只能在加载主页后工作一次。 输入图像描述 IncrementBloc
这是项目的源代码: https://github.com/fabienbellanger/flutter_bloc_example。
动画仅在小部件加载时启动,而不是每次计数器更改时都启动。
[编辑] 我希望每次点击“+”时,计数器的字体大小都会增长。它只能在加载主页后工作一次。 输入图像描述 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);
}
}
计数器主页
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,
),
);
}
}