Showing
14 changed files
with
202 additions
and
141 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,22 +368,30 @@ class _SmallVideo extends StatelessWidget { | ... | @@ -368,22 +368,30 @@ 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: AspectRatio( | 371 | + child: Tapped( |
372 | - aspectRatio: 3.px / 4.0, | 372 | + onTap: (){ |
373 | - child: Container( | 373 | + NavigatorUtils.push( |
374 | - decoration: const BoxDecoration( | 374 | + context, |
375 | - image: DecorationImage( | 375 | + '${PoemRouter.poemDetailPage}?id=100', |
376 | - image: AssetImage("assets/images/poem/poem_background.png"), | 376 | + ); |
377 | - fit: BoxFit.fill, | 377 | + }, |
378 | + child: AspectRatio( | ||
379 | + aspectRatio: 3.px / 4.0, | ||
380 | + child: Container( | ||
381 | + decoration: const BoxDecoration( | ||
382 | + image: DecorationImage( | ||
383 | + image: AssetImage("assets/images/poem/poem_background.png"), | ||
384 | + fit: BoxFit.fill, | ||
385 | + ), | ||
378 | ), | 386 | ), |
379 | - ), | 387 | + alignment: Alignment.center, |
380 | - alignment: Alignment.center, | 388 | + child: Text( |
381 | - child: Text( | 389 | + '一言', |
382 | - '一言', | 390 | + style: TextStyle( |
383 | - style: TextStyle( | 391 | + color: Colors.black54, |
384 | - color: Colors.black54, | 392 | + fontSize: 18.px, |
385 | - fontSize: 18.px, | 393 | + fontWeight: FontWeight.w900, |
386 | - fontWeight: FontWeight.w900, | 394 | + ), |
387 | ), | 395 | ), |
388 | ), | 396 | ), |
389 | ), | 397 | ), | ... | ... |
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,23 +86,18 @@ class _CategoryListPageState extends State<CategoryListPage> with AutomaticKeepA | ... | @@ -97,23 +86,18 @@ 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, |
104 | - onRefresh: _onRefresh, | 92 | + onRefresh: _onRefresh, |
105 | - loadMore: _loadMore, | 93 | + loadMore: _loadMore, |
106 | - hasMore: _page < _maxPage, | 94 | + hasMore: _page < _maxPage, |
107 | - itemBuilder: (_, index) { | 95 | + itemBuilder: (_, index) { |
108 | - return CategoryItem( | 96 | + return CategoryItem( |
109 | - index: index, | 97 | + index: index, |
110 | - selectIndex: _selectIndex, | 98 | + selectIndex: _selectIndex, |
111 | - item: _list[index], | 99 | + item: _list[index], |
112 | - ); | 100 | + ); |
113 | - } | 101 | + }); |
114 | - ); | ||
115 | } | 102 | } |
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 |
66 | - padding: const EdgeInsets.only(top: 0), | 63 | + ? ListView( |
67 | - controller: _scrollController, | 64 | + padding: const EdgeInsets.only(top: 0), |
68 | - children: <Widget>[ | 65 | + controller: _scrollController, |
69 | - ListView.builder( | 66 | + children: <Widget>[ |
70 | - padding: const EdgeInsets.only(top: 0), | 67 | + ListView.builder( |
71 | - itemBuilder: _mainListViewBuilder, | 68 | + padding: const EdgeInsets.only(top: 0), |
72 | - itemCount: _friendModelEntity.data.length, | 69 | + itemBuilder: _mainListViewBuilder, |
73 | - shrinkWrap: true, | 70 | + itemCount: _friendModelEntity.data!.length, |
74 | - physics: const NeverScrollableScrollPhysics(), | 71 | + shrinkWrap: true, |
75 | - ) | 72 | + physics: const NeverScrollableScrollPhysics(), |
76 | - ], | 73 | + ) |
77 | - ), | 74 | + ], |
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,35 +41,40 @@ typedef RefreshCallback = Future<void> Function(); | ... | @@ -40,35 +41,40 @@ 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 | + |
47 | @override | 47 | @override |
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 | - padding: widget.padding, | 55 | + ? widget.itemCount |
56 | - itemExtent: widget.itemExtent, | 56 | + : widget.itemCount + 1, |
57 | - itemBuilder: (BuildContext context, int index) { | 57 | + padding: widget.padding, |
58 | - /// 不需要加载更多则不需要添加FootView | 58 | + itemExtent: widget.itemExtent, |
59 | - if (widget.loadMore == null) { | 59 | + itemBuilder: (BuildContext context, int index) { |
60 | - return widget.itemBuilder(context, index); | 60 | + /// 不需要加载更多则不需要添加FootView |
61 | - } else { | 61 | + if (widget.loadMore == null) { |
62 | - return index < widget.itemCount ? widget.itemBuilder(context, index) : MoreWidget(widget.itemCount, widget.hasMore, widget.pageSize); | 62 | + return widget.itemBuilder(context, index); |
63 | - } | 63 | + } else { |
64 | - }, | 64 | + return index < widget.itemCount |
65 | - ), | 65 | + ? widget.itemBuilder(context, index) |
66 | + : MoreWidget( | ||
67 | + widget.itemCount, widget.hasMore, widget.pageSize); | ||
68 | + } | ||
69 | + }, | ||
70 | + ), | ||
66 | ); | 71 | ); |
67 | return SafeArea( | 72 | return SafeArea( |
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,20 +98,21 @@ class _DeerListViewState extends State<DeerListView> { | ... | @@ -92,20 +98,21 @@ 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; |
104 | final int pageSize; | 109 | final int pageSize; |
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