如何在flutter中创建如下圆形动画
How to create the following circular animation in flutter
- 暗部不断循环。
- 深色部分的大小与加载的数据量成正比。
示例:- 当加载了 40% 的数据时,暗循环部分是圆周的 40%。当加载 60% 的数据时,黑色循环部分是圆周的 60%。等等
第一次添加:
dependencies:
percent_indicator: ^3.4.0
然后示例:
import 'package:flutter/material.dart';
import 'package:percent_indicator_example/sample_circular_page.dart';
import 'package:percent_indicator_example/sample_linear_page.dart';
void main() {
runApp(MaterialApp(home: Scaffold(body: SamplePage())));
}
class SamplePage extends StatefulWidget {
@override
_SamplePageState createState() => _SamplePageState();
}
class _SamplePageState extends State<SamplePage> {
void _openPage(Widget page) {
Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) => page,
),
);
}
@override
Widget build(BuildContext context) {
return Container(
child: Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
MaterialButton(
color: Colors.blueAccent,
child: Text("Circular Library"),
onPressed: () => _openPage(SampleCircularPage()),
),
Padding(
padding: EdgeInsets.all(20.0),
),
MaterialButton(
color: Colors.blueAccent,
child: Text("Linear Library"),
onPressed: () => _openPage(SampleLinearPage()),
),
],
),
),
);
}
}
这是我创建这个动画的尝试:
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: Scaffold(
body: HomePage(),
),
);
}
}
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage>
with SingleTickerProviderStateMixin {
late final AnimationController controller;
double percent = 0.0;
// ** Addition in @mmcdon20 code - Start
changePercent() {
// 20 frame is enough to beat eye, that's why I used
// 50 refresh/second to keep animation smooth
Future.delayed(
const Duration(milliseconds: 20), // Adjust accordingly.
() {
setState(() {
percent += 0.005; // Adjust accordingly.
});
print('........................');
if (percent < 1) {
changePercent();
}
},
);
}
// ** Addition in @mmcdon20 code - End
@override
void initState() {
super.initState();
controller = AnimationController(
duration: const Duration(seconds: 2),
vsync: this,
)
..animateTo(1)
..repeat();
// ** Addition in @mmcdon20 code - Start
changePercent();
// ** Addition in @mmcdon20 code - End
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
CustomProgressIndicator(
value: percent,
color: Colors.orange,
controller: controller,
width: 200,
height: 200,
strokeWidth: 10,
// curve: Curves.slowMiddle, // ** Eliminationated from @mmcdon20 code
),
// ** Eliminationated from @mmcdon20 code - Start
// Slider(
// value: percent,
// onChanged: (v) {
// setState(() {
// percent = v;
// });
// },
// ),
// ** Eliminationated from @mmcdon20 code - End
],
),
);
}
}
class CustomProgressIndicator extends StatelessWidget {
const CustomProgressIndicator({
Key? key,
required this.color,
required this.value,
required this.controller,
required this.width,
required this.height,
required this.strokeWidth,
this.curve = Curves.linear,
}) : super(key: key);
final Color color;
final double value;
final AnimationController controller;
final double width;
final double height;
final double strokeWidth;
final Curve curve;
@override
Widget build(BuildContext context) {
return RotationTransition(
turns: CurvedAnimation(
parent: controller,
curve: curve,
),
child: SizedBox(
width: width,
height: height,
child: CircularProgressIndicator(
strokeWidth: strokeWidth,
color: color,
backgroundColor: color.withOpacity(.2),
value: value,
),
),
);
}
}
- 暗部不断循环。
- 深色部分的大小与加载的数据量成正比。
示例:- 当加载了 40% 的数据时,暗循环部分是圆周的 40%。当加载 60% 的数据时,黑色循环部分是圆周的 60%。等等
第一次添加:
dependencies:
percent_indicator: ^3.4.0
然后示例:
import 'package:flutter/material.dart';
import 'package:percent_indicator_example/sample_circular_page.dart';
import 'package:percent_indicator_example/sample_linear_page.dart';
void main() {
runApp(MaterialApp(home: Scaffold(body: SamplePage())));
}
class SamplePage extends StatefulWidget {
@override
_SamplePageState createState() => _SamplePageState();
}
class _SamplePageState extends State<SamplePage> {
void _openPage(Widget page) {
Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) => page,
),
);
}
@override
Widget build(BuildContext context) {
return Container(
child: Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
MaterialButton(
color: Colors.blueAccent,
child: Text("Circular Library"),
onPressed: () => _openPage(SampleCircularPage()),
),
Padding(
padding: EdgeInsets.all(20.0),
),
MaterialButton(
color: Colors.blueAccent,
child: Text("Linear Library"),
onPressed: () => _openPage(SampleLinearPage()),
),
],
),
),
);
}
}
这是我创建这个动画的尝试:
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: Scaffold(
body: HomePage(),
),
);
}
}
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage>
with SingleTickerProviderStateMixin {
late final AnimationController controller;
double percent = 0.0;
// ** Addition in @mmcdon20 code - Start
changePercent() {
// 20 frame is enough to beat eye, that's why I used
// 50 refresh/second to keep animation smooth
Future.delayed(
const Duration(milliseconds: 20), // Adjust accordingly.
() {
setState(() {
percent += 0.005; // Adjust accordingly.
});
print('........................');
if (percent < 1) {
changePercent();
}
},
);
}
// ** Addition in @mmcdon20 code - End
@override
void initState() {
super.initState();
controller = AnimationController(
duration: const Duration(seconds: 2),
vsync: this,
)
..animateTo(1)
..repeat();
// ** Addition in @mmcdon20 code - Start
changePercent();
// ** Addition in @mmcdon20 code - End
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
CustomProgressIndicator(
value: percent,
color: Colors.orange,
controller: controller,
width: 200,
height: 200,
strokeWidth: 10,
// curve: Curves.slowMiddle, // ** Eliminationated from @mmcdon20 code
),
// ** Eliminationated from @mmcdon20 code - Start
// Slider(
// value: percent,
// onChanged: (v) {
// setState(() {
// percent = v;
// });
// },
// ),
// ** Eliminationated from @mmcdon20 code - End
],
),
);
}
}
class CustomProgressIndicator extends StatelessWidget {
const CustomProgressIndicator({
Key? key,
required this.color,
required this.value,
required this.controller,
required this.width,
required this.height,
required this.strokeWidth,
this.curve = Curves.linear,
}) : super(key: key);
final Color color;
final double value;
final AnimationController controller;
final double width;
final double height;
final double strokeWidth;
final Curve curve;
@override
Widget build(BuildContext context) {
return RotationTransition(
turns: CurvedAnimation(
parent: controller,
curve: curve,
),
child: SizedBox(
width: width,
height: height,
child: CircularProgressIndicator(
strokeWidth: strokeWidth,
color: color,
backgroundColor: color.withOpacity(.2),
value: value,
),
),
);
}
}