Showing
7 changed files
with
288 additions
and
263 deletions
... | @@ -22,6 +22,8 @@ class MessageLookup extends MessageLookupByLibrary { | ... | @@ -22,6 +22,8 @@ class MessageLookup extends MessageLookupByLibrary { |
22 | 22 | ||
23 | final messages = _notInlinedMessages(_notInlinedMessages); | 23 | final messages = _notInlinedMessages(_notInlinedMessages); |
24 | static Map<String, Function> _notInlinedMessages(_) => <String, Function>{ | 24 | static Map<String, Function> _notInlinedMessages(_) => <String, Function>{ |
25 | + "categoryBottomNavigationBarItemTitle": | ||
26 | + MessageLookupByLibrary.simpleMessage("category"), | ||
25 | "confirm": MessageLookupByLibrary.simpleMessage("Confirm"), | 27 | "confirm": MessageLookupByLibrary.simpleMessage("Confirm"), |
26 | "forgotPasswordLink": | 28 | "forgotPasswordLink": |
27 | MessageLookupByLibrary.simpleMessage("Forgot Password"), | 29 | MessageLookupByLibrary.simpleMessage("Forgot Password"), |
... | @@ -40,14 +42,20 @@ class MessageLookup extends MessageLookupByLibrary { | ... | @@ -40,14 +42,20 @@ class MessageLookup extends MessageLookupByLibrary { |
40 | "login": MessageLookupByLibrary.simpleMessage("Login"), | 42 | "login": MessageLookupByLibrary.simpleMessage("Login"), |
41 | "noAccountRegisterLink": MessageLookupByLibrary.simpleMessage( | 43 | "noAccountRegisterLink": MessageLookupByLibrary.simpleMessage( |
42 | "No account yet? Register now"), | 44 | "No account yet? Register now"), |
45 | + "onePoemBottomNavigationBarItemTitle": | ||
46 | + MessageLookupByLibrary.simpleMessage("Poem"), | ||
43 | "openYourAccount": | 47 | "openYourAccount": |
44 | MessageLookupByLibrary.simpleMessage("Open your account"), | 48 | MessageLookupByLibrary.simpleMessage("Open your account"), |
45 | "passwordLogin": MessageLookupByLibrary.simpleMessage("Password Login"), | 49 | "passwordLogin": MessageLookupByLibrary.simpleMessage("Password Login"), |
50 | + "profileBottomNavigationBarItemTitle": | ||
51 | + MessageLookupByLibrary.simpleMessage("profile"), | ||
46 | "register": MessageLookupByLibrary.simpleMessage("Register"), | 52 | "register": MessageLookupByLibrary.simpleMessage("Register"), |
47 | "registeredTips": MessageLookupByLibrary.simpleMessage( | 53 | "registeredTips": MessageLookupByLibrary.simpleMessage( |
48 | "Unregistered mobile phone number, please "), | 54 | "Unregistered mobile phone number, please "), |
49 | "resetLoginPassword": | 55 | "resetLoginPassword": |
50 | MessageLookupByLibrary.simpleMessage("Reset Login Password"), | 56 | MessageLookupByLibrary.simpleMessage("Reset Login Password"), |
57 | + "timelineBottomNavigationBarItemTitle": | ||
58 | + MessageLookupByLibrary.simpleMessage("timeline"), | ||
51 | "title": MessageLookupByLibrary.simpleMessage("One Poem"), | 59 | "title": MessageLookupByLibrary.simpleMessage("One Poem"), |
52 | "verificationButton": MessageLookupByLibrary.simpleMessage( | 60 | "verificationButton": MessageLookupByLibrary.simpleMessage( |
53 | "Not really sent, just log in!"), | 61 | "Not really sent, just log in!"), | ... | ... |
... | @@ -22,6 +22,8 @@ class MessageLookup extends MessageLookupByLibrary { | ... | @@ -22,6 +22,8 @@ class MessageLookup extends MessageLookupByLibrary { |
22 | 22 | ||
23 | final messages = _notInlinedMessages(_notInlinedMessages); | 23 | final messages = _notInlinedMessages(_notInlinedMessages); |
24 | static Map<String, Function> _notInlinedMessages(_) => <String, Function>{ | 24 | static Map<String, Function> _notInlinedMessages(_) => <String, Function>{ |
25 | + "categoryBottomNavigationBarItemTitle": | ||
26 | + MessageLookupByLibrary.simpleMessage("众妙"), | ||
25 | "confirm": MessageLookupByLibrary.simpleMessage("确认"), | 27 | "confirm": MessageLookupByLibrary.simpleMessage("确认"), |
26 | "forgotPasswordLink": MessageLookupByLibrary.simpleMessage("忘记密码"), | 28 | "forgotPasswordLink": MessageLookupByLibrary.simpleMessage("忘记密码"), |
27 | "getVerificationCode": MessageLookupByLibrary.simpleMessage("获取验证码"), | 29 | "getVerificationCode": MessageLookupByLibrary.simpleMessage("获取验证码"), |
... | @@ -34,12 +36,18 @@ class MessageLookup extends MessageLookupByLibrary { | ... | @@ -34,12 +36,18 @@ class MessageLookup extends MessageLookupByLibrary { |
34 | "login": MessageLookupByLibrary.simpleMessage("登录"), | 36 | "login": MessageLookupByLibrary.simpleMessage("登录"), |
35 | "noAccountRegisterLink": | 37 | "noAccountRegisterLink": |
36 | MessageLookupByLibrary.simpleMessage("还没账号?快去注册"), | 38 | MessageLookupByLibrary.simpleMessage("还没账号?快去注册"), |
39 | + "onePoemBottomNavigationBarItemTitle": | ||
40 | + MessageLookupByLibrary.simpleMessage("一言"), | ||
37 | "openYourAccount": MessageLookupByLibrary.simpleMessage("开启你的账号"), | 41 | "openYourAccount": MessageLookupByLibrary.simpleMessage("开启你的账号"), |
38 | "passwordLogin": MessageLookupByLibrary.simpleMessage("密码登录"), | 42 | "passwordLogin": MessageLookupByLibrary.simpleMessage("密码登录"), |
43 | + "profileBottomNavigationBarItemTitle": | ||
44 | + MessageLookupByLibrary.simpleMessage("我在"), | ||
39 | "register": MessageLookupByLibrary.simpleMessage("注册"), | 45 | "register": MessageLookupByLibrary.simpleMessage("注册"), |
40 | "registeredTips": | 46 | "registeredTips": |
41 | MessageLookupByLibrary.simpleMessage("提示:未注册账号的手机号,请先"), | 47 | MessageLookupByLibrary.simpleMessage("提示:未注册账号的手机号,请先"), |
42 | "resetLoginPassword": MessageLookupByLibrary.simpleMessage("重置登录密码"), | 48 | "resetLoginPassword": MessageLookupByLibrary.simpleMessage("重置登录密码"), |
49 | + "timelineBottomNavigationBarItemTitle": | ||
50 | + MessageLookupByLibrary.simpleMessage("临境"), | ||
43 | "title": MessageLookupByLibrary.simpleMessage("一言"), | 51 | "title": MessageLookupByLibrary.simpleMessage("一言"), |
44 | "verificationButton": | 52 | "verificationButton": |
45 | MessageLookupByLibrary.simpleMessage("并没有真正发送哦,直接登录吧!"), | 53 | MessageLookupByLibrary.simpleMessage("并没有真正发送哦,直接登录吧!"), | ... | ... |
... | @@ -229,6 +229,46 @@ class S { | ... | @@ -229,6 +229,46 @@ class S { |
229 | args: [], | 229 | args: [], |
230 | ); | 230 | ); |
231 | } | 231 | } |
232 | + | ||
233 | + /// `Poem` | ||
234 | + String get onePoemBottomNavigationBarItemTitle { | ||
235 | + return Intl.message( | ||
236 | + 'Poem', | ||
237 | + name: 'onePoemBottomNavigationBarItemTitle', | ||
238 | + desc: 'One Poem', | ||
239 | + args: [], | ||
240 | + ); | ||
241 | + } | ||
242 | + | ||
243 | + /// `timeline` | ||
244 | + String get timelineBottomNavigationBarItemTitle { | ||
245 | + return Intl.message( | ||
246 | + 'timeline', | ||
247 | + name: 'timelineBottomNavigationBarItemTitle', | ||
248 | + desc: 'One Poem', | ||
249 | + args: [], | ||
250 | + ); | ||
251 | + } | ||
252 | + | ||
253 | + /// `category` | ||
254 | + String get categoryBottomNavigationBarItemTitle { | ||
255 | + return Intl.message( | ||
256 | + 'category', | ||
257 | + name: 'categoryBottomNavigationBarItemTitle', | ||
258 | + desc: 'One Poem', | ||
259 | + args: [], | ||
260 | + ); | ||
261 | + } | ||
262 | + | ||
263 | + /// `profile` | ||
264 | + String get profileBottomNavigationBarItemTitle { | ||
265 | + return Intl.message( | ||
266 | + 'profile', | ||
267 | + name: 'profileBottomNavigationBarItemTitle', | ||
268 | + desc: 'One Poem', | ||
269 | + args: [], | ||
270 | + ); | ||
271 | + } | ||
232 | } | 272 | } |
233 | 273 | ||
234 | class AppLocalizationDelegate extends LocalizationsDelegate<S> { | 274 | class AppLocalizationDelegate extends LocalizationsDelegate<S> { | ... | ... |
... | @@ -106,5 +106,29 @@ | ... | @@ -106,5 +106,29 @@ |
106 | "description": "Registered Tips", | 106 | "description": "Registered Tips", |
107 | "type": "text", | 107 | "type": "text", |
108 | "placeholders": {} | 108 | "placeholders": {} |
109 | + }, | ||
110 | + "onePoemBottomNavigationBarItemTitle": "Poem", | ||
111 | + "@onePoemBottomNavigationBarItemTitle": { | ||
112 | + "description": "One Poem", | ||
113 | + "type": "text", | ||
114 | + "placeholders": {} | ||
115 | + }, | ||
116 | + "timelineBottomNavigationBarItemTitle": "timeline", | ||
117 | + "@timelineBottomNavigationBarItemTitle": { | ||
118 | + "description": "One Poem", | ||
119 | + "type": "text", | ||
120 | + "placeholders": {} | ||
121 | + }, | ||
122 | + "categoryBottomNavigationBarItemTitle": "category", | ||
123 | + "@categoryBottomNavigationBarItemTitle": { | ||
124 | + "description": "One Poem", | ||
125 | + "type": "text", | ||
126 | + "placeholders": {} | ||
127 | + }, | ||
128 | + "profileBottomNavigationBarItemTitle": "profile", | ||
129 | + "@profileBottomNavigationBarItemTitle": { | ||
130 | + "description": "One Poem", | ||
131 | + "type": "text", | ||
132 | + "placeholders": {} | ||
109 | } | 133 | } |
110 | } | 134 | } |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
... | @@ -16,5 +16,9 @@ | ... | @@ -16,5 +16,9 @@ |
16 | "getVerificationCode": "获取验证码", | 16 | "getVerificationCode": "获取验证码", |
17 | "confirm": "确认", | 17 | "confirm": "确认", |
18 | "resetLoginPassword": "重置登录密码", | 18 | "resetLoginPassword": "重置登录密码", |
19 | - "registeredTips": "提示:未注册账号的手机号,请先" | 19 | + "registeredTips": "提示:未注册账号的手机号,请先", |
20 | + "onePoemBottomNavigationBarItemTitle" : "一言", | ||
21 | + "timelineBottomNavigationBarItemTitle" : "临境", | ||
22 | + "categoryBottomNavigationBarItemTitle" : "众妙", | ||
23 | + "profileBottomNavigationBarItemTitle" : "我在" | ||
20 | } | 24 | } |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
1 | - | ||
2 | import 'package:flutter/material.dart'; | 1 | import 'package:flutter/material.dart'; |
3 | import 'package:one_poem/res/resources.dart'; | 2 | import 'package:one_poem/res/resources.dart'; |
4 | import 'package:one_poem/routers/fluro_navigator.dart'; | 3 | import 'package:one_poem/routers/fluro_navigator.dart'; | ... | ... |
1 | - | 1 | +import 'package:flutter/cupertino.dart'; |
2 | import 'package:flutter/material.dart'; | 2 | import 'package:flutter/material.dart'; |
3 | -import 'package:flutter/services.dart'; | ||
4 | -import 'package:one_poem/order/provider/order_page_provider.dart'; | ||
5 | -import 'package:one_poem/res/resources.dart'; | ||
6 | -import 'package:one_poem/routers/fluro_navigator.dart'; | ||
7 | -import 'package:one_poem/util/image_utils.dart'; | ||
8 | -import 'package:one_poem/util/theme_utils.dart'; | ||
9 | -import 'package:one_poem/util/screen_utils.dart'; | ||
10 | -import 'package:one_poem/widgets/load_image.dart'; | ||
11 | -import 'package:one_poem/widgets/my_card.dart'; | ||
12 | -import 'package:one_poem/widgets/my_flexible_space_bar.dart'; | ||
13 | -import 'package:provider/provider.dart'; | ||
14 | - | ||
15 | -import '../order_router.dart'; | ||
16 | -import 'order_list_page.dart'; | ||
17 | - | ||
18 | 3 | ||
19 | -/// design/3订单/index.html | ||
20 | class OrderPage extends StatefulWidget { | 4 | class OrderPage extends StatefulWidget { |
21 | - | ||
22 | const OrderPage({Key? key}) : super(key: key); | 5 | const OrderPage({Key? key}) : super(key: key); |
23 | 6 | ||
24 | @override | 7 | @override |
25 | _OrderPageState createState() => _OrderPageState(); | 8 | _OrderPageState createState() => _OrderPageState(); |
26 | } | 9 | } |
27 | 10 | ||
28 | -class _OrderPageState extends State<OrderPage> with AutomaticKeepAliveClientMixin<OrderPage>, SingleTickerProviderStateMixin { | 11 | +class _OrderPageState extends State<OrderPage> with WidgetsBindingObserver { |
12 | + TikTokPageTag tabBarType = TikTokPageTag.home; | ||
29 | 13 | ||
30 | - @override | 14 | + TikTokScaffoldController tkController = TikTokScaffoldController(); |
31 | - bool get wantKeepAlive => true; | ||
32 | - | ||
33 | - TabController? _tabController; | ||
34 | - OrderPageProvider provider = OrderPageProvider(); | ||
35 | 15 | ||
36 | - int _lastReportedPage = 0; | 16 | + PageController _pageController = PageController(); |
37 | - | 17 | + |
38 | - @override | 18 | + TikTokVideoListController _videoListController = TikTokVideoListController(); |
39 | - void initState() { | 19 | + |
40 | - super.initState(); | 20 | + /// 记录点赞 |
41 | - _tabController = TabController(vsync: this, length: 5); | 21 | + Map<int, bool> favoriteMap = {}; |
42 | - WidgetsBinding.instance!.addPostFrameCallback((_) { | 22 | + |
43 | - /// 预先缓存剩余切换图片 | 23 | + List<UserVideo> videoDataList = []; |
44 | - _preCacheImage(); | ||
45 | - }); | ||
46 | - } | ||
47 | 24 | ||
48 | - void _preCacheImage() { | 25 | + @override |
49 | - precacheImage(ImageUtils.getAssetImage('order/xdd_n'), context); | 26 | + void didChangeAppLifecycleState(AppLifecycleState state) async { |
50 | - precacheImage(ImageUtils.getAssetImage('order/dps_s'), context); | 27 | + if (state != AppLifecycleState.resumed) { |
51 | - precacheImage(ImageUtils.getAssetImage('order/dwc_s'), context); | 28 | + _videoListController.currentPlayer.pause(); |
52 | - precacheImage(ImageUtils.getAssetImage('order/ywc_s'), context); | 29 | + } |
53 | - precacheImage(ImageUtils.getAssetImage('order/yqx_s'), context); | ||
54 | } | 30 | } |
55 | 31 | ||
56 | @override | 32 | @override |
57 | void dispose() { | 33 | void dispose() { |
58 | - _tabController?.dispose(); | 34 | + WidgetsBinding.instance!.removeObserver(this); |
35 | + _videoListController.currentPlayer.pause(); | ||
59 | super.dispose(); | 36 | super.dispose(); |
60 | } | 37 | } |
61 | 38 | ||
62 | - bool isDark = false; | ||
63 | - | ||
64 | @override | 39 | @override |
65 | - Widget build(BuildContext context) { | 40 | + void initState() { |
66 | - super.build(context); | 41 | + videoDataList = UserVideo.fetchVideo(); |
67 | - isDark = context.isDark; | 42 | + WidgetsBinding.instance!.addObserver(this); |
68 | - return ChangeNotifierProvider<OrderPageProvider>( | 43 | + _videoListController.init( |
69 | - create: (_) => provider, | 44 | + pageController: _pageController, |
70 | - child: Scaffold( | 45 | + initialList: videoDataList |
71 | - body: Stack( | 46 | + .map( |
72 | - children: <Widget>[ | 47 | + (e) => VPVideoController( |
73 | - /// 像素对齐问题的临时解决方法 | 48 | + videoInfo: e, |
74 | - SafeArea( | 49 | + builder: () => VideoPlayerController.network(e.url), |
75 | - child: SizedBox( | ||
76 | - height: 105, | ||
77 | - width: double.infinity, | ||
78 | - child: isDark ? null : const DecoratedBox( | ||
79 | - decoration: BoxDecoration( | ||
80 | - gradient: LinearGradient(colors: [Colours.gradient_blue, Color(0xFF4647FA)]), | ||
81 | - ), | ||
82 | - ), | ||
83 | - ), | ||
84 | - ), | ||
85 | - NestedScrollView( | ||
86 | - key: const Key('order_list'), | ||
87 | - physics: const ClampingScrollPhysics(), | ||
88 | - headerSliverBuilder: (context, innerBoxIsScrolled) => _sliverBuilder(context), | ||
89 | - body: NotificationListener<ScrollNotification>( | ||
90 | - onNotification: (ScrollNotification notification) { | ||
91 | - /// PageView的onPageChanged是监听ScrollUpdateNotification,会造成滑动中卡顿。这里修改为监听滚动结束再更新、 | ||
92 | - if (notification.depth == 0 && notification is ScrollEndNotification) { | ||
93 | - final PageMetrics metrics = notification.metrics as PageMetrics; | ||
94 | - final int currentPage = (metrics.page ?? 0).round(); | ||
95 | - if (currentPage != _lastReportedPage) { | ||
96 | - _lastReportedPage = currentPage; | ||
97 | - _onPageChange(currentPage); | ||
98 | - } | ||
99 | - } | ||
100 | - return false; | ||
101 | - }, | ||
102 | - child: PageView.builder( | ||
103 | - key: const Key('pageView'), | ||
104 | - itemCount: 5, | ||
105 | - controller: _pageController, | ||
106 | - itemBuilder: (_, index) => OrderListPage(index: index), | ||
107 | - ), | ||
108 | - ), | ||
109 | - ), | ||
110 | - ], | ||
111 | ), | 50 | ), |
112 | - ), | 51 | + ) |
113 | - ); | 52 | + .toList(), |
114 | - } | 53 | + videoProvider: (int index, List<VPVideoController> list) async { |
115 | - | 54 | + return videoDataList |
116 | - List<Widget> _sliverBuilder(BuildContext context) { | 55 | + .map( |
117 | - return <Widget>[ | 56 | + (e) => VPVideoController( |
118 | - SliverOverlapAbsorber( | 57 | + videoInfo: e, |
119 | - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), | 58 | + builder: () => VideoPlayerController.network(e.url), |
120 | - sliver: SliverAppBar( | ||
121 | - systemOverlayStyle: SystemUiOverlayStyle.light, | ||
122 | - actions: <Widget>[ | ||
123 | - IconButton( | ||
124 | - onPressed: () { | ||
125 | - NavigatorUtils.push(context, OrderRouter.orderSearchPage); | ||
126 | - }, | ||
127 | - tooltip: '搜索', | ||
128 | - icon: LoadAssetImage('order/icon_search', | ||
129 | - width: 22.0, | ||
130 | - height: 22.0, | ||
131 | - color: ThemeUtils.getIconColor(context), | ||
132 | - ), | ||
133 | - ) | ||
134 | - ], | ||
135 | - backgroundColor: Colors.transparent, | ||
136 | - elevation: 0.0, | ||
137 | - centerTitle: true, | ||
138 | - expandedHeight: 100.0, // 不随着滑动隐藏标题 | ||
139 | - pinned: true, // 固定在顶部 | ||
140 | - flexibleSpace: MyFlexibleSpaceBar( | ||
141 | - background: isDark ? Container(height: 113.0, color: Colours.dark_bg_color,) : LoadAssetImage('order/order_bg', | ||
142 | - width: context.width, | ||
143 | - height: 113.0, | ||
144 | - fit: BoxFit.fill, | ||
145 | - ), | ||
146 | - centerTitle: true, | ||
147 | - titlePadding: const EdgeInsetsDirectional.only(start: 16.0, bottom: 14.0), | ||
148 | - collapseMode: CollapseMode.pin, | ||
149 | - title: Text('订单', style: TextStyle(color: ThemeUtils.getIconColor(context)),), | ||
150 | ), | 59 | ), |
151 | - ), | 60 | + ) |
152 | - ), | 61 | + .toList(); |
153 | - SliverPersistentHeader( | 62 | + }, |
154 | - pinned: true, | 63 | + ); |
155 | - delegate: SliverAppBarDelegate( | 64 | + _videoListController.addListener(() { |
156 | - DecoratedBox( | 65 | + setState(() {}); |
157 | - decoration: BoxDecoration( | 66 | + }); |
158 | - color: isDark ? Colours.dark_bg_color : null, | 67 | + tkController.addListener( |
159 | - image: isDark ? null : DecorationImage( | 68 | + () { |
160 | - image: ImageUtils.getAssetImage('order/order_bg1'), | 69 | + if (tkController.value == TikTokPagePositon.middle) { |
161 | - fit: BoxFit.fill, | 70 | + _videoListController.currentPlayer.play(); |
162 | - ), | 71 | + } else { |
163 | - ), | 72 | + _videoListController.currentPlayer.pause(); |
164 | - child: Padding( | 73 | + } |
165 | - padding: const EdgeInsets.symmetric(horizontal: 16.0), | 74 | + }, |
166 | - child: MyCard( | 75 | + ); |
167 | - child: Container( | ||
168 | - height: 80.0, | ||
169 | - padding: const EdgeInsets.only(top: 8.0), | ||
170 | - child: TabBar( | ||
171 | - labelPadding: EdgeInsets.zero, | ||
172 | - controller: _tabController, | ||
173 | - labelColor: context.isDark ? Colours.dark_text : Colours.text, | ||
174 | - unselectedLabelColor: context.isDark ? Colours.dark_text_gray : Colours.text, | ||
175 | - labelStyle: TextStyles.textBold14, | ||
176 | - unselectedLabelStyle: const TextStyle( | ||
177 | - fontSize: Dimens.font_sp14, | ||
178 | - ), | ||
179 | - indicatorColor: Colors.transparent, | ||
180 | - tabs: const <Widget>[ | ||
181 | - _TabView(0, '新订单'), | ||
182 | - _TabView(1, '待配送'), | ||
183 | - _TabView(2, '待完成'), | ||
184 | - _TabView(3, '已完成'), | ||
185 | - _TabView(4, '已取消'), | ||
186 | - ], | ||
187 | - onTap: (index) { | ||
188 | - if (!mounted) { | ||
189 | - return; | ||
190 | - } | ||
191 | - _pageController.jumpToPage(index); | ||
192 | - }, | ||
193 | - ), | ||
194 | - ), | ||
195 | - ), | ||
196 | - ), | ||
197 | - ), 80.0, | ||
198 | - ), | ||
199 | - ), | ||
200 | - ]; | ||
201 | - } | ||
202 | 76 | ||
203 | - final PageController _pageController = PageController(); | 77 | + super.initState(); |
204 | - Future<void> _onPageChange(int index) async { | ||
205 | - provider.setIndex(index); | ||
206 | - /// 这里没有指示器,所以缩短过渡动画时间,减少不必要的刷新 | ||
207 | - _tabController?.animateTo(index, duration: Duration.zero); | ||
208 | } | 78 | } |
209 | -} | ||
210 | - | ||
211 | -List<List<String>> img = [ | ||
212 | - ['order/xdd_s', 'order/xdd_n'], | ||
213 | - ['order/dps_s', 'order/dps_n'], | ||
214 | - ['order/dwc_s', 'order/dwc_n'], | ||
215 | - ['order/ywc_s', 'order/ywc_n'], | ||
216 | - ['order/yqx_s', 'order/yqx_n'] | ||
217 | -]; | ||
218 | - | ||
219 | -List<List<String>> darkImg = [ | ||
220 | - ['order/dark/icon_xdd_s', 'order/dark/icon_xdd_n'], | ||
221 | - ['order/dark/icon_dps_s', 'order/dark/icon_dps_n'], | ||
222 | - ['order/dark/icon_dwc_s', 'order/dark/icon_dwc_n'], | ||
223 | - ['order/dark/icon_ywc_s', 'order/dark/icon_ywc_n'], | ||
224 | - ['order/dark/icon_yqx_s', 'order/dark/icon_yqx_n'] | ||
225 | -]; | ||
226 | 79 | ||
227 | -class _TabView extends StatelessWidget { | ||
228 | - | ||
229 | - const _TabView(this.index, this.text); | ||
230 | - | ||
231 | - final int index; | ||
232 | - final String text; | ||
233 | - | ||
234 | @override | 80 | @override |
235 | Widget build(BuildContext context) { | 81 | Widget build(BuildContext context) { |
236 | - final List<List<String>> imgList = context.isDark ? darkImg : img; | 82 | + Widget? currentPage; |
237 | - return Stack( | 83 | + |
238 | - children: <Widget>[ | 84 | + switch (tabBarType) { |
239 | - Container( | 85 | + case TikTokPageTag.home: |
240 | - width: 46.0, | 86 | + break; |
241 | - padding: const EdgeInsets.symmetric(vertical: 8.0), | 87 | + case TikTokPageTag.follow: |
242 | - child: Column( | 88 | + currentPage = FollowPage(); |
243 | - children: <Widget>[ | 89 | + break; |
244 | - /// 使用context.select替代Consumer | 90 | + case TikTokPageTag.msg: |
245 | - LoadAssetImage(context.select<OrderPageProvider, int>((value) => value.index) == index ? | 91 | + currentPage = MsgPage(); |
246 | - imgList[index][0] : | 92 | + break; |
247 | - imgList[index][1], width: 24.0, height: 24.0,), | 93 | + case TikTokPageTag.me: |
248 | - Gaps.vGap4, | 94 | + currentPage = UserPage(isSelfPage: true); |
249 | - Text(text), | 95 | + break; |
250 | - ], | 96 | + } |
97 | + double a = MediaQuery.of(context).size.aspectRatio; | ||
98 | + bool hasBottomPadding = a < 0.55; | ||
99 | + | ||
100 | + bool hasBackground = hasBottomPadding; | ||
101 | + hasBackground = tabBarType != TikTokPageTag.home; | ||
102 | + if (hasBottomPadding) { | ||
103 | + hasBackground = true; | ||
104 | + } | ||
105 | + Widget tikTokTabBar = TikTokTabBar( | ||
106 | + hasBackground: hasBackground, | ||
107 | + current: tabBarType, | ||
108 | + onTabSwitch: (type) async { | ||
109 | + setState(() { | ||
110 | + tabBarType = type; | ||
111 | + if (type == TikTokPageTag.home) { | ||
112 | + _videoListController.currentPlayer.play(); | ||
113 | + } else { | ||
114 | + _videoListController.currentPlayer.pause(); | ||
115 | + } | ||
116 | + }); | ||
117 | + }, | ||
118 | + onAddButton: () { | ||
119 | + Navigator.of(context).push( | ||
120 | + MaterialPageRoute( | ||
121 | + fullscreenDialog: true, | ||
122 | + builder: (context) => CameraPage(), | ||
251 | ), | 123 | ), |
252 | - ), | 124 | + ); |
253 | - Positioned( | 125 | + }, |
254 | - right: 0.0, | ||
255 | - child: index < 3 ? DecoratedBox( | ||
256 | - decoration: BoxDecoration( | ||
257 | - color: Theme.of(context).errorColor, | ||
258 | - borderRadius: BorderRadius.circular(11.0), | ||
259 | - ), | ||
260 | - child: const Padding( | ||
261 | - padding: EdgeInsets.symmetric(horizontal: 5.5, vertical: 2.0), | ||
262 | - child: Text('10', style: TextStyle(color: Colors.white, fontSize: Dimens.font_sp12),), | ||
263 | - ), | ||
264 | - ) : Gaps.empty, | ||
265 | - ) | ||
266 | - ], | ||
267 | ); | 126 | ); |
268 | - } | ||
269 | -} | ||
270 | - | ||
271 | -class SliverAppBarDelegate extends SliverPersistentHeaderDelegate { | ||
272 | - | ||
273 | - SliverAppBarDelegate(this.widget, this.height); | ||
274 | - | ||
275 | - final Widget widget; | ||
276 | - final double height; | ||
277 | - | ||
278 | - // minHeight 和 maxHeight 的值设置为相同时,header就不会收缩了 | ||
279 | - @override | ||
280 | - double get minExtent => height; | ||
281 | - | ||
282 | - @override | ||
283 | - double get maxExtent => height; | ||
284 | 127 | ||
285 | - @override | 128 | + var userPage = UserPage( |
286 | - Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) { | 129 | + isSelfPage: false, |
287 | - return widget; | 130 | + canPop: true, |
288 | - } | 131 | + onPop: () { |
132 | + tkController.animateToMiddle(); | ||
133 | + }, | ||
134 | + ); | ||
135 | + var searchPage = SearchPage( | ||
136 | + onPop: tkController.animateToMiddle, | ||
137 | + ); | ||
289 | 138 | ||
290 | - @override | 139 | + var header = tabBarType == TikTokPageTag.home |
291 | - bool shouldRebuild(SliverAppBarDelegate oldDelegate) { | 140 | + ? TikTokHeader( |
292 | - return true; | 141 | + onSearch: () { |
142 | + tkController.animateToLeft(); | ||
143 | + }, | ||
144 | + ) | ||
145 | + : Container(); | ||
146 | + | ||
147 | + // 组合 | ||
148 | + return TikTokScaffold( | ||
149 | + controller: tkController, | ||
150 | + hasBottomPadding: hasBackground, | ||
151 | + tabBar: tikTokTabBar, | ||
152 | + header: header, | ||
153 | + leftPage: searchPage, | ||
154 | + rightPage: userPage, | ||
155 | + enableGesture: tabBarType == TikTokPageTag.home, | ||
156 | + // onPullDownRefresh: _fetchData, | ||
157 | + page: Stack( | ||
158 | + // index: currentPage == null ? 0 : 1, | ||
159 | + children: <Widget>[ | ||
160 | + PageView.builder( | ||
161 | + key: Key('home'), | ||
162 | + physics: QuickerScrollPhysics(), | ||
163 | + controller: _pageController, | ||
164 | + scrollDirection: Axis.vertical, | ||
165 | + itemCount: _videoListController.videoCount, | ||
166 | + itemBuilder: (context, i) { | ||
167 | + // 拼一个视频组件出来 | ||
168 | + bool isF = SafeMap(favoriteMap)[i].boolean ?? false; | ||
169 | + var player = _videoListController.playerOfIndex(i)!; | ||
170 | + var data = player.videoInfo!; | ||
171 | + // 右侧按钮列 | ||
172 | + Widget buttons = TikTokButtonColumn( | ||
173 | + isFavorite: isF, | ||
174 | + onAvatar: () { | ||
175 | + tkController.animateToPage(TikTokPagePositon.right); | ||
176 | + }, | ||
177 | + onFavorite: () { | ||
178 | + setState(() { | ||
179 | + favoriteMap[i] = !isF; | ||
180 | + }); | ||
181 | + // showAboutDialog(context: context); | ||
182 | + }, | ||
183 | + onComment: () { | ||
184 | + CustomBottomSheet.showModalBottomSheet( | ||
185 | + backgroundColor: Colors.white.withOpacity(0), | ||
186 | + context: context, | ||
187 | + builder: (BuildContext context) => | ||
188 | + TikTokCommentBottomSheet(), | ||
189 | + ); | ||
190 | + }, | ||
191 | + onShare: () {}, | ||
192 | + ); | ||
193 | + // video | ||
194 | + Widget currentVideo = Center( | ||
195 | + child: AspectRatio( | ||
196 | + aspectRatio: player.controller.value.aspectRatio, | ||
197 | + child: VideoPlayer(player.controller), | ||
198 | + ), | ||
199 | + ); | ||
200 | + | ||
201 | + currentVideo = TikTokVideoPage( | ||
202 | + // 手势播放与自然播放都会产生暂停按钮状态变化,待处理 | ||
203 | + hidePauseIcon: !player.showPauseIcon.value, | ||
204 | + aspectRatio: 9 / 16.0, | ||
205 | + key: Key(data.url + '$i'), | ||
206 | + tag: data.url, | ||
207 | + bottomPadding: hasBottomPadding ? 16.0 : 16.0, | ||
208 | + userInfoWidget: VideoUserInfo( | ||
209 | + desc: data.desc, | ||
210 | + bottomPadding: hasBottomPadding ? 16.0 : 50.0, | ||
211 | + ), | ||
212 | + onSingleTap: () async { | ||
213 | + if (player.controller.value.isPlaying) { | ||
214 | + await player.pause(); | ||
215 | + } else { | ||
216 | + await player.play(); | ||
217 | + } | ||
218 | + setState(() {}); | ||
219 | + }, | ||
220 | + onAddFavorite: () { | ||
221 | + setState(() { | ||
222 | + favoriteMap[i] = true; | ||
223 | + }); | ||
224 | + }, | ||
225 | + rightButtonColumn: buttons, | ||
226 | + video: currentVideo, | ||
227 | + ); | ||
228 | + return currentVideo; | ||
229 | + }, | ||
230 | + ), | ||
231 | + currentPage ?? Container(), | ||
232 | + ], | ||
233 | + ), | ||
234 | + ); | ||
293 | } | 235 | } |
294 | } | 236 | } | ... | ... |
-
Please register or login to post a comment