import 'package:flutter/material.dart'; import 'package:plan/page/plan/detail/viewmodel/plan_detail_store.dart'; import 'package:provider/provider.dart'; import 'package:remixicon/remixicon.dart'; ///模块标题 class SuggestedTitle extends StatelessWidget { const SuggestedTitle({super.key}); @override Widget build(BuildContext context) { var list = context.select>( (store) => store.planDetail.suggestionsList, ); if (list.isEmpty) { return const SliverToBoxAdapter( child: SizedBox(), ); } return SliverToBoxAdapter( child: TweenAnimationBuilder( tween: Tween(begin: 0, end: 1), // 从透明到完全显示 duration: const Duration(milliseconds: 300), builder: (context, value, child) { return Opacity( opacity: value, child: child, ); }, child: Container( margin: const EdgeInsets.only(top: 20, bottom: 5), child: Opacity( opacity: 0.6, child: Row( spacing: 20, mainAxisAlignment: MainAxisAlignment.center, children: [ Container( width: 15, height: 1, color: Theme.of(context).colorScheme.surfaceContainerHigh, ), Text( "额外建议", style: Theme.of(context).textTheme.titleSmall, ), Container( width: 15, height: 1, color: Theme.of(context).colorScheme.surfaceContainerHigh, ), ], ), ), ), ), ); } } ///额外建议列表 class SuggestedList extends StatefulWidget { const SuggestedList({super.key}); @override State createState() => _SuggestedListState(); } class _SuggestedListState extends State { final GlobalKey _listKey = GlobalKey(); List _suggestionsList = []; @override void initState() { super.initState(); _initListen(); } void _initListen() { final store = context.read(); //先初始化,只在详情时才会有意义 _suggestionsList = store.planDetail.suggestionsList; store.addListener(() { final newList = store.planDetail.suggestionsList; // 找出新增的 item if (newList.length > _suggestionsList.length) { final addedItems = newList.sublist(_suggestionsList.length); for (var item in addedItems) { final index = _suggestionsList.length; _suggestionsList.add(item); // 插入动画 _listKey.currentState?.insertItem( index, duration: Duration(milliseconds: 300), ); } } else { setState(() { _suggestionsList = store.planDetail.suggestionsList; }); } }); } @override Widget build(BuildContext context) { return SliverAnimatedList( key: _listKey, initialItemCount: _suggestionsList.length, itemBuilder: (_, index, animation) { final curvedAnimation = CurvedAnimation( parent: animation, curve: Curves.easeInOut, ); return SuggestedItem( title: _suggestionsList[index], curvedAnimation: curvedAnimation, ); }, ); } } ///建议item class SuggestedItem extends StatelessWidget { final String title; final CurvedAnimation curvedAnimation; const SuggestedItem({ super.key, required this.title, required this.curvedAnimation, }); @override Widget build(BuildContext context) { return FadeTransition( opacity: curvedAnimation, child: SizeTransition( sizeFactor: curvedAnimation, axis: Axis.vertical, child: Padding( padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), child: Row( crossAxisAlignment: CrossAxisAlignment.start, spacing: 10, children: [ Transform.translate( offset: const Offset(0, 5), child: Icon( RemixIcons.lightbulb_flash_fill, color: Color(0xfff2a529), size: 18, ), ), Expanded( child: Opacity( opacity: 0.5, child: Text( title, style: Theme.of(context).textTheme.bodyMedium, ), ), ), ], ), ), ), ); } }