Showing
3 changed files
with
561 additions
and
0 deletions
... | @@ -2,6 +2,8 @@ import 'package:flutter/cupertino.dart'; | ... | @@ -2,6 +2,8 @@ import 'package:flutter/cupertino.dart'; |
2 | import 'package:flutter/material.dart'; | 2 | import 'package:flutter/material.dart'; |
3 | import 'package:one_poem/tiktok/controller/tiktok_video_list_controller.dart'; | 3 | import 'package:one_poem/tiktok/controller/tiktok_video_list_controller.dart'; |
4 | import 'package:one_poem/tiktok/mock/video.dart'; | 4 | import 'package:one_poem/tiktok/mock/video.dart'; |
5 | +import 'package:one_poem/tiktok/pages/search_page.dart'; | ||
6 | +import 'package:one_poem/tiktok/pages/user_page.dart'; | ||
5 | import 'package:one_poem/tiktok/style/physics.dart'; | 7 | import 'package:one_poem/tiktok/style/physics.dart'; |
6 | import 'package:one_poem/tiktok/views/tiktok_header.dart'; | 8 | import 'package:one_poem/tiktok/views/tiktok_header.dart'; |
7 | import 'package:one_poem/tiktok/views/tiktok_scaffold.dart'; | 9 | import 'package:one_poem/tiktok/views/tiktok_scaffold.dart'; |
... | @@ -96,10 +98,23 @@ class _PoemPageState extends State<PoemPage> with WidgetsBindingObserver { | ... | @@ -96,10 +98,23 @@ class _PoemPageState extends State<PoemPage> with WidgetsBindingObserver { |
96 | }, | 98 | }, |
97 | ); | 99 | ); |
98 | 100 | ||
101 | + var userPage = UserPage( | ||
102 | + isSelfPage: false, | ||
103 | + canPop: true, | ||
104 | + onPop: () { | ||
105 | + tkController.animateToMiddle(); | ||
106 | + }, | ||
107 | + ); | ||
108 | + var searchPage = SearchPage( | ||
109 | + onPop: tkController.animateToMiddle, | ||
110 | + ); | ||
111 | + | ||
99 | // 组合 | 112 | // 组合 |
100 | return TikTokScaffold( | 113 | return TikTokScaffold( |
101 | controller: tkController, | 114 | controller: tkController, |
102 | header: header, | 115 | header: header, |
116 | + leftPage: searchPage, | ||
117 | + rightPage: userPage, | ||
103 | enableGesture: true, | 118 | enableGesture: true, |
104 | page: Stack( | 119 | page: Stack( |
105 | // index: currentPage == null ? 0 : 1, | 120 | // index: currentPage == null ? 0 : 1, | ... | ... |
lib/tiktok/pages/search_page.dart
0 → 100644
1 | +import 'package:flutter/material.dart'; | ||
2 | +import 'package:one_poem/tiktok/style/style.dart'; | ||
3 | +import 'package:tapped/tapped.dart'; | ||
4 | + | ||
5 | +class SearchPage extends StatefulWidget { | ||
6 | + final Function? onPop; | ||
7 | + | ||
8 | + const SearchPage({ | ||
9 | + Key? key, | ||
10 | + this.onPop, | ||
11 | + }) : super(key: key); | ||
12 | + @override | ||
13 | + _SearchPageState createState() => _SearchPageState(); | ||
14 | +} | ||
15 | + | ||
16 | +class _SearchPageState extends State<SearchPage> { | ||
17 | + @override | ||
18 | + Widget build(BuildContext context) { | ||
19 | + Widget head = Container( | ||
20 | + padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top), | ||
21 | + color: ColorPlate.back2, | ||
22 | + width: double.infinity, | ||
23 | + alignment: Alignment.center, | ||
24 | + child: Container( | ||
25 | + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), | ||
26 | + child: Row( | ||
27 | + children: <Widget>[ | ||
28 | + const Icon( | ||
29 | + Icons.fullscreen, | ||
30 | + size: 24, | ||
31 | + ), | ||
32 | + Expanded( | ||
33 | + child: Container( | ||
34 | + height: 32, | ||
35 | + margin: const EdgeInsets.only(right: 20, left: 12), | ||
36 | + decoration: BoxDecoration( | ||
37 | + color: Colors.white.withOpacity(0.2), | ||
38 | + borderRadius: BorderRadius.circular(4), | ||
39 | + ), | ||
40 | + padding: const EdgeInsets.only(left: 12), | ||
41 | + child: Opacity( | ||
42 | + opacity: 0.3, | ||
43 | + child: Row( | ||
44 | + children: <Widget>[ | ||
45 | + const Icon( | ||
46 | + Icons.search, | ||
47 | + size: 20, | ||
48 | + ), | ||
49 | + Container( | ||
50 | + padding: const EdgeInsets.only(left: 2, bottom: 2), | ||
51 | + child: const Text( | ||
52 | + '搜索内容', | ||
53 | + style: StandardTextStyle.normal, | ||
54 | + ), | ||
55 | + ) | ||
56 | + ], | ||
57 | + ), | ||
58 | + ), | ||
59 | + ), | ||
60 | + ), | ||
61 | + Tapped( | ||
62 | + child: Text( | ||
63 | + '取消', | ||
64 | + style: StandardTextStyle.normal.apply(color: ColorPlate.orange), | ||
65 | + ), | ||
66 | + onTap: widget.onPop, | ||
67 | + ), | ||
68 | + ], | ||
69 | + ), | ||
70 | + ), | ||
71 | + ); | ||
72 | + Widget body = ListView( | ||
73 | + padding: EdgeInsets.zero, | ||
74 | + children: <Widget>[ | ||
75 | + const _SearchSelectRow(), | ||
76 | + const _SearchSelectRow(), | ||
77 | + const Opacity( | ||
78 | + opacity: 0.6, | ||
79 | + child: SizedBox( | ||
80 | + height: 46, | ||
81 | + child: Center(child: Text('全部搜索记录')), | ||
82 | + ), | ||
83 | + ), | ||
84 | + Container( | ||
85 | + margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 16), | ||
86 | + child: AspectRatio( | ||
87 | + aspectRatio: 4.0, | ||
88 | + child: Container( | ||
89 | + decoration: BoxDecoration( | ||
90 | + color: ColorPlate.darkGray, | ||
91 | + border: Border.all(color: Colors.black), | ||
92 | + borderRadius: BorderRadius.circular(8), | ||
93 | + ), | ||
94 | + alignment: Alignment.center, | ||
95 | + child: Text( | ||
96 | + '预留轮播图', | ||
97 | + style: TextStyle( | ||
98 | + color: Colors.white.withOpacity(0.1), | ||
99 | + fontSize: 18, | ||
100 | + fontWeight: FontWeight.w900, | ||
101 | + ), | ||
102 | + ), | ||
103 | + ), | ||
104 | + ), | ||
105 | + ), | ||
106 | + ], | ||
107 | + ); | ||
108 | + return Scaffold( | ||
109 | + body: Container( | ||
110 | + color: ColorPlate.back1, | ||
111 | + height: double.infinity, | ||
112 | + width: double.infinity, | ||
113 | + child: Column( | ||
114 | + children: <Widget>[ | ||
115 | + head, | ||
116 | + Expanded(child: body), | ||
117 | + ], | ||
118 | + ), | ||
119 | + ), | ||
120 | + ); | ||
121 | + } | ||
122 | +} | ||
123 | + | ||
124 | +class _SearchSelectRow extends StatelessWidget { | ||
125 | + const _SearchSelectRow({ | ||
126 | + Key? key, | ||
127 | + }) : super(key: key); | ||
128 | + | ||
129 | + @override | ||
130 | + Widget build(BuildContext context) { | ||
131 | + return Container( | ||
132 | + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), | ||
133 | + child: Row( | ||
134 | + children: <Widget>[ | ||
135 | + const Icon( | ||
136 | + Icons.timelapse, | ||
137 | + size: 20, | ||
138 | + ), | ||
139 | + Expanded( | ||
140 | + child: Container( | ||
141 | + padding: const EdgeInsets.only(left: 8, bottom: 1), | ||
142 | + child: const Text( | ||
143 | + '搜索唐诗宋词元曲3000首', | ||
144 | + style: StandardTextStyle.normal, | ||
145 | + ), | ||
146 | + ), | ||
147 | + ), | ||
148 | + const Icon( | ||
149 | + Icons.clear, | ||
150 | + size: 20, | ||
151 | + ), | ||
152 | + ], | ||
153 | + ), | ||
154 | + ); | ||
155 | + } | ||
156 | +} |
lib/tiktok/pages/user_page.dart
0 → 100644
1 | +import 'package:flutter/material.dart'; | ||
2 | +import 'package:one_poem/tiktok/style/style.dart'; | ||
3 | +import 'package:tapped/tapped.dart'; | ||
4 | +import 'package:flutter_gen/gen_l10n/one_poem_localizations.dart'; | ||
5 | + | ||
6 | +class UserPage extends StatefulWidget { | ||
7 | + final bool canPop; | ||
8 | + final bool isSelfPage; | ||
9 | + final Function? onPop; | ||
10 | + final Function? onSwitch; | ||
11 | + | ||
12 | + const UserPage({ | ||
13 | + Key? key, | ||
14 | + this.canPop = false, | ||
15 | + this.onPop, | ||
16 | + required this.isSelfPage, | ||
17 | + this.onSwitch, | ||
18 | + }) : super(key: key); | ||
19 | + | ||
20 | + @override | ||
21 | + _UserPageState createState() => _UserPageState(); | ||
22 | +} | ||
23 | + | ||
24 | +class _UserPageState extends State<UserPage> { | ||
25 | + @override | ||
26 | + Widget build(BuildContext context) { | ||
27 | + Widget likeButton = Container( | ||
28 | + color: ColorPlate.back1, | ||
29 | + child: Row( | ||
30 | + crossAxisAlignment: CrossAxisAlignment.start, | ||
31 | + mainAxisAlignment: MainAxisAlignment.end, | ||
32 | + children: <Widget>[ | ||
33 | + Tapped( | ||
34 | + child: _UserRightButton( | ||
35 | + title: widget.isSelfPage ? '钱包' : '关注', | ||
36 | + ), | ||
37 | + ), | ||
38 | + ], | ||
39 | + ), | ||
40 | + ); | ||
41 | + Widget avatar = Container( | ||
42 | + height: 120 + MediaQuery.of(context).padding.top, | ||
43 | + padding: const EdgeInsets.only(left: 18), | ||
44 | + alignment: Alignment.bottomLeft, | ||
45 | + child: OverflowBox( | ||
46 | + alignment: Alignment.bottomLeft, | ||
47 | + minHeight: 20, | ||
48 | + maxHeight: 300, | ||
49 | + child: Container( | ||
50 | + height: 74, | ||
51 | + width: 74, | ||
52 | + margin: const EdgeInsets.only(bottom: 12), | ||
53 | + decoration: BoxDecoration( | ||
54 | + borderRadius: BorderRadius.circular(44), | ||
55 | + color: Colors.orange, | ||
56 | + border: Border.all( | ||
57 | + color: Colors.white, | ||
58 | + width: 1, | ||
59 | + ), | ||
60 | + ), | ||
61 | + child: ClipOval( | ||
62 | + child: Image.network( | ||
63 | + "https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif", | ||
64 | + fit: BoxFit.cover, | ||
65 | + ), | ||
66 | + ), | ||
67 | + ), | ||
68 | + ), | ||
69 | + ); | ||
70 | + Widget body = ListView( | ||
71 | + physics: const BouncingScrollPhysics( | ||
72 | + parent: AlwaysScrollableScrollPhysics(), | ||
73 | + ), | ||
74 | + children: <Widget>[ | ||
75 | + Container(height: 20), | ||
76 | + // 头像与关注 | ||
77 | + Stack( | ||
78 | + alignment: Alignment.bottomLeft, | ||
79 | + children: <Widget>[likeButton, avatar], | ||
80 | + ), | ||
81 | + Container( | ||
82 | + color: ColorPlate.back1, | ||
83 | + child: Column( | ||
84 | + children: <Widget>[ | ||
85 | + Container( | ||
86 | + padding: const EdgeInsets.only(left: 18), | ||
87 | + color: ColorPlate.back1, | ||
88 | + child: Column( | ||
89 | + crossAxisAlignment: CrossAxisAlignment.start, | ||
90 | + children: <Widget>[ | ||
91 | + const Text( | ||
92 | + '@唐宋八大家TOP8', | ||
93 | + style: StandardTextStyle.big, | ||
94 | + ), | ||
95 | + Container(height: 8), | ||
96 | + Text( | ||
97 | + '朴实无华,且枯燥', | ||
98 | + style: StandardTextStyle.smallWithOpacity.apply( | ||
99 | + color: Colors.white, | ||
100 | + ), | ||
101 | + ), | ||
102 | + Container(height: 10), | ||
103 | + Row( | ||
104 | + children: const <Widget>[ | ||
105 | + _UserTag(tag: '幽默'), | ||
106 | + _UserTag(tag: '机智'), | ||
107 | + _UserTag(tag: '枯燥'), | ||
108 | + _UserTag(tag: '狮子座'), | ||
109 | + ], | ||
110 | + ), | ||
111 | + Container(height: 10), | ||
112 | + ], | ||
113 | + ), | ||
114 | + ), | ||
115 | + Container( | ||
116 | + color: ColorPlate.back1, | ||
117 | + padding: const EdgeInsets.symmetric( | ||
118 | + horizontal: 8, | ||
119 | + vertical: 2, | ||
120 | + ), | ||
121 | + child: Row( | ||
122 | + mainAxisAlignment: MainAxisAlignment.start, | ||
123 | + crossAxisAlignment: CrossAxisAlignment.center, | ||
124 | + children: const <Widget>[ | ||
125 | + TextGroup('356', '关注'), | ||
126 | + TextGroup('145万', '粉丝'), | ||
127 | + TextGroup('1423万', '获赞'), | ||
128 | + ], | ||
129 | + ), | ||
130 | + ), | ||
131 | + Container( | ||
132 | + height: 10, | ||
133 | + margin: const EdgeInsets.symmetric(horizontal: 12), | ||
134 | + decoration: BoxDecoration( | ||
135 | + border: Border( | ||
136 | + bottom: BorderSide( | ||
137 | + color: Colors.white.withOpacity(0.1), | ||
138 | + ), | ||
139 | + ), | ||
140 | + ), | ||
141 | + ), | ||
142 | + const _UserVideoTable(), | ||
143 | + ], | ||
144 | + ), | ||
145 | + ), | ||
146 | + ], | ||
147 | + ); | ||
148 | + return Container( | ||
149 | + decoration: const BoxDecoration( | ||
150 | + gradient: LinearGradient( | ||
151 | + begin: Alignment.topCenter, | ||
152 | + colors: <Color>[ | ||
153 | + Colors.orange, | ||
154 | + Colors.red, | ||
155 | + ], | ||
156 | + ), | ||
157 | + ), | ||
158 | + child: Stack( | ||
159 | + alignment: Alignment.topCenter, | ||
160 | + children: <Widget>[ | ||
161 | + Container( | ||
162 | + margin: const EdgeInsets.only(top: 400), | ||
163 | + height: double.infinity, | ||
164 | + width: double.infinity, | ||
165 | + color: ColorPlate.back1, | ||
166 | + ), | ||
167 | + body, | ||
168 | + ], | ||
169 | + ), | ||
170 | + ); | ||
171 | + } | ||
172 | +} | ||
173 | + | ||
174 | +class _UserRightButton extends StatelessWidget { | ||
175 | + const _UserRightButton({ | ||
176 | + Key? key, | ||
177 | + required this.title, | ||
178 | + }) : super(key: key); | ||
179 | + | ||
180 | + final String title; | ||
181 | + | ||
182 | + @override | ||
183 | + Widget build(BuildContext context) { | ||
184 | + return Container( | ||
185 | + padding: const EdgeInsets.symmetric( | ||
186 | + vertical: 6, | ||
187 | + horizontal: 20, | ||
188 | + ), | ||
189 | + margin: const EdgeInsets.all(8), | ||
190 | + alignment: Alignment.center, | ||
191 | + child: Text( | ||
192 | + title, | ||
193 | + style: const TextStyle(color: ColorPlate.orange), | ||
194 | + ), | ||
195 | + decoration: BoxDecoration( | ||
196 | + border: Border.all(color: ColorPlate.orange), | ||
197 | + borderRadius: BorderRadius.circular(4), | ||
198 | + ), | ||
199 | + ); | ||
200 | + } | ||
201 | +} | ||
202 | + | ||
203 | +class _UserTag extends StatelessWidget { | ||
204 | + final String? tag; | ||
205 | + const _UserTag({ | ||
206 | + Key? key, | ||
207 | + this.tag, | ||
208 | + }) : super(key: key); | ||
209 | + | ||
210 | + @override | ||
211 | + Widget build(BuildContext context) { | ||
212 | + return Container( | ||
213 | + margin: const EdgeInsets.symmetric(horizontal: 4), | ||
214 | + padding: const EdgeInsets.symmetric( | ||
215 | + vertical: 2, | ||
216 | + horizontal: 4, | ||
217 | + ), | ||
218 | + decoration: BoxDecoration( | ||
219 | + border: Border.all( | ||
220 | + color: Colors.white.withOpacity(0.3), | ||
221 | + ), | ||
222 | + borderRadius: BorderRadius.circular(4), | ||
223 | + ), | ||
224 | + child: Text( | ||
225 | + tag ?? '标签', | ||
226 | + style: StandardTextStyle.smallWithOpacity, | ||
227 | + ), | ||
228 | + ); | ||
229 | + } | ||
230 | +} | ||
231 | + | ||
232 | +class _UserVideoTable extends StatelessWidget { | ||
233 | + const _UserVideoTable({ | ||
234 | + Key? key, | ||
235 | + }) : super(key: key); | ||
236 | + | ||
237 | + @override | ||
238 | + Widget build(BuildContext context) { | ||
239 | + return Column( | ||
240 | + children: <Widget>[ | ||
241 | + Container( | ||
242 | + color: ColorPlate.back1, | ||
243 | + padding: const EdgeInsets.symmetric( | ||
244 | + vertical: 12, | ||
245 | + ), | ||
246 | + child: Row( | ||
247 | + mainAxisAlignment: MainAxisAlignment.center, | ||
248 | + crossAxisAlignment: CrossAxisAlignment.center, | ||
249 | + children: <Widget>[ | ||
250 | + _PointSelectTextButton( | ||
251 | + true, | ||
252 | + OnePoemLocalizations.of(context) | ||
253 | + .onePoemBottomNavigationBarItemTitle, | ||
254 | + ), | ||
255 | + _PointSelectTextButton( | ||
256 | + false, | ||
257 | + OnePoemLocalizations.of(context) | ||
258 | + .timelineBottomNavigationBarItemTitle), | ||
259 | + _PointSelectTextButton( | ||
260 | + false, | ||
261 | + OnePoemLocalizations.of(context) | ||
262 | + .categoryBottomNavigationBarItemTitle), | ||
263 | + ], | ||
264 | + ), | ||
265 | + ), | ||
266 | + Row( | ||
267 | + children: const <Widget>[ | ||
268 | + _SmallVideo(), | ||
269 | + _SmallVideo(), | ||
270 | + _SmallVideo(), | ||
271 | + ], | ||
272 | + ), | ||
273 | + Row( | ||
274 | + children: const <Widget>[ | ||
275 | + _SmallVideo(), | ||
276 | + _SmallVideo(), | ||
277 | + _SmallVideo(), | ||
278 | + ], | ||
279 | + ), | ||
280 | + ], | ||
281 | + ); | ||
282 | + } | ||
283 | +} | ||
284 | + | ||
285 | +class _SmallVideo extends StatelessWidget { | ||
286 | + const _SmallVideo({ | ||
287 | + Key? key, | ||
288 | + }) : super(key: key); | ||
289 | + | ||
290 | + @override | ||
291 | + Widget build(BuildContext context) { | ||
292 | + return Expanded( | ||
293 | + child: AspectRatio( | ||
294 | + aspectRatio: 3 / 4.0, | ||
295 | + child: Container( | ||
296 | + decoration: BoxDecoration( | ||
297 | + color: ColorPlate.darkGray, | ||
298 | + border: Border.all(color: Colors.black), | ||
299 | + ), | ||
300 | + alignment: Alignment.center, | ||
301 | + child: Text( | ||
302 | + '一言', | ||
303 | + style: TextStyle( | ||
304 | + color: Colors.white.withOpacity(0.1), | ||
305 | + fontSize: 18, | ||
306 | + fontWeight: FontWeight.w900, | ||
307 | + ), | ||
308 | + ), | ||
309 | + ), | ||
310 | + ), | ||
311 | + ); | ||
312 | + } | ||
313 | +} | ||
314 | + | ||
315 | +class _PointSelectTextButton extends StatelessWidget { | ||
316 | + final bool isSelect; | ||
317 | + final String title; | ||
318 | + final Function? onTap; | ||
319 | + const _PointSelectTextButton( | ||
320 | + this.isSelect, | ||
321 | + this.title, { | ||
322 | + Key? key, | ||
323 | + this.onTap, | ||
324 | + }) : super(key: key); | ||
325 | + | ||
326 | + @override | ||
327 | + Widget build(BuildContext context) { | ||
328 | + return Expanded( | ||
329 | + child: Row( | ||
330 | + mainAxisAlignment: MainAxisAlignment.center, | ||
331 | + children: <Widget>[ | ||
332 | + isSelect | ||
333 | + ? Container( | ||
334 | + width: 6, | ||
335 | + height: 6, | ||
336 | + decoration: BoxDecoration( | ||
337 | + color: ColorPlate.orange, | ||
338 | + borderRadius: BorderRadius.circular(3), | ||
339 | + ), | ||
340 | + ) | ||
341 | + : Container(), | ||
342 | + Container( | ||
343 | + padding: const EdgeInsets.only(left: 2), | ||
344 | + child: Text( | ||
345 | + title, | ||
346 | + style: isSelect | ||
347 | + ? StandardTextStyle.small | ||
348 | + : StandardTextStyle.smallWithOpacity, | ||
349 | + ), | ||
350 | + ) | ||
351 | + ], | ||
352 | + ), | ||
353 | + ); | ||
354 | + } | ||
355 | +} | ||
356 | + | ||
357 | +class TextGroup extends StatelessWidget { | ||
358 | + final String title, tag; | ||
359 | + final Color? color; | ||
360 | + | ||
361 | + const TextGroup( | ||
362 | + this.title, | ||
363 | + this.tag, { | ||
364 | + Key? key, | ||
365 | + this.color, | ||
366 | + }) : super(key: key); | ||
367 | + | ||
368 | + @override | ||
369 | + Widget build(BuildContext context) { | ||
370 | + return Container( | ||
371 | + padding: const EdgeInsets.symmetric(vertical: 0, horizontal: 8), | ||
372 | + child: Row( | ||
373 | + crossAxisAlignment: CrossAxisAlignment.end, | ||
374 | + children: <Widget>[ | ||
375 | + Text( | ||
376 | + title, | ||
377 | + style: StandardTextStyle.big.apply(color: color), | ||
378 | + ), | ||
379 | + Container(width: 4), | ||
380 | + Text( | ||
381 | + tag, | ||
382 | + style: StandardTextStyle.smallWithOpacity.apply( | ||
383 | + color: color?.withOpacity(0.6), | ||
384 | + ), | ||
385 | + ), | ||
386 | + ], | ||
387 | + ), | ||
388 | + ); | ||
389 | + } | ||
390 | +} |
-
Please register or login to post a comment