#flutter
#трепетание
Вопрос:
Я показываю какой-то анимированный пользовательский индикатор выполнения в моем приложении, он показывает некоторую ошибку
Error: The following assertion was thrown while notifying listeners for AnimationController:
'package:flutter/src/widgets/framework.dart': Failed assertion: line 4263 pos 12: '_debugLifecycleState != _ElementLifecycle.defunct': is not true.
У меня есть простая домашняя страница, на которой у меня есть панель навигации. Я просто показываю контейнер, когда навигация меняется следующим образом
SingleChildScrollView(
child: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("images/sidebg.png"),
fit: BoxFit.cover,
),
),
child: Column(
children: [
pageIndex == 0 ? DashboardScreen() : Container(),
pageIndex == 1 ? MapScreen() : Container(),
pageIndex == 3 ? ServiceCenter() : Container(),
pageIndex == 4 ? ProfileScreen() : Container(),
],
)),
),
Проблема в том, что вы можете видеть изменения страниц при изменении индекса, но когда я меняю страницу, она показывает ошибку, как я упоминал выше, в непрерывном цикле, который не останавливается.
Если я удалю этот индикатор выполнения, все будет работать нормально.
Это экран индикатора выполнения
import 'dart:math' as math;
import 'package:curved_navigation_bar/curved_navigation_bar.dart';
import 'package:sleek_circular_slider/sleek_circular_slider.dart';
import 'package:liquid_progress_indicator/liquid_progress_indicator.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_rating_bar/flutter_rating_bar.dart';
import 'package:smooth_star_rating/smooth_star_rating.dart';
class DashboardScreen extends StatefulWidget {
@override
_DashboardScreenState createState() => _DashboardScreenState();
}
class _DashboardScreenState extends State<DashboardScreen> {
@override
Widget build(BuildContext context) {
double width = MediaQuery.of(context).size.width;
double height = MediaQuery.of(context).size.height;
return Container(
child: Column(
children: [
SizedBox(
height: height * 0.05,
),
Circular_arc(),
],
),
);
}
}
final Gradient gradient = new LinearGradient(
colors: <Color>[
Colors.greenAccent.withOpacity(1.0),
Colors.yellowAccent.withOpacity(1.0),
Colors.redAccent.withOpacity(1.0),
],
stops: [
0.0,
0.5,
1.0,
],
);
class Circular_arc extends StatefulWidget {
const Circular_arc({
Key key,
}) : super(key: key);
@override
_Circular_arcState createState() => _Circular_arcState();
}
class _Circular_arcState extends State<Circular_arc>
with SingleTickerProviderStateMixin {
Animation<double> animation;
AnimationController animController;
@override
void initState() {
// TODO: implement initState
super.initState();
animController =
AnimationController(duration: Duration(seconds: 3), vsync: this);
final curvedAnimation =
CurvedAnimation(parent: animController, curve: Curves.easeInOutCubic);
animation = Tween<double>(begin: 0.0, end: 2).animate(curvedAnimation)
..addListener(() {
setState(() {});
});
animController.repeat(max: 1);
}
@override
Widget build(BuildContext context) {
double width = MediaQuery.of(context).size.width;
double height = MediaQuery.of(context).size.height;
return Container(
child: Stack(
children: [
CustomPaint(
size: Size(300, 300),
painter: ProgressArc(null, Colors.black54, true),
),
CustomPaint(
size: Size(300, 300),
painter: ProgressArc(animation.value, Colors.redAccent, false),
),
Positioned(
top: height * 0.07,
left: width * 0.2,
child: Column(
children: [
Image.asset(
'images/star-icon-fill@3x.png',
height: height * 0.045,
),
RichText(
text: new TextSpan(
// Note: Styles for TextSpans must be explicitly defined.
// Child text spans will inherit styles from parent
style: new TextStyle(
fontSize: 14.0,
color: Colors.black,
),
children: <TextSpan>[
new TextSpan(
text: '4.6',
style: new TextStyle(
fontSize: 40, fontFamily: 'UbuntuRegular')),
new TextSpan(
text: ' /5',
style: TextStyle(
fontSize: 25,
color: Colors.grey[400],
fontFamily: 'UbuntuRegular')),
],
),
),
Text(
'FIFTEEN DAYS SCORE',
style: TextStyle(
color: Colors.grey[400], fontFamily: 'UbuntuMedium'),
)
],
),
)
],
),
);
}
}
class ProgressArc extends CustomPainter {
bool isBackground;
double arc;
Color progressColor;
ProgressArc(this.arc, this.progressColor, this.isBackground);
@override
void paint(Canvas canvas, Size size) {
final rect = Rect.fromLTRB(0, 0, 300, 300);
final startAngle = -math.pi;
final sweepAngle = arc != null ? arc : math.pi;
final userCenter = false;
final paint = Paint()
..strokeCap = StrokeCap.round
..color = progressColor
..style = PaintingStyle.stroke
..strokeWidth = 10;
if (!isBackground) {
paint.shader = gradient.createShader(rect);
}
canvas.drawArc(rect, startAngle, sweepAngle, userCenter, paint);
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
// TODO: implement shouldRepaint
return true;
}
}
Ошибка в непрерывном цикле, он не останавливается. А также он запускается, когда я меняю индекс страницы (имеется в виду, когда я меняю навигацию из дома).
Ответ №1:
В вашем _CircularArcState
, пожалуйста…
- Вызов
animController.forward();
послеanimController.repeat(max: 1);
- Чтобы сохранить состояние
CircularArc
, добавьте mixinAutomaticKeepAliveClientMixin
_CircularArcState
. Затем переопределитеwantKeepAlive
и вернитеtrue
. Кроме того, вызовитеsuper.build(context);
insidebuild(...)
.
import 'dart:math' as math;
import 'dart:ui';
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: PageView(
scrollDirection: Axis.vertical,
children: [
DashboardScreen(),
Container(color: Colors.orange),
Container(color: Colors.blue),
Container(color: Colors.green),
],
),
),
);
}
}
class DashboardScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
double width = MediaQuery.of(context).size.width;
double height = MediaQuery.of(context).size.height;
return Container(
child: Column(
children: [
SizedBox(
height: height * 0.05,
),
CircularArc(),
],
),
);
}
}
final Gradient gradient = new LinearGradient(
colors: <Color>[
Colors.greenAccent.withOpacity(1.0),
Colors.yellowAccent.withOpacity(1.0),
Colors.redAccent.withOpacity(1.0),
],
stops: [0.0, 0.5, 1.0],
);
class CircularArc extends StatefulWidget {
const CircularArc({
Key key,
}) : super(key: key);
@override
_CircularArcState createState() => _CircularArcState();
}
class _CircularArcState extends State<CircularArc>
with SingleTickerProviderStateMixin, AutomaticKeepAliveClientMixin {
double width;
double height;
Animation<double> animation;
@override
void initState() {
super.initState();
final AnimationController animController =
AnimationController(duration: Duration(seconds: 3), vsync: this);
final curvedAnimation =
CurvedAnimation(parent: animController, curve: Curves.easeInOutCubic);
animation = Tween<double>(begin: 0.0, end: 2).animate(curvedAnimation)
..addListener(() {
setState(() {});
});
animController.repeat(max: 1);
animController.forward();
}
@override
bool get wantKeepAlive => true;
@override
Widget build(BuildContext context) {
super.build(context);
if (width == null amp;amp; height == null) {
width = MediaQuery.of(context).size.width;
height = MediaQuery.of(context).size.height;
}
return Container(
child: Stack(
children: [
CustomPaint(
size: Size(300, 300),
painter: ProgressArc(null, Colors.black54, true),
),
CustomPaint(
size: Size(300, 300),
painter: ProgressArc(animation.value, Colors.redAccent, false),
),
Positioned(
top: height * 0.07,
left: width * 0.2,
child: Column(
children: [
// Image.asset(
// 'images/star-icon-fill@3x.png',
// height: height * 0.045,
// ),
RichText(
text: new TextSpan(
// Note: Styles for TextSpans must be explicitly defined.
// Child text spans will inherit styles from parent
style: new TextStyle(
fontSize: 14.0,
color: Colors.black,
),
children: <TextSpan>[
new TextSpan(
text: '4.6',
style: new TextStyle(
fontSize: 40, fontFamily: 'UbuntuRegular')),
new TextSpan(
text: ' /5',
style: TextStyle(
fontSize: 25,
color: Colors.grey[400],
fontFamily: 'UbuntuRegular')),
],
),
),
Text(
'FIFTEEN DAYS SCORE',
style: TextStyle(
color: Colors.grey[400], fontFamily: 'UbuntuMedium'),
)
],
),
)
],
),
);
}
}
class ProgressArc extends CustomPainter {
bool isBackground;
double arc;
Color progressColor;
ProgressArc(this.arc, this.progressColor, this.isBackground);
@override
void paint(Canvas canvas, Size size) {
final rect = Rect.fromLTRB(0, 0, 300, 300);
final startAngle = -math.pi;
final sweepAngle = arc != null ? arc : math.pi;
final userCenter = false;
final paint = Paint()
..strokeCap = StrokeCap.round
..color = progressColor
..style = PaintingStyle.stroke
..strokeWidth = 10;
if (!isBackground) {
paint.shader = gradient.createShader(rect);
}
canvas.drawArc(rect, startAngle, sweepAngle, userCenter, paint);
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
// TODO: implement shouldRepaint
return true;
}
}
Комментарии:
1. @UmaizKhan что не работает? Как анимация, так и сохранение состояния?
2. @UmaizKhan Я добавил весь пример кода. Пожалуйста, смотрите обновленный ответ.