Showing
14 changed files
with
154 additions
and
93 deletions
| 1 | import 'package:flutter/material.dart'; | 1 | import 'package:flutter/material.dart'; |
| 2 | +import 'package:one_poem/poem/poem_router.dart'; | ||
| 2 | import 'package:one_poem/routers/fluro_navigator.dart'; | 3 | import 'package:one_poem/routers/fluro_navigator.dart'; |
| 3 | import 'package:one_poem/setting/setting_router.dart'; | 4 | import 'package:one_poem/setting/setting_router.dart'; |
| 4 | import 'package:one_poem/tiktok/style/style.dart'; | 5 | import 'package:one_poem/tiktok/style/style.dart'; |
| ... | @@ -186,6 +187,12 @@ class _AccountPageState extends State<AccountPage> { | ... | @@ -186,6 +187,12 @@ class _AccountPageState extends State<AccountPage> { |
| 186 | child: Stack( | 187 | child: Stack( |
| 187 | alignment: Alignment.topCenter, | 188 | alignment: Alignment.topCenter, |
| 188 | children: <Widget>[ | 189 | children: <Widget>[ |
| 190 | + Container( | ||
| 191 | + margin: const EdgeInsets.only(top: 500), | ||
| 192 | + height: double.infinity, | ||
| 193 | + width: double.infinity, | ||
| 194 | + color: ColorPlate.white, | ||
| 195 | + ), | ||
| 189 | body, | 196 | body, |
| 190 | Container( | 197 | Container( |
| 191 | alignment: Alignment.centerRight, | 198 | alignment: Alignment.centerRight, |
| ... | @@ -335,21 +342,14 @@ class _UserVideoTable extends StatelessWidget { | ... | @@ -335,21 +342,14 @@ class _UserVideoTable extends StatelessWidget { |
| 335 | ), | 342 | ), |
| 336 | ), | 343 | ), |
| 337 | Row( | 344 | Row( |
| 338 | - children: const <Widget>[ | 345 | + children: const [ |
| 339 | - _SmallVideo(), | ||
| 340 | - _SmallVideo(), | ||
| 341 | - _SmallVideo(), | ||
| 342 | - ], | ||
| 343 | - ), | ||
| 344 | - Row( | ||
| 345 | - children: const <Widget>[ | ||
| 346 | _SmallVideo(), | 346 | _SmallVideo(), |
| 347 | _SmallVideo(), | 347 | _SmallVideo(), |
| 348 | _SmallVideo(), | 348 | _SmallVideo(), |
| 349 | ], | 349 | ], |
| 350 | ), | 350 | ), |
| 351 | Row( | 351 | Row( |
| 352 | - children: const <Widget>[ | 352 | + children: const [ |
| 353 | _SmallVideo(), | 353 | _SmallVideo(), |
| 354 | _SmallVideo(), | 354 | _SmallVideo(), |
| 355 | _SmallVideo(), | 355 | _SmallVideo(), |
| ... | @@ -368,6 +368,13 @@ class _SmallVideo extends StatelessWidget { | ... | @@ -368,6 +368,13 @@ class _SmallVideo extends StatelessWidget { |
| 368 | @override | 368 | @override |
| 369 | Widget build(BuildContext context) { | 369 | Widget build(BuildContext context) { |
| 370 | return Expanded( | 370 | return Expanded( |
| 371 | + child: Tapped( | ||
| 372 | + onTap: (){ | ||
| 373 | + NavigatorUtils.push( | ||
| 374 | + context, | ||
| 375 | + '${PoemRouter.poemDetailPage}?id=100', | ||
| 376 | + ); | ||
| 377 | + }, | ||
| 371 | child: AspectRatio( | 378 | child: AspectRatio( |
| 372 | aspectRatio: 3.px / 4.0, | 379 | aspectRatio: 3.px / 4.0, |
| 373 | child: Container( | 380 | child: Container( |
| ... | @@ -388,6 +395,7 @@ class _SmallVideo extends StatelessWidget { | ... | @@ -388,6 +395,7 @@ class _SmallVideo extends StatelessWidget { |
| 388 | ), | 395 | ), |
| 389 | ), | 396 | ), |
| 390 | ), | 397 | ), |
| 398 | + ), | ||
| 391 | ); | 399 | ); |
| 392 | } | 400 | } |
| 393 | } | 401 | } | ... | ... |
| 1 | import 'package:flutter/material.dart'; | 1 | import 'package:flutter/material.dart'; |
| 2 | import 'package:one_poem/category/provider/categories_page_provider.dart'; | 2 | import 'package:one_poem/category/provider/categories_page_provider.dart'; |
| 3 | -import 'package:one_poem/util/theme_utils.dart'; | ||
| 4 | import 'package:one_poem/widgets/my_app_bar.dart'; | 3 | import 'package:one_poem/widgets/my_app_bar.dart'; |
| 5 | import 'package:provider/provider.dart'; | 4 | import 'package:provider/provider.dart'; |
| 6 | 5 | ||
| ... | @@ -13,11 +12,7 @@ class CategoriesPage extends StatefulWidget { | ... | @@ -13,11 +12,7 @@ class CategoriesPage extends StatefulWidget { |
| 13 | _CategoriesPageState createState() => _CategoriesPageState(); | 12 | _CategoriesPageState createState() => _CategoriesPageState(); |
| 14 | } | 13 | } |
| 15 | 14 | ||
| 16 | -class _CategoriesPageState extends State<CategoriesPage> | 15 | +class _CategoriesPageState extends State<CategoriesPage>{ |
| 17 | - with SingleTickerProviderStateMixin, AutomaticKeepAliveClientMixin { | ||
| 18 | - TabController? _tabController; | ||
| 19 | - final PageController _pageController = PageController(); | ||
| 20 | - | ||
| 21 | final GlobalKey _bodyKey = GlobalKey(); | 16 | final GlobalKey _bodyKey = GlobalKey(); |
| 22 | 17 | ||
| 23 | CategoriesPageProvider provider = CategoriesPageProvider(); | 18 | CategoriesPageProvider provider = CategoriesPageProvider(); |
| ... | @@ -25,19 +20,15 @@ class _CategoriesPageState extends State<CategoriesPage> | ... | @@ -25,19 +20,15 @@ class _CategoriesPageState extends State<CategoriesPage> |
| 25 | @override | 20 | @override |
| 26 | void initState() { | 21 | void initState() { |
| 27 | super.initState(); | 22 | super.initState(); |
| 28 | - _tabController = TabController(vsync: this, length: 3); | ||
| 29 | } | 23 | } |
| 30 | 24 | ||
| 31 | @override | 25 | @override |
| 32 | void dispose() { | 26 | void dispose() { |
| 33 | - _tabController?.dispose(); | ||
| 34 | super.dispose(); | 27 | super.dispose(); |
| 35 | } | 28 | } |
| 36 | 29 | ||
| 37 | @override | 30 | @override |
| 38 | Widget build(BuildContext context) { | 31 | Widget build(BuildContext context) { |
| 39 | - super.build(context); | ||
| 40 | - final Color? _iconColor = ThemeUtils.getIconColor(context); | ||
| 41 | return ChangeNotifierProvider<CategoriesPageProvider>( | 32 | return ChangeNotifierProvider<CategoriesPageProvider>( |
| 42 | create: (_) => provider, | 33 | create: (_) => provider, |
| 43 | child: Scaffold( | 34 | child: Scaffold( |
| ... | @@ -63,27 +54,13 @@ class _CategoriesPageState extends State<CategoriesPage> | ... | @@ -63,27 +54,13 @@ class _CategoriesPageState extends State<CategoriesPage> |
| 63 | body: Column( | 54 | body: Column( |
| 64 | key: _bodyKey, | 55 | key: _bodyKey, |
| 65 | crossAxisAlignment: CrossAxisAlignment.start, | 56 | crossAxisAlignment: CrossAxisAlignment.start, |
| 66 | - children: <Widget>[ | 57 | + children: const <Widget>[ |
| 67 | Expanded( | 58 | Expanded( |
| 68 | - child: PageView.builder( | 59 | + child: CategoryListPage(index: 1), |
| 69 | - key: const Key('pageView'), | ||
| 70 | - itemCount: 3, | ||
| 71 | - onPageChanged: _onPageChange, | ||
| 72 | - controller: _pageController, | ||
| 73 | - itemBuilder: (_, int index) => | ||
| 74 | - CategoryListPage(index: index)), | ||
| 75 | ) | 60 | ) |
| 76 | ], | 61 | ], |
| 77 | ), | 62 | ), |
| 78 | ), | 63 | ), |
| 79 | ); | 64 | ); |
| 80 | } | 65 | } |
| 81 | - | ||
| 82 | - void _onPageChange(int index) { | ||
| 83 | - _tabController?.animateTo(index); | ||
| 84 | - provider.setIndex(index); | ||
| 85 | - } | ||
| 86 | - | ||
| 87 | - @override | ||
| 88 | - bool get wantKeepAlive => true; | ||
| 89 | } | 66 | } | ... | ... |
| ... | @@ -8,11 +8,7 @@ import 'package:one_poem/widgets/state_layout.dart'; | ... | @@ -8,11 +8,7 @@ import 'package:one_poem/widgets/state_layout.dart'; |
| 8 | import 'package:provider/provider.dart'; | 8 | import 'package:provider/provider.dart'; |
| 9 | 9 | ||
| 10 | class CategoryListPage extends StatefulWidget { | 10 | class CategoryListPage extends StatefulWidget { |
| 11 | - | 11 | + const CategoryListPage({Key? key, required this.index}) : super(key: key); |
| 12 | - const CategoryListPage({ | ||
| 13 | - Key? key, | ||
| 14 | - required this.index | ||
| 15 | - }): super(key: key); | ||
| 16 | 12 | ||
| 17 | final int index; | 13 | final int index; |
| 18 | 14 | ||
| ... | @@ -20,34 +16,20 @@ class CategoryListPage extends StatefulWidget { | ... | @@ -20,34 +16,20 @@ class CategoryListPage extends StatefulWidget { |
| 20 | _CategoryListPageState createState() => _CategoryListPageState(); | 16 | _CategoryListPageState createState() => _CategoryListPageState(); |
| 21 | } | 17 | } |
| 22 | 18 | ||
| 23 | -class _CategoryListPageState extends State<CategoryListPage> with AutomaticKeepAliveClientMixin<CategoryListPage>, SingleTickerProviderStateMixin { | 19 | +class _CategoryListPageState extends State<CategoryListPage> { |
| 24 | - | ||
| 25 | final int _selectIndex = -1; | 20 | final int _selectIndex = -1; |
| 26 | - late Animation<double> _animation; | ||
| 27 | - late AnimationController _controller; | ||
| 28 | List<CategoryItemEntity> _list = []; | 21 | List<CategoryItemEntity> _list = []; |
| 29 | - AnimationStatus _animationStatus = AnimationStatus.dismissed; | ||
| 30 | 22 | ||
| 31 | @override | 23 | @override |
| 32 | void initState() { | 24 | void initState() { |
| 33 | super.initState(); | 25 | super.initState(); |
| 34 | - // 初始化动画控制 | ||
| 35 | - _controller = AnimationController(duration: const Duration(milliseconds: 450), vsync: this); | ||
| 36 | - // 动画曲线 | ||
| 37 | - final _curvedAnimation = CurvedAnimation(parent: _controller, curve: Curves.easeOutSine); | ||
| 38 | - _animation = Tween(begin: 0.0, end: 1.1).animate(_curvedAnimation) ..addStatusListener((status) { | ||
| 39 | - _animationStatus = status; | ||
| 40 | - }); | ||
| 41 | - | ||
| 42 | //Item数量 | 26 | //Item数量 |
| 43 | _maxPage = widget.index == 0 ? 1 : (widget.index == 1 ? 2 : 3); | 27 | _maxPage = widget.index == 0 ? 1 : (widget.index == 1 ? 2 : 3); |
| 44 | - | ||
| 45 | _onRefresh(); | 28 | _onRefresh(); |
| 46 | } | 29 | } |
| 47 | 30 | ||
| 48 | @override | 31 | @override |
| 49 | void dispose() { | 32 | void dispose() { |
| 50 | - _controller.dispose(); | ||
| 51 | super.dispose(); | 33 | super.dispose(); |
| 52 | } | 34 | } |
| 53 | 35 | ||
| ... | @@ -67,8 +49,11 @@ class _CategoryListPageState extends State<CategoryListPage> with AutomaticKeepA | ... | @@ -67,8 +49,11 @@ class _CategoryListPageState extends State<CategoryListPage> with AutomaticKeepA |
| 67 | await Future.delayed(const Duration(seconds: 2), () { | 49 | await Future.delayed(const Duration(seconds: 2), () { |
| 68 | setState(() { | 50 | setState(() { |
| 69 | _page = 1; | 51 | _page = 1; |
| 70 | - _list = List.generate(widget.index == 0 ? 3 : 10, (i) => | 52 | + _list = List.generate( |
| 71 | - CategoryItemEntity(icon: _imgList[i % 6], title: '八月十五中秋月饼礼盒', type: i % 3)); | 53 | + widget.index == 0 ? 3 : 10, |
| 54 | + (i) => CategoryItemEntity( | ||
| 55 | + icon: _imgList[i % 6], title: '八月十五中秋月饼礼盒', type: i % 3), | ||
| 56 | + ); | ||
| 72 | }); | 57 | }); |
| 73 | _setGoodsCount(_list.length); | 58 | _setGoodsCount(_list.length); |
| 74 | }); | 59 | }); |
| ... | @@ -77,16 +62,20 @@ class _CategoryListPageState extends State<CategoryListPage> with AutomaticKeepA | ... | @@ -77,16 +62,20 @@ class _CategoryListPageState extends State<CategoryListPage> with AutomaticKeepA |
| 77 | Future _loadMore() async { | 62 | Future _loadMore() async { |
| 78 | await Future.delayed(const Duration(seconds: 2), () { | 63 | await Future.delayed(const Duration(seconds: 2), () { |
| 79 | setState(() { | 64 | setState(() { |
| 80 | - _list.addAll(List.generate(10, (i) => | 65 | + _list.addAll( |
| 81 | - CategoryItemEntity(icon: _imgList[i % 6], title: '八月十五中秋月饼礼盒', type: i % 3))); | 66 | + List.generate( |
| 82 | - _page ++; | 67 | + 10, |
| 68 | + (i) => CategoryItemEntity( | ||
| 69 | + icon: _imgList[i % 6], title: '八月十五中秋月饼礼盒', type: i % 3), | ||
| 70 | + ), | ||
| 71 | + ); | ||
| 72 | + _page++; | ||
| 83 | }); | 73 | }); |
| 84 | _setGoodsCount(_list.length); | 74 | _setGoodsCount(_list.length); |
| 85 | }); | 75 | }); |
| 86 | } | 76 | } |
| 87 | 77 | ||
| 88 | void _setGoodsCount(int count) { | 78 | void _setGoodsCount(int count) { |
| 89 | -// Provider.of<GoodsPageProvider>(context, listen: false).setGoodsCount(count); | ||
| 90 | /// 与上方等价,provider 4.1.0添加的拓展方法 | 79 | /// 与上方等价,provider 4.1.0添加的拓展方法 |
| 91 | context.read<CategoriesPageProvider>().setGoodsCount(count); | 80 | context.read<CategoriesPageProvider>().setGoodsCount(count); |
| 92 | } | 81 | } |
| ... | @@ -97,7 +86,6 @@ class _CategoryListPageState extends State<CategoryListPage> with AutomaticKeepA | ... | @@ -97,7 +86,6 @@ class _CategoryListPageState extends State<CategoryListPage> with AutomaticKeepA |
| 97 | 86 | ||
| 98 | @override | 87 | @override |
| 99 | Widget build(BuildContext context) { | 88 | Widget build(BuildContext context) { |
| 100 | - super.build(context); | ||
| 101 | return DeerListView( | 89 | return DeerListView( |
| 102 | itemCount: _list.length, | 90 | itemCount: _list.length, |
| 103 | stateType: _stateType, | 91 | stateType: _stateType, |
| ... | @@ -110,10 +98,6 @@ class _CategoryListPageState extends State<CategoryListPage> with AutomaticKeepA | ... | @@ -110,10 +98,6 @@ class _CategoryListPageState extends State<CategoryListPage> with AutomaticKeepA |
| 110 | selectIndex: _selectIndex, | 98 | selectIndex: _selectIndex, |
| 111 | item: _list[index], | 99 | item: _list[index], |
| 112 | ); | 100 | ); |
| 101 | + }); | ||
| 113 | } | 102 | } |
| 114 | - ); | ||
| 115 | - } | ||
| 116 | - | ||
| 117 | - @override | ||
| 118 | - bool get wantKeepAlive => true; | ||
| 119 | } | 103 | } | ... | ... |
| ... | @@ -12,7 +12,7 @@ FriendEntity $FriendEntityFromJson(Map<String, dynamic> json) { | ... | @@ -12,7 +12,7 @@ FriendEntity $FriendEntityFromJson(Map<String, dynamic> json) { |
| 12 | 12 | ||
| 13 | Map<String, dynamic> $FriendEntityToJson(FriendEntity entity) { | 13 | Map<String, dynamic> $FriendEntityToJson(FriendEntity entity) { |
| 14 | final Map<String, dynamic> data = <String, dynamic>{}; | 14 | final Map<String, dynamic> data = <String, dynamic>{}; |
| 15 | - data['data'] = entity.data.map((v) => v.toJson()).toList(); | 15 | + data['data'] = entity.data!.map((v) => v.toJson()).toList(); |
| 16 | return data; | 16 | return data; |
| 17 | } | 17 | } |
| 18 | 18 | ... | ... |
| ... | @@ -29,6 +29,14 @@ import 'util/theme_utils.dart'; | ... | @@ -29,6 +29,14 @@ import 'util/theme_utils.dart'; |
| 29 | /// 3. 創建i18n文件 | 29 | /// 3. 創建i18n文件 |
| 30 | /// 4. 执行:flutter gen-l10n --template-arb-file intl_en.arb --output-class OnePoemLocalizations letLocalizations --output-localization-file one_poem_localizations.dart | 30 | /// 4. 执行:flutter gen-l10n --template-arb-file intl_en.arb --output-class OnePoemLocalizations letLocalizations --output-localization-file one_poem_localizations.dart |
| 31 | /// | 31 | /// |
| 32 | +/// json to model | ||
| 33 | +/// 安装 | ||
| 34 | +/// dependencies: | ||
| 35 | +/// json_annotation: ^4.4.0 | ||
| 36 | +/// dev_dependencies: | ||
| 37 | +/// json_serializable: ^6.1.3 | ||
| 38 | +/// build_runner: ^2.1.7 | ||
| 39 | +/// 执行:flutter packages pub run build_runner build --delete-conflicting-outputs | ||
| 32 | 40 | ||
| 33 | Future<void> main() async { | 41 | Future<void> main() async { |
| 34 | // debugProfileBuildsEnabled = true; | 42 | // debugProfileBuildsEnabled = true; | ... | ... |
| ... | @@ -56,7 +56,9 @@ class _PoemDetailPageState extends State<PoemDetailPage> { | ... | @@ -56,7 +56,9 @@ class _PoemDetailPageState extends State<PoemDetailPage> { |
| 56 | }, | 56 | }, |
| 57 | funcRight: () { | 57 | funcRight: () { |
| 58 | NavigatorUtils.push( | 58 | NavigatorUtils.push( |
| 59 | - context, '${PoemRouter.poemRecordAudioPage}?id=100'); | 59 | + context, |
| 60 | + '${PoemRouter.poemRecordAudioPage}?id=100', | ||
| 61 | + ); | ||
| 60 | }, | 62 | }, |
| 61 | ), | 63 | ), |
| 62 | homeActionWidgets: HomeActionWidgets( | 64 | homeActionWidgets: HomeActionWidgets( |
| ... | @@ -133,7 +135,12 @@ class _PoemDetailPageState extends State<PoemDetailPage> { | ... | @@ -133,7 +135,12 @@ class _PoemDetailPageState extends State<PoemDetailPage> { |
| 133 | Icons.mic_none, | 135 | Icons.mic_none, |
| 134 | size: 36.px, | 136 | size: 36.px, |
| 135 | ), | 137 | ), |
| 136 | - onPressed: () {}, | 138 | + onPressed: () { |
| 139 | + NavigatorUtils.push( | ||
| 140 | + context, | ||
| 141 | + '${PoemRouter.poemRecordAudioPage}?id=100', | ||
| 142 | + ); | ||
| 143 | + }, | ||
| 137 | ), | 144 | ), |
| 138 | Gaps.hGap16, | 145 | Gaps.hGap16, |
| 139 | IconButton( | 146 | IconButton( | ... | ... |
| ... | @@ -89,6 +89,13 @@ class _PoemPageState extends State<PoemPage> with WidgetsBindingObserver { | ... | @@ -89,6 +89,13 @@ class _PoemPageState extends State<PoemPage> with WidgetsBindingObserver { |
| 89 | } | 89 | } |
| 90 | 90 | ||
| 91 | @override | 91 | @override |
| 92 | + void setState(fn) { | ||
| 93 | + if (mounted) { | ||
| 94 | + super.setState(fn); | ||
| 95 | + } | ||
| 96 | + } | ||
| 97 | + | ||
| 98 | + @override | ||
| 92 | Widget build(BuildContext context) { | 99 | Widget build(BuildContext context) { |
| 93 | Widget? currentPage; | 100 | Widget? currentPage; |
| 94 | double a = MediaQuery.of(context).size.aspectRatio; | 101 | double a = MediaQuery.of(context).size.aspectRatio; | ... | ... |
lib/poem/page/poem_video_player.dart
0 → 100644
| 1 | +import 'package:fijkplayer/fijkplayer.dart'; | ||
| 2 | +import 'package:flutter/material.dart'; | ||
| 3 | + | ||
| 4 | +class PoemVideoPlayer extends StatefulWidget { | ||
| 5 | + final String url; | ||
| 6 | + | ||
| 7 | + const PoemVideoPlayer({ | ||
| 8 | + Key? key, | ||
| 9 | + required this.url, | ||
| 10 | + }) : super(key: key); | ||
| 11 | + | ||
| 12 | + @override | ||
| 13 | + _PoemVideoPlayerState createState() => _PoemVideoPlayerState(); | ||
| 14 | +} | ||
| 15 | + | ||
| 16 | +class _PoemVideoPlayerState extends State<PoemVideoPlayer> { | ||
| 17 | + final FijkPlayer player = FijkPlayer(); | ||
| 18 | + | ||
| 19 | + _PoemVideoPlayerState(); | ||
| 20 | + | ||
| 21 | + @override | ||
| 22 | + void initState() { | ||
| 23 | + super.initState(); | ||
| 24 | + player.setDataSource(widget.url, autoPlay: true); | ||
| 25 | + } | ||
| 26 | + | ||
| 27 | + @override | ||
| 28 | + Widget build(BuildContext context) { | ||
| 29 | + return Scaffold( | ||
| 30 | + appBar: AppBar(title: const Text("Fijkplayer Example")), | ||
| 31 | + body: Container( | ||
| 32 | + alignment: Alignment.center, | ||
| 33 | + child: FijkView( | ||
| 34 | + player: player, | ||
| 35 | + ), | ||
| 36 | + )); | ||
| 37 | + } | ||
| 38 | + | ||
| 39 | + @override | ||
| 40 | + void dispose() { | ||
| 41 | + super.dispose(); | ||
| 42 | + player.release(); | ||
| 43 | + } | ||
| 44 | +} |
| ... | @@ -3,11 +3,13 @@ import 'package:one_poem/poem/page/poem_record_audio.dart'; | ... | @@ -3,11 +3,13 @@ import 'package:one_poem/poem/page/poem_record_audio.dart'; |
| 3 | import 'package:one_poem/routers/i_router.dart'; | 3 | import 'package:one_poem/routers/i_router.dart'; |
| 4 | import 'page/poem_detail.dart'; | 4 | import 'page/poem_detail.dart'; |
| 5 | import 'page/poem_page.dart'; | 5 | import 'page/poem_page.dart'; |
| 6 | +import 'page/poem_video_player.dart'; | ||
| 6 | 7 | ||
| 7 | class PoemRouter implements IRouterProvider { | 8 | class PoemRouter implements IRouterProvider { |
| 8 | static String poemPage = '/poem'; | 9 | static String poemPage = '/poem'; |
| 9 | static String poemDetailPage = '/detail'; | 10 | static String poemDetailPage = '/detail'; |
| 10 | - static String poemRecordAudioPage = '/poem_record_audio'; | 11 | + static String poemRecordAudioPage = '/poem/record/audio'; |
| 12 | + static String poemVidePlayer = '/poem/video/player'; | ||
| 11 | 13 | ||
| 12 | @override | 14 | @override |
| 13 | void initRouter(FluroRouter router) { | 15 | void initRouter(FluroRouter router) { |
| ... | @@ -27,5 +29,12 @@ class PoemRouter implements IRouterProvider { | ... | @@ -27,5 +29,12 @@ class PoemRouter implements IRouterProvider { |
| 27 | poemId: int.parse(id!), | 29 | poemId: int.parse(id!), |
| 28 | ); | 30 | ); |
| 29 | })); | 31 | })); |
| 32 | + router.define(poemVidePlayer, | ||
| 33 | + handler: Handler(handlerFunc: (_, Map<String, List<String>> params) { | ||
| 34 | + String? url = params['url']?.first; | ||
| 35 | + return PoemVideoPlayer( | ||
| 36 | + url: url!, | ||
| 37 | + ); | ||
| 38 | + })); | ||
| 30 | } | 39 | } |
| 31 | } | 40 | } | ... | ... |
| ... | @@ -5,7 +5,7 @@ import 'package:one_poem/generated/json/friend_entity.g.dart'; | ... | @@ -5,7 +5,7 @@ import 'package:one_poem/generated/json/friend_entity.g.dart'; |
| 5 | @JsonSerializable() | 5 | @JsonSerializable() |
| 6 | class FriendEntity { | 6 | class FriendEntity { |
| 7 | 7 | ||
| 8 | - late List<FriendData> data; | 8 | + List<FriendData>? data; |
| 9 | 9 | ||
| 10 | FriendEntity(); | 10 | FriendEntity(); |
| 11 | 11 | ... | ... |
| ... | @@ -17,8 +17,6 @@ class TimelinesPage extends StatefulWidget { | ... | @@ -17,8 +17,6 @@ class TimelinesPage extends StatefulWidget { |
| 17 | 17 | ||
| 18 | class _TimelinesPageState extends State<TimelinesPage> { | 18 | class _TimelinesPageState extends State<TimelinesPage> { |
| 19 | final ScrollController _scrollController = ScrollController(); | 19 | final ScrollController _scrollController = ScrollController(); |
| 20 | - double _opacity = 0; | ||
| 21 | - | ||
| 22 | FriendEntity _friendModelEntity = FriendEntity(); | 20 | FriendEntity _friendModelEntity = FriendEntity(); |
| 23 | 21 | ||
| 24 | Future<String> loadAsset() async { | 22 | Future<String> loadAsset() async { |
| ... | @@ -43,14 +41,13 @@ class _TimelinesPageState extends State<TimelinesPage> { | ... | @@ -43,14 +41,13 @@ class _TimelinesPageState extends State<TimelinesPage> { |
| 43 | alpha = 1; | 41 | alpha = 1; |
| 44 | } | 42 | } |
| 45 | setState(() { | 43 | setState(() { |
| 46 | - _opacity = alpha; | ||
| 47 | }); | 44 | }); |
| 48 | }); | 45 | }); |
| 49 | } | 46 | } |
| 50 | 47 | ||
| 51 | Widget _mainListViewBuilder(BuildContext context, int index) { | 48 | Widget _mainListViewBuilder(BuildContext context, int index) { |
| 52 | return FriendCell( | 49 | return FriendCell( |
| 53 | - model: _friendModelEntity.data[index], | 50 | + model: _friendModelEntity.data![index], |
| 54 | ); | 51 | ); |
| 55 | } | 52 | } |
| 56 | 53 | ||
| ... | @@ -62,19 +59,21 @@ class _TimelinesPageState extends State<TimelinesPage> { | ... | @@ -62,19 +59,21 @@ class _TimelinesPageState extends State<TimelinesPage> { |
| 62 | isTransparent: true, | 59 | isTransparent: true, |
| 63 | homeMenuHeader: TimelineMenuHeader(), | 60 | homeMenuHeader: TimelineMenuHeader(), |
| 64 | ), | 61 | ), |
| 65 | - body: ListView( | 62 | + body: _friendModelEntity.data != null |
| 63 | + ? ListView( | ||
| 66 | padding: const EdgeInsets.only(top: 0), | 64 | padding: const EdgeInsets.only(top: 0), |
| 67 | controller: _scrollController, | 65 | controller: _scrollController, |
| 68 | children: <Widget>[ | 66 | children: <Widget>[ |
| 69 | ListView.builder( | 67 | ListView.builder( |
| 70 | padding: const EdgeInsets.only(top: 0), | 68 | padding: const EdgeInsets.only(top: 0), |
| 71 | itemBuilder: _mainListViewBuilder, | 69 | itemBuilder: _mainListViewBuilder, |
| 72 | - itemCount: _friendModelEntity.data.length, | 70 | + itemCount: _friendModelEntity.data!.length, |
| 73 | shrinkWrap: true, | 71 | shrinkWrap: true, |
| 74 | physics: const NeverScrollableScrollPhysics(), | 72 | physics: const NeverScrollableScrollPhysics(), |
| 75 | ) | 73 | ) |
| 76 | ], | 74 | ], |
| 77 | - ), | 75 | + ) |
| 76 | + : const Center(child: CupertinoActivityIndicator(radius: 16.0)), | ||
| 78 | ); | 77 | ); |
| 79 | } | 78 | } |
| 80 | } | 79 | } | ... | ... |
| ... | @@ -6,7 +6,6 @@ import 'package:one_poem/widgets/state_layout.dart'; | ... | @@ -6,7 +6,6 @@ import 'package:one_poem/widgets/state_layout.dart'; |
| 6 | 6 | ||
| 7 | /// 封装下拉刷新与加载更多 | 7 | /// 封装下拉刷新与加载更多 |
| 8 | class DeerListView extends StatefulWidget { | 8 | class DeerListView extends StatefulWidget { |
| 9 | - | ||
| 10 | const DeerListView({ | 9 | const DeerListView({ |
| 11 | Key? key, | 10 | Key? key, |
| 12 | required this.itemCount, | 11 | required this.itemCount, |
| ... | @@ -18,7 +17,7 @@ class DeerListView extends StatefulWidget { | ... | @@ -18,7 +17,7 @@ class DeerListView extends StatefulWidget { |
| 18 | this.pageSize = 10, | 17 | this.pageSize = 10, |
| 19 | this.padding, | 18 | this.padding, |
| 20 | this.itemExtent, | 19 | this.itemExtent, |
| 21 | - }): super(key: key); | 20 | + }) : super(key: key); |
| 22 | 21 | ||
| 23 | final RefreshCallback onRefresh; | 22 | final RefreshCallback onRefresh; |
| 24 | final LoadMoreCallback? loadMore; | 23 | final LoadMoreCallback? loadMore; |
| ... | @@ -26,8 +25,10 @@ class DeerListView extends StatefulWidget { | ... | @@ -26,8 +25,10 @@ class DeerListView extends StatefulWidget { |
| 26 | final bool hasMore; | 25 | final bool hasMore; |
| 27 | final IndexedWidgetBuilder itemBuilder; | 26 | final IndexedWidgetBuilder itemBuilder; |
| 28 | final StateType stateType; | 27 | final StateType stateType; |
| 28 | + | ||
| 29 | /// 一页的数量,默认为10 | 29 | /// 一页的数量,默认为10 |
| 30 | final int pageSize; | 30 | final int pageSize; |
| 31 | + | ||
| 31 | /// padding属性使用时注意会破坏原有的SafeArea,需要自行计算bottom大小 | 32 | /// padding属性使用时注意会破坏原有的SafeArea,需要自行计算bottom大小 |
| 32 | final EdgeInsetsGeometry? padding; | 33 | final EdgeInsetsGeometry? padding; |
| 33 | final double? itemExtent; | 34 | final double? itemExtent; |
| ... | @@ -40,7 +41,6 @@ typedef RefreshCallback = Future<void> Function(); | ... | @@ -40,7 +41,6 @@ typedef RefreshCallback = Future<void> Function(); |
| 40 | typedef LoadMoreCallback = Future<void> Function(); | 41 | typedef LoadMoreCallback = Future<void> Function(); |
| 41 | 42 | ||
| 42 | class _DeerListViewState extends State<DeerListView> { | 43 | class _DeerListViewState extends State<DeerListView> { |
| 43 | - | ||
| 44 | /// 是否正在加载数据 | 44 | /// 是否正在加载数据 |
| 45 | bool _isLoading = false; | 45 | bool _isLoading = false; |
| 46 | 46 | ||
| ... | @@ -48,10 +48,12 @@ class _DeerListViewState extends State<DeerListView> { | ... | @@ -48,10 +48,12 @@ class _DeerListViewState extends State<DeerListView> { |
| 48 | Widget build(BuildContext context) { | 48 | Widget build(BuildContext context) { |
| 49 | final Widget child = RefreshIndicator( | 49 | final Widget child = RefreshIndicator( |
| 50 | onRefresh: widget.onRefresh, | 50 | onRefresh: widget.onRefresh, |
| 51 | - child: widget.itemCount == 0 ? | 51 | + child: widget.itemCount == 0 |
| 52 | - StateLayout(type: widget.stateType) : | 52 | + ? StateLayout(type: widget.stateType) |
| 53 | - ListView.builder( | 53 | + : ListView.builder( |
| 54 | - itemCount: widget.loadMore == null ? widget.itemCount : widget.itemCount + 1, | 54 | + itemCount: widget.loadMore == null |
| 55 | + ? widget.itemCount | ||
| 56 | + : widget.itemCount + 1, | ||
| 55 | padding: widget.padding, | 57 | padding: widget.padding, |
| 56 | itemExtent: widget.itemExtent, | 58 | itemExtent: widget.itemExtent, |
| 57 | itemBuilder: (BuildContext context, int index) { | 59 | itemBuilder: (BuildContext context, int index) { |
| ... | @@ -59,7 +61,10 @@ class _DeerListViewState extends State<DeerListView> { | ... | @@ -59,7 +61,10 @@ class _DeerListViewState extends State<DeerListView> { |
| 59 | if (widget.loadMore == null) { | 61 | if (widget.loadMore == null) { |
| 60 | return widget.itemBuilder(context, index); | 62 | return widget.itemBuilder(context, index); |
| 61 | } else { | 63 | } else { |
| 62 | - return index < widget.itemCount ? widget.itemBuilder(context, index) : MoreWidget(widget.itemCount, widget.hasMore, widget.pageSize); | 64 | + return index < widget.itemCount |
| 65 | + ? widget.itemBuilder(context, index) | ||
| 66 | + : MoreWidget( | ||
| 67 | + widget.itemCount, widget.hasMore, widget.pageSize); | ||
| 63 | } | 68 | } |
| 64 | }, | 69 | }, |
| 65 | ), | 70 | ), |
| ... | @@ -68,7 +73,8 @@ class _DeerListViewState extends State<DeerListView> { | ... | @@ -68,7 +73,8 @@ class _DeerListViewState extends State<DeerListView> { |
| 68 | child: NotificationListener<ScrollNotification>( | 73 | child: NotificationListener<ScrollNotification>( |
| 69 | onNotification: (ScrollNotification note) { | 74 | onNotification: (ScrollNotification note) { |
| 70 | /// 确保是垂直方向滚动,且滑动至底部 | 75 | /// 确保是垂直方向滚动,且滑动至底部 |
| 71 | - if (note.metrics.pixels == note.metrics.maxScrollExtent && note.metrics.axis == Axis.vertical) { | 76 | + if (note.metrics.pixels == note.metrics.maxScrollExtent && |
| 77 | + note.metrics.axis == Axis.vertical) { | ||
| 72 | _loadMore(); | 78 | _loadMore(); |
| 73 | } | 79 | } |
| 74 | return true; | 80 | return true; |
| ... | @@ -92,12 +98,11 @@ class _DeerListViewState extends State<DeerListView> { | ... | @@ -92,12 +98,11 @@ class _DeerListViewState extends State<DeerListView> { |
| 92 | await widget.loadMore?.call(); | 98 | await widget.loadMore?.call(); |
| 93 | _isLoading = false; | 99 | _isLoading = false; |
| 94 | } | 100 | } |
| 95 | - | ||
| 96 | } | 101 | } |
| 97 | 102 | ||
| 98 | class MoreWidget extends StatelessWidget { | 103 | class MoreWidget extends StatelessWidget { |
| 99 | - | 104 | + const MoreWidget(this.itemCount, this.hasMore, this.pageSize, {Key? key}) |
| 100 | - const MoreWidget(this.itemCount, this.hasMore, this.pageSize, {Key? key}): super(key: key); | 105 | + : super(key: key); |
| 101 | 106 | ||
| 102 | final int itemCount; | 107 | final int itemCount; |
| 103 | final bool hasMore; | 108 | final bool hasMore; |
| ... | @@ -105,7 +110,9 @@ class MoreWidget extends StatelessWidget { | ... | @@ -105,7 +110,9 @@ class MoreWidget extends StatelessWidget { |
| 105 | 110 | ||
| 106 | @override | 111 | @override |
| 107 | Widget build(BuildContext context) { | 112 | Widget build(BuildContext context) { |
| 108 | - final TextStyle style = context.isDark ? TextStyles.textGray14 : const TextStyle(color: Color(0x8A000000)); | 113 | + final TextStyle style = context.isDark |
| 114 | + ? TextStyles.textGray14 | ||
| 115 | + : const TextStyle(color: Color(0x8A000000)); | ||
| 109 | return Padding( | 116 | return Padding( |
| 110 | padding: const EdgeInsets.symmetric(vertical: 10.0), | 117 | padding: const EdgeInsets.symmetric(vertical: 10.0), |
| 111 | child: Row( | 118 | child: Row( |
| ... | @@ -113,8 +120,10 @@ class MoreWidget extends StatelessWidget { | ... | @@ -113,8 +120,10 @@ class MoreWidget extends StatelessWidget { |
| 113 | children: <Widget>[ | 120 | children: <Widget>[ |
| 114 | if (hasMore) const CupertinoActivityIndicator(), | 121 | if (hasMore) const CupertinoActivityIndicator(), |
| 115 | if (hasMore) Gaps.hGap5, | 122 | if (hasMore) Gaps.hGap5, |
| 123 | + | ||
| 116 | /// 只有一页的时候,就不显示FooterView了 | 124 | /// 只有一页的时候,就不显示FooterView了 |
| 117 | - Text(hasMore ? '正在加载中...' : (itemCount < pageSize ? '' : '没有了呦~'), style: style), | 125 | + Text(hasMore ? '正在加载中...' : (itemCount < pageSize ? '' : '没有了呦~'), |
| 126 | + style: style), | ||
| 118 | ], | 127 | ], |
| 119 | ), | 128 | ), |
| 120 | ); | 129 | ); | ... | ... |
| ... | @@ -295,6 +295,13 @@ packages: | ... | @@ -295,6 +295,13 @@ packages: |
| 295 | url: "https://pub.dartlang.org" | 295 | url: "https://pub.dartlang.org" |
| 296 | source: hosted | 296 | source: hosted |
| 297 | version: "1.1.2" | 297 | version: "1.1.2" |
| 298 | + fijkplayer: | ||
| 299 | + dependency: "direct main" | ||
| 300 | + description: | ||
| 301 | + name: fijkplayer | ||
| 302 | + url: "https://pub.dartlang.org" | ||
| 303 | + source: hosted | ||
| 304 | + version: "0.10.1" | ||
| 298 | file: | 305 | file: |
| 299 | dependency: transitive | 306 | dependency: transitive |
| 300 | description: | 307 | description: | ... | ... |
| ... | @@ -89,6 +89,8 @@ dependencies: | ... | @@ -89,6 +89,8 @@ dependencies: |
| 89 | tapped: ^2.0.0-nullsafety.0 | 89 | tapped: ^2.0.0-nullsafety.0 |
| 90 | # 加载动画库 | 90 | # 加载动画库 |
| 91 | flutter_spinkit: ^5.0.0 | 91 | flutter_spinkit: ^5.0.0 |
| 92 | + # fijkplayer (Video player plugin for Flutter) Flutter 媒体播放器 | ||
| 93 | + fijkplayer: ^0.10.1 | ||
| 92 | 94 | ||
| 93 | json_annotation: ^4.4.0 | 95 | json_annotation: ^4.4.0 |
| 94 | flutter_plugin_record: ^1.0.1 | 96 | flutter_plugin_record: ^1.0.1 | ... | ... |
-
Please register or login to post a comment