home_content.dart 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806
  1. import 'dart:async';
  2. import 'dart:convert';
  3. import 'package:flutter/material.dart';
  4. import 'package:flutter_svg/svg.dart';
  5. import 'package:get/get.dart';
  6. import 'package:link/utils/global.dart';
  7. import 'package:link/view/home_social_list.dart';
  8. import '../model/model.dart';
  9. import '../utils/size_fit.dart';
  10. import '../utils/storage.dart';
  11. import '../utils/util.dart';
  12. import 'home_add_link.dart';
  13. class HomeContent extends StatefulWidget {
  14. UserBean userBean;
  15. Map<String, dynamic> styles;
  16. GlobalKey? _itemkey;
  17. GlobalKey? _addLinkkey;
  18. List socials;
  19. double scale;
  20. // ignore: prefer_typing_uninitialized_variables
  21. var _openMenu, _share;
  22. bool _isPreview = false;
  23. HomeContent({
  24. Key? key,
  25. required this.userBean,
  26. required this.styles,
  27. required this.socials,
  28. GlobalKey? itemkey,
  29. GlobalKey? addLinkkey,
  30. required this.scale,
  31. var openMenu,
  32. var share,
  33. bool? isPreview,
  34. }) : super(key: key) {
  35. if (openMenu != null) {
  36. _openMenu = openMenu;
  37. }
  38. if (share != null) {
  39. _share = share;
  40. }
  41. if (isPreview != null) {
  42. _isPreview = isPreview;
  43. }
  44. if (itemkey != null) {
  45. _itemkey = itemkey;
  46. }
  47. if (addLinkkey != null) {
  48. _addLinkkey = addLinkkey;
  49. }
  50. }
  51. @override
  52. State<HomeContent> createState() => _HomeContentState();
  53. }
  54. class _HomeContentState extends State<HomeContent> {
  55. bool isExpanded = false;
  56. bool isMyPage = false;
  57. GlobalKey columnKey = GlobalKey();
  58. int bottomStatus = -1; //copyright -1都不显示 0 显示相对布局 1 显示绝对布局
  59. @override
  60. void initState() {
  61. // TODO: implement initState
  62. super.initState();
  63. if (Global().hasLogin &&
  64. StorageUtil().getJSON('userInfo')['id'] == widget.userBean.id) {
  65. isMyPage = true;
  66. }
  67. // bottomStatus = 0;
  68. // if (bottomStatus != -1) {
  69. // return;
  70. // }
  71. Timer(const Duration(milliseconds: 300), () {
  72. RenderBox widget =
  73. columnKey.currentContext!.findRenderObject() as RenderBox;
  74. setState(() {
  75. if (widget.size.height >= MediaQuery.of(context).size.height) {
  76. bottomStatus = 0;
  77. } else {
  78. bottomStatus = 1;
  79. }
  80. });
  81. });
  82. }
  83. Widget background() {
  84. var background = widget.styles['background'];
  85. if (background['type'] == 'single-color') {
  86. String strColor = background['color'].substring(1, 9);
  87. int value = int.parse(strColor, radix: 16);
  88. return Container(
  89. color: Color(value),
  90. );
  91. }
  92. if (background['type'] == 'skew') {
  93. double screenHeight = MediaQuery.of(context).size.height;
  94. String strTopColor = background['top_color'].substring(1, 9);
  95. int topColor = int.parse(strTopColor, radix: 16);
  96. String strBottomColor = background['bottom_color'].substring(1, 9);
  97. int bottomColor = int.parse(strBottomColor, radix: 16);
  98. String strSperateColor = background['seprate_line_color'].substring(1, 9);
  99. int sperateColor = int.parse(strSperateColor, radix: 16);
  100. double topLeft = double.parse(background['top_left_y']);
  101. double topRight = double.parse(background['top_right_y']);
  102. if (topLeft == topRight) {
  103. return Container(
  104. color: Color(topColor),
  105. width: 375.px * widget.scale,
  106. height: screenHeight * widget.scale,
  107. child: Column(
  108. children: [
  109. SizedBox(
  110. height: topLeft * widget.scale,
  111. ),
  112. Container(
  113. height: screenHeight * widget.scale - topLeft * widget.scale,
  114. width: 375.px * widget.scale,
  115. decoration: BoxDecoration(
  116. color: Color(bottomColor),
  117. borderRadius: BorderRadius.only(
  118. topLeft: Radius.circular(
  119. double.parse(background['top_left_corner']).px *
  120. widget.scale),
  121. topRight: Radius.circular(
  122. double.parse(background['top_right_corner']).px *
  123. widget.scale)),
  124. // border: Border(
  125. // top: BorderSide(
  126. // color: Colors.red,
  127. // width: double.parse(
  128. // background['seprate_line_width'])))
  129. ))
  130. ],
  131. ),
  132. );
  133. }
  134. return Container(
  135. color: Color(topColor),
  136. width: 375.px * widget.scale,
  137. height: screenHeight * widget.scale,
  138. child: Stack(children: [
  139. ClipPath(
  140. clipper: SkewCut(topLeft.px * widget.scale, topRight.px * widget.scale),
  141. child: Container(
  142. // decoration: const BoxDecoration(
  143. // gradient:
  144. // LinearGradient(colors: [Colors.blue, Colors.pink])),
  145. color: Color(bottomColor),
  146. width: 375.px * widget.scale,
  147. height: screenHeight * widget.scale,
  148. ),
  149. ),
  150. CustomPaint(
  151. painter: SkewPaint(
  152. topLeft.px * widget.scale,
  153. topRight.px * widget.scale,
  154. Color(sperateColor),
  155. double.parse(background['seprate_line_width']) * widget.scale,
  156. widget.scale))
  157. ]),
  158. );
  159. }
  160. List<Color> colors = [];
  161. List<double> stops = [];
  162. background['colors'].forEach((item) {
  163. String strColor = item['color'].substring(1, 9);
  164. int value = int.parse(strColor, radix: 16);
  165. colors.add(Color(value));
  166. stops.add(item['percent'] * 0.01);
  167. });
  168. double corner = double.parse(background['corner']);
  169. // double corner = 90;
  170. if (corner > 90) {
  171. corner = 90;
  172. }
  173. double beginLeft = corner==0?0:-corner / 45;
  174. double beginTop = -1;
  175. double endLeft = corner / 45;
  176. double endTop = 1.0;
  177. if (corner > 45) {
  178. beginTop = -(1 - (corner - 45) / 45);
  179. endTop = 1 - (corner - 45) / 45;
  180. }
  181. if (beginLeft < -1) {
  182. beginLeft = -1.0;
  183. }
  184. if (endLeft > 1) {
  185. endLeft = 1.0;
  186. }
  187. return Container(
  188. decoration: BoxDecoration(
  189. gradient: LinearGradient(
  190. begin: Alignment(beginLeft, beginTop),
  191. end: Alignment(endLeft, endTop),
  192. colors: colors,
  193. stops: stops
  194. )),
  195. );
  196. }
  197. Widget topWidget() {
  198. return Container(
  199. width: 375.px * widget.scale,
  200. child: Row(
  201. children: [
  202. if (widget._isPreview && widget.scale == 1.0)
  203. GestureDetector(
  204. onTap: () {
  205. Get.back();
  206. },
  207. // onTap: (){Get.to(()=>const EditScreen());print('helo');},
  208. child: Container(
  209. height: 72.px,
  210. alignment: Alignment.centerLeft,
  211. padding: EdgeInsets.only(
  212. left: 24.px * widget.scale, right: 24.px * widget.scale),
  213. child: Text(
  214. '退出预览',
  215. style: TextStyle(
  216. fontSize: 14.px,
  217. color: Util().stringToColor(
  218. widget.styles['toolbar']['left_icon']['color']),
  219. ),
  220. ),
  221. ),
  222. ),
  223. if (!widget._isPreview || (widget._isPreview && widget.scale != 1.0))
  224. GestureDetector(
  225. onTap: () {
  226. if (StorageUtil().getBool('hasLogin') == null ||
  227. StorageUtil().getBool('hasLogin') == false) {
  228. Get.toNamed('/welcome');
  229. return;
  230. }
  231. if (!isMyPage) {
  232. Get.toNamed('/', parameters: {}, preventDuplicates: false);
  233. return;
  234. }
  235. widget._openMenu();
  236. // Get.toNamed('/detail');
  237. },
  238. // onTap: (){Get.to(()=>const EditScreen());print('helo');},
  239. child: Container(
  240. height: 72.px * widget.scale,
  241. padding: EdgeInsets.only(
  242. left: 24.px * widget.scale, right: 24.px * widget.scale),
  243. child: SvgPicture.asset(
  244. isMyPage
  245. ? 'assets/icons/navi_menu.svg'
  246. : 'assets/icons/home.svg',
  247. width: 24.px * widget.scale,
  248. height: 24.px * widget.scale,
  249. color: Util().stringToColor(
  250. widget.styles['toolbar']['left_icon']['color']),
  251. ),
  252. ),
  253. ),
  254. const Expanded(
  255. child: SizedBox(
  256. height: 1.0,
  257. )),
  258. if (isMyPage && !widget._isPreview)
  259. GestureDetector(
  260. onTap: () {
  261. Get.toNamed('/home_preview',
  262. parameters: {"style": jsonEncode(widget.styles)});
  263. // Get.toNamed('/',
  264. // parameters: {'preview': '1'}, preventDuplicates: false);
  265. },
  266. child: Container(
  267. margin: EdgeInsets.only(right: 0.px),
  268. child: SvgPicture.asset(
  269. 'assets/icons/preview.svg',
  270. width: 36.px * widget.scale,
  271. height: 24.px * widget.scale,
  272. color: Util().stringToColor(
  273. widget.styles['toolbar']['right_icon']['color']),
  274. )),
  275. ),
  276. GestureDetector(
  277. onTap: () {
  278. widget._share();
  279. // js.context.callMethod('share',['hi']);
  280. },
  281. child: Container(
  282. height: 72.px * widget.scale,
  283. padding: EdgeInsets.only(
  284. left: 24.px * widget.scale, right: 24.px * widget.scale),
  285. child: SvgPicture.asset(
  286. 'assets/icons/navi_share.svg',
  287. width: 24.px * widget.scale,
  288. height: 24.px * widget.scale,
  289. color: Util().stringToColor(
  290. widget.styles['toolbar']['right_icon']['color']),
  291. ),
  292. ),
  293. )
  294. ],
  295. ),
  296. );
  297. }
  298. Widget avatarWidget() {
  299. var avatarObj = widget.styles['avatar'];
  300. String strColor = '';
  301. if (avatarObj['border_color'] != null &&
  302. avatarObj['border_color'].length >= 9) {
  303. strColor = avatarObj['border_color'].substring(1, 9);
  304. }
  305. Color borderColor;
  306. if (strColor.isEmpty) {
  307. borderColor = Colors.transparent;
  308. } else {
  309. int value = int.parse(strColor, radix: 16);
  310. borderColor = Color(value);
  311. }
  312. AlignmentGeometry alignmentGeometry = Alignment.center;
  313. double marginLeft = 0.0;
  314. double marginRight = 0.0;
  315. if (avatarObj['type'] == 'left') {
  316. alignmentGeometry = Alignment.centerLeft;
  317. if (!avatarObj['margin_left'].isEmpty) {
  318. marginLeft = double.parse(avatarObj['margin_left']);
  319. }
  320. } else if (avatarObj['type'] == 'right') {
  321. alignmentGeometry = Alignment.centerRight;
  322. if (!avatarObj['margin_right'].isEmpty) {
  323. marginLeft = double.parse(avatarObj['margin_right']);
  324. }
  325. }
  326. return Container(
  327. width: 375.px * widget.scale,
  328. alignment: alignmentGeometry,
  329. margin: EdgeInsets.only(
  330. left: marginLeft * widget.scale,
  331. right: marginRight * widget.scale,
  332. top: double.parse(avatarObj['top']).px * widget.scale),
  333. child: ClipRRect(
  334. borderRadius: BorderRadius.circular(
  335. double.parse(avatarObj['border_radius']).px * widget.scale),
  336. child: Container(
  337. decoration: BoxDecoration(
  338. image: DecorationImage(
  339. image: NetworkImage(widget.userBean.avatar), fit: BoxFit.cover),
  340. borderRadius: BorderRadius.circular(
  341. double.parse(avatarObj['border_radius']).px * widget.scale),
  342. border: Border.all(
  343. color: borderColor,
  344. width:
  345. double.parse(avatarObj['border_width']).px * widget.scale),
  346. ),
  347. width: double.parse(avatarObj['width']).px * widget.scale,
  348. height: double.parse(avatarObj['height']).px * widget.scale,
  349. // child: Image.network(userBean!.avatar),
  350. ),
  351. ),
  352. );
  353. }
  354. Widget nicknameWidget() {
  355. var nickObj = widget.styles['nickname'];
  356. String strColor = nickObj['color'].substring(1, 9);
  357. int value = int.parse(strColor, radix: 16);
  358. TextAlign textAlign = TextAlign.center;
  359. if (nickObj['type'] == 'left') {
  360. textAlign = TextAlign.left;
  361. } else if (nickObj['type'] == 'right') {
  362. textAlign = TextAlign.right;
  363. }
  364. FontWeight fontWeight = FontWeight.normal;
  365. if (nickObj['font_weight'] == 'bold') {
  366. fontWeight = FontWeight.bold;
  367. }
  368. return Container(
  369. width: 375.px * widget.scale,
  370. margin:
  371. EdgeInsets.only(top: double.parse(nickObj['top']).px * widget.scale),
  372. child: Text(
  373. widget.userBean.nickname!,
  374. textAlign: textAlign,
  375. style: TextStyle(
  376. color: Color(value),
  377. fontSize: double.parse(nickObj['font_size']).px * widget.scale,
  378. fontWeight: fontWeight),
  379. ),
  380. );
  381. }
  382. Widget signatureWidget() {
  383. var signatureObj = widget.styles['signature'];
  384. double left = double.parse(signatureObj['margin_left']).px * widget.scale;
  385. double right = double.parse(signatureObj['margin_right']).px * widget.scale;
  386. String strColor = signatureObj['color'].substring(1, 9);
  387. int value = int.parse(strColor, radix: 16);
  388. TextAlign textAlign = TextAlign.center;
  389. if (signatureObj['type'] == 'left') {
  390. textAlign = TextAlign.left;
  391. } else if (signatureObj['type'] == 'right') {
  392. textAlign = TextAlign.right;
  393. }
  394. double height = double.parse(signatureObj['line_height']) /
  395. double.parse(signatureObj['font_size']);
  396. int lines = int.parse(signatureObj['num_lines']);
  397. TextStyle style = TextStyle(
  398. color: Color(value),
  399. height: height,
  400. fontSize: double.parse(signatureObj['font_size']).px * widget.scale);
  401. String content = widget.userBean.signature!;
  402. bool showExpand = false;
  403. String strShow = '';
  404. double width = (375.px - left - right) * widget.scale;
  405. double maxHeight =
  406. lines * Util().boundingTextSize('1', style, width).height;
  407. if (Util().boundingTextSize(content, style, width).height <= maxHeight ||
  408. isExpanded) {
  409. strShow = content;
  410. } else {
  411. for (int i = 5 * lines; i < content.length; i++) {
  412. if (!showExpand && !isExpanded) {
  413. String subString = content.substring(0, i) + '...';
  414. if (Util().boundingTextSize(subString, style, width).height >
  415. maxHeight) {
  416. strShow = content.substring(0, i - 8);// + '...';
  417. showExpand = true;
  418. }
  419. }
  420. }
  421. }
  422. if (showExpand) {
  423. return Container(
  424. margin: EdgeInsets.only(
  425. top: double.parse(signatureObj['top']),
  426. left: left,
  427. right: right,
  428. ),
  429. child: Stack(
  430. children: [
  431. Text(
  432. strShow,
  433. textAlign: textAlign,
  434. style: style,
  435. ),
  436. Positioned(
  437. right: 0,
  438. bottom: 0,
  439. child: GestureDetector(
  440. onTap: () {
  441. setState(() {
  442. isExpanded = true;
  443. });
  444. },
  445. child: Container(
  446. height: maxHeight / lines,
  447. // width: maxHeight / lines,
  448. alignment: Alignment.center,
  449. child: Text('…更多',style: TextStyle(color: const Color(0x33131314),fontSize: 13.px*widget.scale),)
  450. // SvgPicture.asset(
  451. // 'assets/icons/arrow_down.svg',
  452. // color:
  453. // Util().stringToColor(signatureObj['icon']['color']),
  454. // width: double.parse(signatureObj['icon']['width']),
  455. // height: double.parse(signatureObj['icon']['height']),
  456. // ),
  457. ),
  458. ))
  459. ],
  460. ));
  461. }
  462. return Container(
  463. margin: EdgeInsets.only(
  464. top: double.parse(signatureObj['top']).px * widget.scale,
  465. left: left,
  466. right: right,
  467. ),
  468. child: Text(
  469. strShow,
  470. textAlign: textAlign,
  471. // softWrap: true,
  472. // overflow: TextOverflow.ellipsis,
  473. style: style,
  474. // maxLines: lines //,
  475. ),
  476. );
  477. }
  478. Widget locationWidget() {
  479. var locationObj = widget.styles['location'];
  480. double top = 0.0;
  481. if (locationObj['top'] != null) {
  482. top = double.parse(locationObj['top']).px * widget.scale;
  483. }
  484. return Container(
  485. alignment: Alignment.center,
  486. margin: EdgeInsets.only(top: top),
  487. child: Row(
  488. mainAxisAlignment: MainAxisAlignment.center,
  489. children: [
  490. Container(
  491. height: double.parse(locationObj['height']).px * widget.scale,
  492. width: double.parse(locationObj['height']).px * widget.scale,
  493. alignment: Alignment.center,
  494. child: SvgPicture.asset(
  495. widget.userBean.sex == 'MALE'
  496. ? 'assets/icons/gender_male.svg'
  497. : 'assets/icons/gender_female.svg',
  498. width: double.parse(locationObj['gender']['width']).px *
  499. widget.scale,
  500. height: double.parse(locationObj['gender']['height']).px *
  501. widget.scale,
  502. color: Util().stringToColor(locationObj['gender']['color']),
  503. ),
  504. decoration: BoxDecoration(
  505. borderRadius: BorderRadius.all(Radius.circular(
  506. double.parse(locationObj['height']).px /
  507. 2.0 *
  508. widget.scale)),
  509. border: Border.all(
  510. color: Util().stringToColor(locationObj['border_color']),
  511. width: double.parse(locationObj['border_width']).px *
  512. widget.scale)),
  513. ),
  514. SizedBox(
  515. width: double.parse(locationObj['space_width']).px * widget.scale,
  516. ),
  517. Container(
  518. height: double.parse(locationObj['height']).px * widget.scale,
  519. alignment: Alignment.center,
  520. padding: EdgeInsets.only(
  521. left: double.parse(locationObj['address']['padding_horizontal'])
  522. .px *
  523. widget.scale,
  524. right:
  525. double.parse(locationObj['address']['padding_horizontal'])
  526. .px *
  527. widget.scale),
  528. child: Row(
  529. children: [
  530. SvgPicture.asset('assets/icons/location.svg',
  531. width: double.parse(locationObj['gender']['width']).px *
  532. widget.scale,
  533. height: double.parse(locationObj['gender']['height']).px *
  534. widget.scale,
  535. color:
  536. Util().stringToColor(locationObj['gender']['color'])),
  537. SizedBox(
  538. width: 4.px,
  539. ),
  540. Text(
  541. widget.userBean.country! + ' ' + widget.userBean.city!,
  542. style: TextStyle(
  543. fontSize: double.parse(locationObj['address']['font_size']).px * widget.scale,
  544. color: Util()
  545. .stringToColor(locationObj['address']['color'])),
  546. )
  547. ],
  548. ),
  549. decoration: BoxDecoration(
  550. borderRadius: BorderRadius.all(Radius.circular(
  551. double.parse(locationObj['height']).px /
  552. 2.0 *
  553. widget.scale)),
  554. border: Border.all(
  555. color: Util().stringToColor(locationObj['border_color']),
  556. width: double.parse(locationObj['border_width']).px *
  557. widget.scale)),
  558. )
  559. ],
  560. ),
  561. );
  562. }
  563. Widget socialWidget() {
  564. var socialObj = widget.styles['social_item'];
  565. double borderWidth = 0.0;
  566. if (socialObj['border_width'] != null) {
  567. borderWidth = double.parse(socialObj['border_width']);
  568. }
  569. return Column(children: [
  570. SizedBox(
  571. height: double.parse(socialObj['margin_top']).px * widget.scale,
  572. ),
  573. if (isMyPage && widget.userBean.socials!.length > 1 && !widget._isPreview)
  574. Container(
  575. alignment: Alignment.center,
  576. width: double.parse(socialObj['width']).px * widget.scale,
  577. height: (double.parse(socialObj['height']) +
  578. 2 * borderWidth +
  579. double.parse((socialObj['space_height'])).px)
  580. .px *
  581. widget.userBean.socials!.length *
  582. widget.scale,
  583. child: Theme(
  584. data: Theme.of(context).copyWith(
  585. canvasColor: Colors.transparent,
  586. shadowColor: Colors.transparent,
  587. ),
  588. child: SocialList(
  589. isMyPage: isMyPage,
  590. userBean: widget.userBean,
  591. socials: widget.socials,
  592. styles: widget.styles,
  593. itemkey: widget._itemkey,
  594. canDrag: true,
  595. scale: widget.scale,
  596. )),
  597. ),
  598. if (!isMyPage || widget.userBean.socials!.length < 2 || widget._isPreview)
  599. SocialList(
  600. isMyPage: isMyPage,
  601. userBean: widget.userBean,
  602. socials: widget.socials,
  603. styles: widget.styles,
  604. itemkey: widget._itemkey,
  605. canDrag: false,
  606. scale: widget.scale,
  607. ),
  608. if (isMyPage && widget._isPreview == false)
  609. GestureDetector(
  610. onTap: () {
  611. Get.toNamed('/begin_add_first_link',
  612. parameters: {'add_more': '1'});
  613. },
  614. child: HomeAddLink(
  615. socialObj: socialObj,
  616. addLinkkey: widget._addLinkkey,
  617. scale: widget.scale,
  618. ))
  619. ]);
  620. }
  621. Widget copyrightWidget(bool isPositioned) {
  622. double bottom = 20.0;
  623. var copyrightObj = widget.styles['copy_right'];
  624. if (copyrightObj['bottom'] != null) {
  625. bottom = double.parse(copyrightObj['bottom']);
  626. }
  627. Color color = Colors.black;
  628. if (copyrightObj['color'] != null) {
  629. color = Util().stringToColor(copyrightObj['color']);
  630. }
  631. if (!isPositioned) {
  632. return Opacity(
  633. opacity: bottomStatus == 0 ? 1 : 0,
  634. child: Container(
  635. alignment: Alignment.center,
  636. child: Text(
  637. '2022 © LINKBaeBae 链接吧,宝贝!',
  638. style: TextStyle(color: color, fontSize: 10.px * widget.scale),
  639. ),
  640. ),
  641. );
  642. }
  643. return Positioned(
  644. bottom: bottom,
  645. left: 0,
  646. right: 0,
  647. child: Opacity(
  648. opacity: bottomStatus == 1 ? 1 : 0,
  649. child: Container(
  650. alignment: Alignment.center,
  651. child: Text(
  652. '2022 © LINKBaeBae 链接吧,宝贝!',
  653. style: TextStyle(color: color, fontSize: 10.px * widget.scale),
  654. ),
  655. ),
  656. ));
  657. }
  658. @override
  659. Widget build(BuildContext context) {
  660. SizeFit.initialize(context);
  661. var backObj = widget.styles['background'];
  662. return Container(
  663. width: 375.px * widget.scale,
  664. color: backObj['type'] == 'skew'
  665. ? (backObj['top_left_y']==backObj['top_right_y']?Util().stringToColor(backObj['top_color']):Util().stringToColor(backObj['bottom_color']))
  666. : Colors.transparent,
  667. child: Stack(
  668. children: [
  669. if (backObj['type'] != 'skew') background(),
  670. if (backObj['type'] == 'skew')
  671. Positioned(
  672. left: 0,
  673. right: 0,
  674. bottom: 0,
  675. height: 400.px * widget.scale,
  676. child: Container(
  677. width: 375.px * widget.scale,
  678. height: 400.px * widget.scale,
  679. color: (backObj['top_left_y']==backObj['top_right_y']?Util().stringToColor(backObj['bottom_color']):Util().stringToColor(backObj['top_color'])),
  680. )),
  681. SingleChildScrollView(
  682. child: Stack(
  683. children: [
  684. if (backObj['type'] == 'skew') background(),
  685. Container(
  686. // color: backObj['type'] == 'skew'
  687. // ? (backObj['top_left_y']==backObj['top_right_y']?Util().stringToColor(backObj['top_color']):Util().stringToColor(backObj['bottom_color']))
  688. // : Colors.transparent,
  689. child: Column(
  690. key: columnKey,
  691. children: [
  692. avatarWidget(),
  693. nicknameWidget(),
  694. locationWidget(),
  695. signatureWidget(),
  696. socialWidget(),
  697. SizedBox(
  698. height: 30.px,
  699. ),
  700. copyrightWidget(false),
  701. SizedBox(
  702. height: 30.px,
  703. )
  704. ],
  705. ),
  706. ),
  707. ],
  708. )),
  709. topWidget(),
  710. copyrightWidget(true),
  711. ],
  712. ),
  713. );
  714. }
  715. }
  716. class SkewCut extends CustomClipper<Path> {
  717. double topLeft;
  718. double topRight;
  719. SkewCut(this.topLeft, this.topRight);
  720. @override
  721. Path getClip(Size size) {
  722. final path = Path();
  723. // path.lineTo(size.width, 0);
  724. // path.lineTo(size.width - 20, size.height);
  725. // path.lineTo(0, size.height);
  726. path.lineTo(0, 0);
  727. path.lineTo(0, topLeft);
  728. path.lineTo(size.width, topRight);
  729. path.lineTo(size.width, 0);
  730. path.close();
  731. return path;
  732. }
  733. @override
  734. bool shouldReclip(covariant CustomClipper<Path> oldClipper) {
  735. // TODO: implement shouldReclip
  736. return false;
  737. }
  738. }
  739. class SkewPaint extends CustomPainter {
  740. Paint? myPaint;
  741. double topLeft;
  742. double topRight;
  743. Color lineColor;
  744. double lineWidth;
  745. double scale;
  746. SkewPaint(
  747. this.topLeft, this.topRight, this.lineColor, this.lineWidth, this.scale);
  748. @override
  749. void paint(Canvas canvas, Size size) {
  750. myPaint = Paint();
  751. myPaint!.color = lineColor;
  752. myPaint!.strokeWidth = lineWidth;
  753. canvas.drawLine(
  754. Offset(-2.px, topLeft), Offset(379.px * scale, topRight), myPaint!);
  755. }
  756. @override
  757. bool shouldRepaint(covariant CustomPainter oldDelegate) {
  758. // TODO: implement shouldRepaint
  759. return false;
  760. }
  761. }