Flutter单个Widget内多文本循环淡入淡出效果如何实现
多段文本循环淡入淡出实现方案
首先调整核心逻辑,支持多文本轮播,对齐目标效果的时间节奏:文本展示停留2秒→2秒淡出→切换文本→2秒淡入→停留2秒循环,修改内容如下:
- 定义多段文本列表存储需要轮播的所有文案
- 新增当前展示文本索引变量跟踪轮播进度
- 调整opacity控制逻辑,对齐淡入淡出与文本切换的时序
- 使用Timer控制动画循环,dispose时销毁Timer避免内存泄漏
完整可运行代码
import 'dart:async'; import 'package:audioplayers/audioplayers.dart'; import 'package:flutter/material.dart'; import 'package:flutter/cupertino.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: HomeScreen(), ); } } class HomeScreen extends StatefulWidget { const HomeScreen({Key? key}) : super(key: key); @override _HomeScreenState createState() => _HomeScreenState(); } class _HomeScreenState extends State<HomeScreen> { AudioPlayer audioPlayer = AudioPlayer(); Duration duration = Duration(); Duration position = Duration(); bool playing = false; Timer? textAnimationTimer; // 自定义轮播文本列表,可按需新增修改 final List<String> quoteList = [ 'Television contracts the imagination and radio expands it.', 'Radio is the theater of the mind.', 'Listening to radio is like having a friend in the room.', 'Radio connects people across boundaries and generations.' ]; int currentTextIndex = 0; double opacity = 1.0; @override void initState() { super.initState(); startTextAnimation(); } startTextAnimation() { // 每4秒触发一次切换:2秒停留 + 2秒淡出 textAnimationTimer = Timer.periodic(const Duration(seconds: 4), (timer) { // 第一步:当前文本淡出 setState(() { opacity = 0.0; }); // 等待2秒淡出完成后切换文本再淡入 Future.delayed(const Duration(seconds: 2), () { if(mounted) { setState(() { currentTextIndex = (currentTextIndex + 1) % quoteList.length; opacity = 1.0; }); } }); }); } @override void dispose() { audioPlayer.dispose(); textAnimationTimer?.cancel(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: const Color(0xff252525), appBar: AppBar( backgroundColor: const Color(0xffffcb05), title: Image.asset( 'assets/logoradio.png', fit: BoxFit.contain, height: 40, width: 40, ), actions: [IconButton(icon: const Icon(Icons.search), onPressed: () {})], ), drawer: Drawer( elevation: 10.0, child: ListView( children: [ UserAccountsDrawerHeader( accountName: const Text('sundar'), accountEmail: const Text('sundar@gmail.com'), currentAccountPicture: CircleAvatar( backgroundColor: Colors.red, child: const Text('xyz'), ), otherAccountsPictures: [ CircleAvatar( backgroundColor: Colors.red, child: const Text('ABC'), ) ], ), const ListTile( title: Text('HOME'), leading: Icon(Icons.mail), ), const Divider( height: 0.5, color: Colors.red, ), const ListTile( title: Text('PODCAST'), leading: Icon(Icons.mail), ), const Divider( height: 0.5, color: Colors.red, ), const ListTile( title: Text('ABOUT'), leading: Icon(Icons.mail), ), const Divider( height: 0.5, color: Colors.red, ), const ListTile( title: Text('CONTACT'), leading: Icon(Icons.people), ) ], ), ), body: SafeArea( child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ // 单个AnimatedOpacity组件实现多文本轮播 AnimatedOpacity( opacity: opacity, duration: const Duration(seconds: 2), child: Text( quoteList[currentTextIndex], textAlign: TextAlign.center, style: const TextStyle( color: Colors.red, fontSize: 30, ), ), ), const SizedBox(height: 80,), InkWell( onTap: () { getAudio(); }, child: Icon( playing == false ? Icons.play_circle_outline : Icons.pause_circle_outline, size: 50, color: Colors.red, ), ), ], ), ))); } Widget slider() { return Slider.adaptive( min: 0.0, value: position.inSeconds.toDouble(), max: duration.inSeconds.toDouble(), onChanged: (double value) { setState(() { audioPlayer.seek(Duration(seconds: value.toInt())); }); }); } void getAudio() async { var url = "https://live.radio5ive.com/proxy/radio5ivetamil/stream"; if (playing) { var res = await audioPlayer.pause(); if (res == 1) { setState(() { playing = false; }); } } else { var res = await audioPlayer.play(url, isLocal: false); if (res == 1) { setState(() { playing = true; }); } } audioPlayer.onDurationChanged.listen((Duration dd) { setState(() { duration = dd; }); }); audioPlayer.onAudioPositionChanged.listen((Duration dd) { setState(() { position = dd; }); }); } }
内容的提问来源于stack exchange,提问作者sundar
相关产品推荐
相关产品推荐

