Hibok
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
 
 
 
 
 
 

1424 рядки
45 KiB

  1. import 'dart:io';
  2. import 'package:cached_network_image/cached_network_image.dart';
  3. import 'package:chat/chat/emoji_text.dart';
  4. import 'package:chat/chat/input_bar.dart';
  5. import 'package:chat/chat/my_special_text_span_builder.dart';
  6. import 'package:chat/data/UserData.dart';
  7. import 'package:chat/data/constants.dart';
  8. import 'package:chat/generated/i18n.dart';
  9. import 'package:chat/home/MyDialogContent.dart';
  10. import 'package:chat/home/SelectPage.dart';
  11. import 'package:chat/home/VerificationCenter.dart';
  12. import 'package:chat/home/VipPage.dart';
  13. import 'package:chat/models/money_change.dart';
  14. import 'package:chat/photo/entity/options.dart';
  15. import 'package:chat/photo/photo.dart';
  16. import 'package:chat/utils/ChargeMoney.dart';
  17. import 'package:chat/utils/CustomUI.dart';
  18. import 'package:chat/utils/HttpUtil.dart';
  19. import 'package:chat/utils/MessageMgr.dart';
  20. import 'package:chat/utils/PicSwiper.dart';
  21. import 'package:chat/utils/file_cache_mgr.dart';
  22. import 'package:chat/utils/keyboard/bottom_area_avoider.dart';
  23. import 'package:chat/utils/keyboard_utils.dart';
  24. import 'package:chat/utils/screen.dart';
  25. import 'package:dio/dio.dart';
  26. import 'package:extended_text_field/extended_text_field.dart';
  27. import 'package:flutter/material.dart';
  28. import 'package:flutter/services.dart';
  29. import 'package:flutter_screenutil/flutter_screenutil.dart';
  30. import 'package:multi_image_picker/multi_image_picker.dart';
  31. import 'package:oktoast/oktoast.dart';
  32. import 'package:photo_manager/photo_manager.dart';
  33. import 'package:provider/provider.dart';
  34. import 'package:shared_preferences/shared_preferences.dart';
  35. import '../utils/ShadowButton.dart';
  36. import '../data/UserData.dart';
  37. import '../utils/TokenMgr.dart';
  38. import '../data/WebData.dart';
  39. class AddProgram extends StatefulWidget {
  40. @required
  41. final bool isProgram;
  42. AddProgram({Key key, this.isProgram = true}) : super(key: key);
  43. _AddProgramState createState() => _AddProgramState();
  44. }
  45. const double LEFT_WIDTH = 80;
  46. const int Max_Img_Num = 4;
  47. class _AddProgramState extends State<AddProgram> {
  48. //期待对象
  49. String lovePeople = "";
  50. Set<String> lovePeopleId = new Set();
  51. //约会范围
  52. String dateRange = "";
  53. Set<String> dateRangeId = new Set();
  54. //开始时间
  55. String beginTime = '';
  56. String beginTimeId = '';
  57. //结束时间
  58. String endTime = '';
  59. var endTimeId = -1;
  60. //List<File> imgFileList = [];
  61. //上传图片地址
  62. List<String> imgUrlList = [];
  63. //禁止评论
  64. bool isCanContent = false;
  65. bool isHidden = false;
  66. int programId = -1;
  67. String programCat = '';
  68. // String content = '';
  69. @override
  70. void initState() {
  71. super.initState();
  72. print('AddProgram initState');
  73. _bloc.start();
  74. getKeyboardHeight();
  75. focusNode.addListener(_focusNodeListener);
  76. msgMgr.on('Keyboard Hide', dealWithKeyboardHide);
  77. }
  78. @override
  79. void dispose() {
  80. focusNode.removeListener(_focusNodeListener);
  81. _bloc.dispose();
  82. msgMgr.off('Keyboard Hide', dealWithKeyboardHide);
  83. super.dispose();
  84. }
  85. ///keyboard相关-----------------------------------------------------------------------------------------------
  86. KeyboardBloc _bloc = KeyboardBloc();
  87. MessageMgr msgMgr = MessageMgr();
  88. double keyboardHeight;
  89. final _keyParent = GlobalKey();
  90. double _offset = 0;
  91. Duration _timeToDismiss = Duration(milliseconds: 120);
  92. OverlayEntry _overlayEntry;
  93. FocusNode focusNode = new FocusNode();
  94. bool get _isShowing {
  95. return _overlayEntry != null;
  96. }
  97. bool isShowEmoji = false;
  98. bool _dismissAnimationNeeded = true;
  99. double _kBarSize = 45.0;
  100. bool isActionFromButton = false;
  101. dealWithKeyboardHide(args) {
  102. if (!isActionFromButton) {
  103. closeEmojiAction();
  104. }
  105. }
  106. TextEditingController _textCtrl = TextEditingController();
  107. final ValueNotifier<bool> _counter = ValueNotifier<bool>(false);
  108. void _insertOverlay() {
  109. print('插入界面');
  110. OverlayState os = Overlay.of(context);
  111. _overlayEntry = OverlayEntry(builder: (context) {
  112. // Update and build footer, if any
  113. final queryData = MediaQuery.of(context);
  114. return Positioned(
  115. bottom: queryData.viewInsets.bottom,
  116. left: 0,
  117. right: 0,
  118. child: SafeArea(
  119. child: Container(
  120. height: _kBarSize,
  121. child: Column(
  122. mainAxisSize: MainAxisSize.min,
  123. children: [
  124. Material(
  125. color: Colors.grey[200],
  126. child: Column(
  127. mainAxisSize: MainAxisSize.min,
  128. children: <Widget>[
  129. Divider(
  130. height: 1,
  131. color: Color(0xffb0b0b0),
  132. ),
  133. InkWell(
  134. child: Container(
  135. padding: EdgeInsets.only(left: 15),
  136. height: 43,
  137. color: Colors.white,
  138. alignment: Alignment.centerLeft,
  139. child: Icon(
  140. IconData(isShowEmoji ? 0xe655 : 0xe651,
  141. fontFamily: Constants.IconFontFamily),
  142. size: 27,
  143. color: Color(0xffb0b0b0)),
  144. ),
  145. onTap: () {
  146. setState(() {
  147. isActionFromButton = true;
  148. isShowEmoji = !isShowEmoji;
  149. _kBarSize = isShowEmoji ? keyboardHeight : 45;
  150. if (isShowEmoji) {
  151. SystemChannels.textInput
  152. .invokeMethod('TextInput.hide');
  153. } else {
  154. SystemChannels.textInput
  155. .invokeMethod('TextInput.show');
  156. }
  157. if (isShowEmoji) {
  158. Future.delayed(Duration(milliseconds: 200), () {
  159. ///150延迟防止界面越界
  160. _counter.value = isShowEmoji;
  161. });
  162. Future.delayed(Duration(milliseconds: 1000), () {
  163. ///缩下键盘的时候-防止表情被关闭
  164. isActionFromButton = false;
  165. });
  166. } else {
  167. _counter.value = isShowEmoji;
  168. Future.delayed(Duration(milliseconds: 360), () {
  169. ///150延迟防止界面越界
  170. isActionFromButton = false;
  171. });
  172. }
  173. });
  174. },
  175. ),
  176. ValueListenableBuilder(
  177. builder:
  178. (BuildContext context, bool value, Widget child) {
  179. return value
  180. ? Container(
  181. width: MediaQuery.of(context).size.width,
  182. child: buildEmojiGird(),
  183. )
  184. : SizedBox(
  185. height: 1,
  186. );
  187. },
  188. valueListenable: _counter,
  189. ),
  190. ],
  191. ),
  192. ),
  193. ],
  194. ),
  195. ),
  196. ),
  197. );
  198. });
  199. os.insert(_overlayEntry);
  200. }
  201. getKeyboardHeight() async {
  202. var sp = await SharedPreferences.getInstance();
  203. keyboardHeight = sp.getDouble(Constants.KeyboardHeight);
  204. print('keyboardHeight : $keyboardHeight');
  205. }
  206. Future<Null> _focusNodeListener() async {
  207. print('监听');
  208. if (isShowEmoji) {
  209. return;
  210. }
  211. _focusChanged(focusNode.hasFocus);
  212. }
  213. _focusChanged(bool showBar) {
  214. print('showBar $showBar _isShowing:$_isShowing');
  215. if (showBar && !_isShowing) {
  216. _insertOverlay();
  217. } else if (!showBar && _isShowing) {
  218. _removeOverlay();
  219. } else if (showBar && _isShowing) {
  220. _overlayEntry.markNeedsBuild();
  221. }
  222. }
  223. /// Remove the overlay bar. Call when losing focus or being dismissed.
  224. void _removeOverlay({bool fromDispose = false}) async {
  225. if (_dismissAnimationNeeded) {
  226. if (mounted && !fromDispose) {
  227. _overlayEntry?.markNeedsBuild();
  228. await Future.delayed(_timeToDismiss);
  229. }
  230. }
  231. _overlayEntry?.remove();
  232. _overlayEntry = null;
  233. if (!fromDispose && _dismissAnimationNeeded) _updateOffset();
  234. _dismissAnimationNeeded = true;
  235. }
  236. void _updateOffset() {
  237. if (!mounted) {
  238. return;
  239. }
  240. if (!_isShowing) {
  241. setState(() {
  242. _offset = 0.0;
  243. });
  244. return;
  245. }
  246. double newOffset = _kBarSize; // offset for the actions bar
  247. newOffset += MediaQuery.of(context)
  248. .viewInsets
  249. .bottom; // + offset for the system keyboard
  250. if (newOffset < 0) newOffset = 0;
  251. // Update state if changed
  252. if (_offset != newOffset) {
  253. setState(() {
  254. _offset = newOffset;
  255. });
  256. }
  257. }
  258. Widget buildEmojiGird() {
  259. return Container(
  260. height: keyboardHeight - 44,
  261. child: Stack(
  262. children: <Widget>[
  263. Padding(
  264. padding: EdgeInsets.fromLTRB(5, 8, 50, 0),
  265. child: GridView.builder(
  266. controller: new ScrollController(keepScrollOffset: false),
  267. gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
  268. crossAxisCount: 7, crossAxisSpacing: 0, mainAxisSpacing: 0),
  269. itemBuilder: (context, index) {
  270. return GestureDetector(
  271. child: Container(
  272. padding: EdgeInsets.all(7),
  273. child: Image.asset(EmojiUitl
  274. .instance.emojiMap[EmojiText.flag + "${index + 1}]"]),
  275. ),
  276. behavior: HitTestBehavior.translucent,
  277. onTap: () {
  278. if (_textCtrl.value.text.length < 94) {
  279. InputBarState.insertText(
  280. EmojiText.flag + "${index + 1}]", _textCtrl);
  281. }
  282. // setState(() {
  283. // _isComposingMessage = _textCtrl.text.length > 0;
  284. // });
  285. },
  286. );
  287. },
  288. itemCount: EmojiUitl.instance.emojiMap.length,
  289. padding: EdgeInsets.all(5.0),
  290. ),
  291. ),
  292. Positioned.fill(
  293. child: Container(
  294. padding: EdgeInsets.fromLTRB(0, 0, 0, 14),
  295. alignment: Alignment(1, 1),
  296. child: InkWell(
  297. onTap: () {
  298. InputBarState.deleteText(_textCtrl);
  299. },
  300. child: Container(
  301. decoration: BoxDecoration(
  302. color: Color(0x4d0E0E10),
  303. borderRadius: BorderRadius.only(
  304. topLeft: Radius.circular(4.0),
  305. bottomLeft: Radius.circular(4))),
  306. width: 37,
  307. height: 28,
  308. child: Icon(
  309. IconData(
  310. 0xe679,
  311. fontFamily: 'iconfont',
  312. ),
  313. size: 16,
  314. color: Colors.white,
  315. ),
  316. ),
  317. ),
  318. )),
  319. ],
  320. ),
  321. );
  322. }
  323. ///keyboard相关------------------------------------------------------------------------------------------------------------
  324. void closeEmojiAction() {
  325. print('### closeEmojiAction');
  326. FocusScope.of(context).requestFocus(FocusNode());
  327. isShowEmoji = false;
  328. _counter.value = isShowEmoji;
  329. _removeOverlay();
  330. _offset = 0;
  331. _kBarSize = isShowEmoji ? keyboardHeight : 45;
  332. }
  333. ScrollController _scrollController = new ScrollController();
  334. @override
  335. Widget build(BuildContext context) {
  336. Widget appBar = new AppBar(
  337. backgroundColor: AppColors.NewAppbarBgColor,
  338. title: Text(
  339. widget.isProgram
  340. ? I18n.of(context).release_program
  341. : I18n.of(context).release_dynamics,
  342. style: TextStyle(color: AppColors.NewAppbarTextColor),
  343. ),
  344. elevation: 0,
  345. leading: CustomUI.buildCustomLeading(context, onTap: () {
  346. closeEmojiAction();
  347. Navigator.of(context).pop();
  348. }),
  349. centerTitle: true,
  350. );
  351. return WillPopScope(
  352. child: Scaffold(
  353. appBar: appBar,
  354. body: SafeArea(
  355. child: Center(
  356. child: Container(
  357. height: MediaQuery.of(context).size.height,
  358. width: MediaQuery.of(context).size.width,
  359. child: GestureDetector(
  360. onTap: () {
  361. closeEmojiAction();
  362. },
  363. child: Material(
  364. color: Colors.transparent,
  365. child: SizedBox(
  366. width: double.maxFinite,
  367. key: _keyParent,
  368. child: BottomAreaAvoider(
  369. scrollTo: _scrollController,
  370. areaToAvoid: _offset,
  371. duration: Duration(
  372. milliseconds:
  373. (_timeToDismiss.inMilliseconds * 1.8).toInt()),
  374. autoScroll: true,
  375. child: Container(
  376. child: Column(
  377. children: <Widget>[_buildBody()],
  378. ),
  379. ),
  380. ),
  381. ),
  382. ),
  383. ),
  384. ),
  385. )),
  386. ),
  387. onWillPop: () {
  388. closeEmojiAction();
  389. return Future.value(true);
  390. });
  391. }
  392. // Future<bool> _willPop() {
  393. // print('###### willpop');
  394. //// tempDispose=true;
  395. //// closeEmojiAction();
  396. //// print('isshowemoji:$isShowEmoji');
  397. //// _counter.value = false;
  398. //// print('关闭emoji');
  399. //// FocusScope.of(context).requestFocus(FocusNode());
  400. // Navigator.pop(context);
  401. // return new Future.value(false);
  402. // }
  403. BoxDecoration _getCardDecoration() {
  404. return new BoxDecoration(
  405. color: Colors.white,
  406. boxShadow: [
  407. BoxShadow(
  408. color: Color.fromRGBO(230, 230, 230, 1),
  409. offset: Offset(0, 10),
  410. blurRadius: 8,
  411. )
  412. ],
  413. );
  414. }
  415. //节目主题
  416. Widget _buildProgramCat() {
  417. return new Container(
  418. margin: EdgeInsets.only(top: 15),
  419. decoration: _getCardDecoration(),
  420. child: _bottomBorderBox(
  421. I18n.of(context).program_theme,
  422. programCat == '' ? I18n.of(context).choose : programCat,
  423. false,
  424. null, () {
  425. CustomUI.buildTip(
  426. context, I18n.of(context).please_choose, _buildCategoryButton());
  427. }, rightTextGrey: programCat == ''),
  428. );
  429. }
  430. //选择期待对象
  431. void selectLovePeople() {
  432. var tempSet = lovePeopleId.toSet();
  433. List<Widget> actions = [
  434. FlatButton(
  435. child: fixedText(I18n.of(context).close),
  436. onPressed: () {
  437. tempSet.clear();
  438. Navigator.of(context).pop();
  439. },
  440. ),
  441. FlatButton(
  442. child: fixedText(I18n.of(context).determine),
  443. onPressed: () {
  444. Navigator.of(context).pop();
  445. setState(() {
  446. lovePeopleId = tempSet.toSet();
  447. lovePeople = '';
  448. lovePeopleId.forEach((k) {
  449. lovePeople += (lovePeople == '')
  450. ? WebData().loverPeopleMap[k]
  451. : ('/' + WebData().loverPeopleMap[k]);
  452. });
  453. });
  454. },
  455. ),
  456. ];
  457. //约会节目
  458. showDialog(
  459. context: context,
  460. builder: (BuildContext context) {
  461. return AlertDialog(
  462. title: new Align(
  463. alignment: Alignment.center,
  464. child: Text(I18n.of(context).expect_lover, textScaleFactor: 1.0),
  465. ),
  466. content: new MyDialogContent(
  467. mostNum: 4,
  468. dataMap: WebData().loverPeopleMap,
  469. keyList: tempSet,
  470. ),
  471. contentPadding: EdgeInsets.only(top: 10),
  472. actions: actions,
  473. );
  474. });
  475. }
  476. //选择约会地区
  477. void selectDateRange() async {
  478. Navigator.of(context).push(
  479. new MaterialPageRoute(
  480. builder: (context) {
  481. return SelectPage(
  482. mostNum: 4,
  483. dataId: dateRangeId,
  484. title: I18n.of(context).select_city,
  485. provinces: {'VietNam': WebData().provinces['VietNam']},
  486. cities: WebData().cities,
  487. isSingle: true,
  488. callback: (tempRankId) {
  489. dateRangeId = tempRankId.toSet();
  490. dateRange = '';
  491. dateRangeId.forEach((item) {
  492. var city = item.split('-');
  493. dateRange += dateRange == ''
  494. ? WebData().cities[city[0]][city[1]]
  495. : '/${WebData().cities[city[0]][city[1]]}';
  496. });
  497. Navigator.of(context).pop();
  498. },
  499. );
  500. },
  501. ),
  502. );
  503. }
  504. //选择开始时间
  505. void selectBegin() async {
  506. DateTime _date = DateTime.now();
  507. final DateTime picked = await showDatePicker(
  508. context: context,
  509. initialDate: _date,
  510. firstDate: DateTime(_date.year, _date.month, _date.day),
  511. locale: WebData().locale,
  512. lastDate: DateTime(_date.year, _date.month, _date.day + 7));
  513. setState(() {
  514. if (picked != null) {
  515. beginTime = '${picked.year}-${picked.month}-${picked.day}';
  516. beginTimeId = '${picked.year}-${picked.month}-${picked.day}';
  517. }
  518. });
  519. if (picked == null) _date = DateTime.now();
  520. }
  521. //分类按钮
  522. Widget _buildCategoryButton() {
  523. return Container(
  524. padding: EdgeInsets.only(top: 10),
  525. child: Column(
  526. children: <Widget>[
  527. Container(
  528. child: Row(
  529. mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  530. children: <Widget>[
  531. _buildIconButton(1, WebData().getProgramName(context, 0),
  532. Constants.Category1Color, 0),
  533. _buildIconButton(2, WebData().getProgramName(context, 1),
  534. Constants.Category2Color, 1),
  535. _buildIconButton(3, WebData().getProgramName(context, 2),
  536. Constants.Category3Color, 2),
  537. _buildIconButton(4, WebData().getProgramName(context, 3),
  538. Constants.Category4Color, 3),
  539. ],
  540. ),
  541. ),
  542. Container(
  543. child: Row(
  544. mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  545. children: <Widget>[
  546. _buildIconButton(5, WebData().getProgramName(context, 4),
  547. Constants.Category5Color, 4),
  548. _buildIconButton(6, WebData().getProgramName(context, 5),
  549. Constants.Category6Color, 5),
  550. _buildIconButton(7, WebData().getProgramName(context, 6),
  551. Constants.Category7Color, 6),
  552. _buildIconButton(8, WebData().getProgramName(context, 7),
  553. Constants.Category8Color, 7),
  554. ],
  555. ),
  556. ),
  557. ],
  558. ));
  559. }
  560. Widget _buildIconButton(iconNum, str, strColor, value) {
  561. Widget icon = Container(
  562. padding: EdgeInsets.only(bottom: 10),
  563. child: Image.asset(
  564. 'assets/images/park/qz_icon$iconNum.png',
  565. height: 60,
  566. ));
  567. Widget text = Positioned(
  568. bottom: 0,
  569. child: Container(
  570. child: new Text(str,
  571. textScaleFactor: 1.0,
  572. style: TextStyle(
  573. color: strColor, fontWeight: FontWeight.w700, fontSize: 13)),
  574. ));
  575. return InkWell(
  576. onTap: () {
  577. setState(() {
  578. programId = value;
  579. programCat = WebData().getProgramName(context, value);
  580. Navigator.of(context).pop();
  581. });
  582. },
  583. highlightColor: Colors.transparent,
  584. radius: 0,
  585. child: Container(
  586. width: (MediaQuery.of(context).size.width * 0.9) / 4,
  587. margin: EdgeInsets.only(top: 10),
  588. child: Stack(
  589. alignment: Alignment.center,
  590. children: <Widget>[
  591. icon,
  592. text,
  593. ],
  594. ),
  595. ));
  596. }
  597. Widget _buildTimeSelect(str, value) {
  598. return InkWell(
  599. child: Container(
  600. margin: EdgeInsets.only(top: 5, bottom: 5),
  601. height: 20,
  602. alignment: Alignment.center,
  603. child: Text(
  604. str,
  605. textScaleFactor: 1.0,
  606. style: TextStyle(fontSize: 15, color: Constants.BlackTextColor),
  607. ),
  608. ),
  609. onTap: () async {
  610. if (WebData().testTimeOver(value, beginTimeId)) {
  611. showToast(I18n.of(context).outTime);
  612. return;
  613. }
  614. setState(() {
  615. endTimeId = value;
  616. endTime = str;
  617. Navigator.of(context).pop();
  618. });
  619. },
  620. );
  621. }
  622. //选择结束时间
  623. void selectEnd() async {
  624. Widget title = Container(
  625. margin: EdgeInsets.only(top: 15, bottom: 10),
  626. alignment: Alignment.center,
  627. child: Text(
  628. I18n.of(context).select_time,
  629. textScaleFactor: 1.0,
  630. style: TextStyle(fontSize: 19, color: Constants.BlackTextColor),
  631. ),
  632. );
  633. List<Widget> list = [title];
  634. WebData().getDateTime(context).forEach((k, v) {
  635. list.add(Divider());
  636. list.add(_buildTimeSelect(v, k));
  637. });
  638. if (beginTimeId == '') {
  639. showToast(I18n.of(context).please_choose4);
  640. return;
  641. }
  642. showModalBottomSheet(
  643. context: context,
  644. builder: (BuildContext context) {
  645. return SafeArea(
  646. child: Container(
  647. height: 345,
  648. child: Column(children: list),
  649. ));
  650. },
  651. ).then((val) {});
  652. }
  653. void _sendPicture() async {
  654. closeEmojiAction();
  655. List<Asset> resultList = List<Asset>();
  656. resultList = await MultiImagePicker.pickImages(
  657. maxImages: Max_Img_Num - imgUrlList.length,
  658. enableCamera: false,
  659. selectedAssets: [],
  660. cupertinoOptions: CupertinoOptions(takePhotoIcon: "chat"),
  661. materialOptions: MaterialOptions(
  662. actionBarColor: "#50A7F9",
  663. actionBarTitle: "Hibok",
  664. allViewTitle: "",
  665. useDetailsView: false,
  666. selectCircleStrokeColor: "#000000",
  667. ),
  668. );
  669. if (resultList != null && resultList.length > 0) {
  670. List<File> fileList = [];
  671. for (var i = 0; i < resultList.length; i++) {
  672. Asset photoEntity = resultList[i];
  673. ByteData byteData = await photoEntity.getByteData();
  674. File file = await FileCacheMgr().writeFile('temp-photo-${DateTime.now().millisecondsSinceEpoch}-$i', byteData.buffer.asInt8List(0));
  675. fileList.add(file);
  676. }
  677. print('文件列表${fileList.length}');
  678. Map data = {"type": 3, "userId": UserData().basicInfo.userId};
  679. data['sign'] = TokenMgr().getSign(data);
  680. Response res = await HttpUtil().uploadFiles(
  681. fileList, data, 'upload/post/postfiles', 'image',
  682. isShowLoading: true);
  683. var resData = res.data;
  684. if (resData['code'] == 0 && resData['msg'] != null) {
  685. imgUrlList.addAll(resData['msg'].split("|"));
  686. setState(() {});
  687. }
  688. }
  689. // var photos = await PhotoPicker.pickAsset(
  690. // context: context,
  691. // themeColor: Color(0xFFF0F0F0),
  692. // maxSelected: Max_Img_Num - imgUrlList.length,
  693. // textColor: Color(0xFF3F3F3F),
  694. // pickType: PickType.onlyImage);
  695. //
  696. // if (photos != null && photos.length > 0) {
  697. // List<File> fileList = [];
  698. // for (var i = 0; i < photos.length; i++) {
  699. // AssetEntity photoEntity = photos[i];
  700. // fileList.add(await photoEntity.file);
  701. // }
  702. // Map data = {"type": 3, "userId": UserData().basicInfo.userId};
  703. // data['sign'] = TokenMgr().getSign(data);
  704. // Response res = await HttpUtil().uploadFiles(
  705. // fileList, data, 'upload/post/postfiles', 'image',
  706. // isShowLoading: true);
  707. // var resData = res.data;
  708. // if (resData['code'] == 0 && resData['msg'] != null) {
  709. // imgUrlList.addAll(resData['msg'].split("|"));
  710. // setState(() {});
  711. // }
  712. // }
  713. }
  714. Widget _buildDynicContent() {
  715. Widget moreInfo = Container(
  716. alignment: Alignment.topCenter,
  717. padding: EdgeInsets.only(left: 15, right: 15),
  718. child: ExtendedTextField(
  719. keyboardAppearance: Brightness.light,
  720. onTap: () {
  721. // if(!isActionFromButton){
  722. isShowEmoji = false;
  723. _counter.value = isShowEmoji;
  724. _kBarSize = isShowEmoji ? keyboardHeight : 45;
  725. // }
  726. },
  727. focusNode: focusNode,
  728. specialTextSpanBuilder:
  729. MySpecialTextSpanBuilder(showAtBackground: true, emojiSize: 17.0),
  730. decoration: new InputDecoration(
  731. hintText: I18n.of(context).please_civilization,
  732. hintStyle: TextStyle(fontSize: 13, height: 1.25),
  733. border: InputBorder.none,
  734. ),
  735. maxLines: 6,
  736. controller: _textCtrl,
  737. style: TextStyle(
  738. fontSize: ScreenUtil().setSp(14),
  739. textBaseline: TextBaseline.alphabetic),
  740. inputFormatters: [LengthLimitingTextInputFormatter(100)],
  741. onChanged: (str) {
  742. if (str.length > 100) {
  743. print('超过100了');
  744. _textCtrl.text = _textCtrl.value.text.substring(0, 100);
  745. int length = _textCtrl.text.length;
  746. Future.delayed(Duration(milliseconds: 100), () {
  747. _textCtrl.selection =
  748. TextSelection(baseOffset: length, extentOffset: length);
  749. });
  750. }
  751. },
  752. ));
  753. List<Widget> imgList = imgUrlList.map((f) {
  754. return _buildImg(f);
  755. }).toList();
  756. if (imgList.length < Max_Img_Num) {
  757. imgList.add(_buildUpButton());
  758. }
  759. Widget picture = Container(
  760. alignment: Alignment.centerLeft,
  761. padding: EdgeInsets.only(left: 15, bottom: 15),
  762. child: Wrap(alignment: WrapAlignment.start, children: imgList));
  763. List<Widget> list = [moreInfo, picture];
  764. return new Container(
  765. margin: EdgeInsets.only(top: 15),
  766. decoration: _getCardDecoration(),
  767. child: Column(
  768. children: list,
  769. ),
  770. );
  771. }
  772. Widget _buildUpButton() {
  773. var color = Colors.grey[350];
  774. return Container(
  775. child: InkWell(
  776. onTap: _sendPicture,
  777. child: Container(
  778. margin: EdgeInsets.only(left: 5, right: 5, top: 5, bottom: 5),
  779. decoration: BoxDecoration(
  780. borderRadius: BorderRadius.circular(10.0),
  781. border: Border.all(color: color)),
  782. width: 75,
  783. height: 75,
  784. child: ClipRRect(
  785. borderRadius: BorderRadius.circular(10),
  786. child: Icon(
  787. IconData(
  788. 0xe616,
  789. fontFamily: 'iconfont',
  790. ),
  791. color: color),
  792. ))));
  793. }
  794. //节目内容
  795. Widget _buildProgramContent() {
  796. Widget moreInfo = Container(
  797. child: Column(
  798. crossAxisAlignment: CrossAxisAlignment.start,
  799. mainAxisAlignment: MainAxisAlignment.start,
  800. children: <Widget>[
  801. Container(
  802. width: Screen.width,
  803. padding: EdgeInsets.only(
  804. top: 15,
  805. ),
  806. margin: EdgeInsets.only(left: 15),
  807. child: Text(
  808. I18n.of(context).describe_details,
  809. textScaleFactor: 1.0,
  810. style: TextStyle(fontSize: 14, fontWeight: FontWeight.w600),
  811. )),
  812. Container(
  813. padding: EdgeInsets.only(right: 5),
  814. margin: EdgeInsets.only(left: 15),
  815. child: ExtendedTextField(
  816. keyboardAppearance: Brightness.light,
  817. focusNode: focusNode,
  818. onTap: () {
  819. // if(!isActionFromButton){
  820. isShowEmoji = false;
  821. _counter.value = isShowEmoji;
  822. _kBarSize = isShowEmoji ? keyboardHeight : 45;
  823. // }
  824. if (_scrollController != null) {
  825. ///解决键盘遮挡输入框
  826. _scrollController.position.moveTo(
  827. 200,
  828. duration: Duration(milliseconds: 100),
  829. curve: Curves.easeIn,
  830. );
  831. }
  832. },
  833. controller: _textCtrl,
  834. specialTextSpanBuilder: MySpecialTextSpanBuilder(
  835. showAtBackground: true, emojiSize: 17.0),
  836. decoration: new InputDecoration(
  837. contentPadding:
  838. EdgeInsets.only(top: 6, bottom: 10, right: 10),
  839. hintText: I18n.of(context).please_civilization,
  840. hintStyle:
  841. TextStyle(fontSize: 12, height: 1.15),
  842. border: InputBorder.none,
  843. ),
  844. style: TextStyle(
  845. fontSize: 13, textBaseline: TextBaseline.alphabetic),
  846. maxLines: 6,
  847. // inputFormatters: [LengthLimitingTextInputFormatter(100)],
  848. onChanged: (str) {
  849. if (str.length > 100) {
  850. print('超过100了');
  851. _textCtrl.text = _textCtrl.value.text.substring(0, 100);
  852. int length = _textCtrl.text.length;
  853. Future.delayed(Duration(milliseconds: 100), () {
  854. _textCtrl.selection = TextSelection(
  855. baseOffset: length, extentOffset: length);
  856. });
  857. }
  858. },
  859. )),
  860. ],
  861. ),
  862. );
  863. List<Widget> imgList = imgUrlList.map((f) {
  864. return _buildImg(f);
  865. }).toList();
  866. if (imgList.length < Max_Img_Num) {
  867. imgList.add(_buildUpButton());
  868. }
  869. Widget picture = Container(
  870. alignment: Alignment.topCenter,
  871. child: Row(
  872. children: <Widget>[
  873. Container(
  874. alignment: Alignment.centerLeft,
  875. width: LEFT_WIDTH,
  876. margin: EdgeInsets.only(left: 15),
  877. child: fixedText(I18n.of(context).image,
  878. fontSize: 14, fontWeight: FontWeight.w600)),
  879. Expanded(
  880. child: Container(
  881. margin: EdgeInsets.only(top: 10, bottom: 10),
  882. child:
  883. Wrap(alignment: WrapAlignment.start, children: imgList))),
  884. ],
  885. ),
  886. );
  887. List<Widget> list = [
  888. _bottomBorderBox(
  889. I18n.of(context).expect_lover,
  890. lovePeople == '' ? I18n.of(context).choose : lovePeople,
  891. false,
  892. null,
  893. selectLovePeople,
  894. rightTextGrey: lovePeople == ''),
  895. _buildDivider(),
  896. // _bottomBorderBox(
  897. // I18n.of(context).city,
  898. // dateRange == '' ? I18n.of(context).choose : dateRange,
  899. // false,
  900. // null,
  901. // selectDateRange,
  902. // rightTextGrey: dateRange == ''),
  903. // _buildDivider(),
  904. _bottomBorderBox(
  905. I18n.of(context).time,
  906. beginTime == '' ? I18n.of(context).choose : beginTime,
  907. false,
  908. null,
  909. selectBegin,
  910. rightTextGrey: beginTime == ''),
  911. _buildDivider(),
  912. _bottomBorderBox('', endTime == '' ? I18n.of(context).choose : endTime,
  913. false, null, selectEnd,
  914. rightTextGrey: endTime == ''),
  915. _buildDivider(),
  916. moreInfo,
  917. _buildDivider(),
  918. picture
  919. ];
  920. return new Container(
  921. margin: EdgeInsets.only(top: 15),
  922. decoration: _getCardDecoration(),
  923. child: Column(
  924. children: list,
  925. ),
  926. );
  927. }
  928. //下划线
  929. Widget _buildDivider() {
  930. return new Container(
  931. margin: EdgeInsets.zero,
  932. padding: EdgeInsets.zero,
  933. decoration: BoxDecoration(border: Border(top: Constants.GreyBorderSide)),
  934. height: 1,
  935. width: MediaQuery.of(context).size.width * 0.9,
  936. );
  937. }
  938. Widget _buildImg(f) {
  939. return Stack(
  940. children: <Widget>[
  941. InkWell(
  942. onTap: () {
  943. Navigator.of(context).push(
  944. new MaterialPageRoute(
  945. builder: (context) {
  946. return PicSwiper(
  947. id: imgUrlList.indexOf(f),
  948. pics: imgUrlList
  949. .map((f) => PicSwiperItem(
  950. f,
  951. id: imgUrlList.indexOf(f),
  952. ))
  953. .toList(),
  954. );
  955. },
  956. ),
  957. );
  958. },
  959. child: Container(
  960. height: 75,
  961. width: 75,
  962. margin: EdgeInsets.only(left: 5, right: 5, top: 5, bottom: 5),
  963. decoration: BoxDecoration(
  964. borderRadius: BorderRadius.circular(10.0),
  965. border: Border.all(color: Colors.grey[300], width: 1),
  966. ),
  967. child: ClipRRect(
  968. borderRadius: BorderRadius.circular(10),
  969. child: f == null
  970. ? Container()
  971. : CachedNetworkImage(
  972. imageUrl: f,
  973. fit: BoxFit.cover,
  974. ),
  975. ))),
  976. Positioned(
  977. right: 0,
  978. child: InkWell(
  979. onTap: () {
  980. imgUrlList.remove(f);
  981. setState(() {});
  982. },
  983. child: Image.asset(
  984. 'assets/images/login/delete.png',
  985. height: 20,
  986. )),
  987. )
  988. ],
  989. );
  990. }
  991. //自定义item
  992. Widget _bottomBorderBox(
  993. String textLeft, String textRight, bool flag, controller, callback,
  994. {bool rightTextGrey = true}) {
  995. Widget left = new Container(
  996. width: LEFT_WIDTH,
  997. child: new Text(
  998. textLeft,
  999. textScaleFactor: 1.0,
  1000. style: TextStyle(fontSize: 14, fontWeight: FontWeight.w600),
  1001. ));
  1002. Widget right = flag
  1003. ? new Expanded(
  1004. child: new TextField(
  1005. keyboardAppearance: Brightness.light,
  1006. controller: controller,
  1007. decoration: new InputDecoration(
  1008. hintText: textRight,
  1009. hintStyle: TextStyle(fontSize: 14),
  1010. border: InputBorder.none,
  1011. ),
  1012. style: TextStyle(textBaseline: TextBaseline.alphabetic),
  1013. maxLines: 1,
  1014. onChanged: (str) {
  1015. if (flag && callback != null) callback(str);
  1016. },
  1017. ),
  1018. )
  1019. : new Expanded(
  1020. child: GestureDetector(
  1021. onTap: () {
  1022. if (!flag && callback != null) callback();
  1023. },
  1024. child: Container(
  1025. color: Colors.transparent,
  1026. height: 53,
  1027. width: MediaQuery.of(context).size.width,
  1028. alignment: Alignment.centerLeft,
  1029. padding: EdgeInsets.only(left: 5),
  1030. child: Text(
  1031. textRight,
  1032. textScaleFactor: 1.0,
  1033. style: TextStyle(
  1034. fontSize: 14,
  1035. color: rightTextGrey
  1036. ? Constants.GreyTextColor
  1037. : Constants.BlackTextColor),
  1038. ),
  1039. ),
  1040. ),
  1041. );
  1042. return new Container(
  1043. height: 53,
  1044. margin: EdgeInsets.only(left: 15, bottom: 0),
  1045. child: new Row(
  1046. children: <Widget>[left, right],
  1047. ),
  1048. );
  1049. }
  1050. Widget _buildSwitch(str, value, callback) {
  1051. Widget left = new Text(
  1052. str,
  1053. textScaleFactor: 1.0,
  1054. style: TextStyle(
  1055. fontSize: 14,
  1056. fontWeight: widget.isProgram ? FontWeight.w600 : FontWeight.normal),
  1057. );
  1058. Widget right = new Expanded(
  1059. child: new Align(
  1060. alignment: Alignment.centerRight,
  1061. child: new Switch(
  1062. activeTrackColor: Constants.ConfrimButtonColor.withOpacity(0.3),
  1063. value: value,
  1064. onChanged: (bool val) {
  1065. callback();
  1066. },
  1067. )));
  1068. return new Container(
  1069. padding: EdgeInsets.only(left: 15),
  1070. height: 53,
  1071. child: new Row(
  1072. children: <Widget>[left, right],
  1073. ),
  1074. );
  1075. }
  1076. Widget _buildSelct() {
  1077. return new Container(
  1078. decoration: _getCardDecoration(),
  1079. //margin: EdgeInsets.only(top: , bottom: 0),
  1080. child: Column(
  1081. children: <Widget>[
  1082. _buildSwitch(I18n.of(context).prohibit_comments, isCanContent, () {
  1083. setState(() {
  1084. isCanContent = !isCanContent;
  1085. });
  1086. }),
  1087. _buildDivider(),
  1088. _buildSwitch(I18n.of(context).same_sex, isHidden, () {
  1089. setState(() {
  1090. isHidden = !isHidden;
  1091. });
  1092. }),
  1093. ],
  1094. ));
  1095. }
  1096. Widget _buildTip() {
  1097. return Container(
  1098. alignment: Alignment.centerLeft,
  1099. margin: EdgeInsets.only(top: 10, bottom: 10, left: 10),
  1100. child: Text(
  1101. I18n.of(context).dont,
  1102. textScaleFactor: 1.0,
  1103. style: TextStyle(fontSize: 12, color: Constants.GreyTextColor),
  1104. ),
  1105. );
  1106. }
  1107. Widget _buildTips() {
  1108. String str = '';
  1109. if (UserData().isMan()) {
  1110. str = I18n.of(context)
  1111. .member_free
  1112. .replaceFirst('/s1', UserData().addProgramPrice.toString());
  1113. } else {
  1114. str = I18n.of(context)
  1115. .certified_free
  1116. .replaceFirst('/s1', UserData().addProgramPrice.toString());
  1117. }
  1118. return Container(
  1119. padding: EdgeInsets.only(bottom: 100, left: 20, right: 20),
  1120. child: Text(
  1121. str,
  1122. textScaleFactor: 1.0,
  1123. style: TextStyle(fontSize: 12, color: Constants.GreyTextColor),
  1124. ),
  1125. );
  1126. }
  1127. Widget _buildBody() {
  1128. List<Widget> program = [
  1129. _buildProgramCat(),
  1130. _buildProgramContent(),
  1131. _buildTip(),
  1132. _buildSelct(),
  1133. _buildLoginButton(),
  1134. _buildTips()
  1135. ];
  1136. List<Widget> dynamics = [
  1137. _buildDynicContent(),
  1138. _buildTip(),
  1139. _buildSelct(),
  1140. _buildLoginButton(),
  1141. _buildTips()
  1142. ];
  1143. return Column(
  1144. children: widget.isProgram ? program : dynamics,
  1145. );
  1146. }
  1147. //构建登陆按钮
  1148. Widget _buildLoginButton() {
  1149. Text text = new Text(I18n.of(context).release,
  1150. textScaleFactor: 1.0,
  1151. style: TextStyle(fontSize: 15, color: Colors.white));
  1152. LinearGradient gradientColor = new LinearGradient(colors: <Color>[
  1153. Constants.ConfrimButtonColor,
  1154. Constants.ConfrimButtonColor
  1155. ]);
  1156. callback() async {
  1157. closeEmojiAction();
  1158. if (widget.isProgram) {
  1159. if (programId == -1) {
  1160. showToast(I18n.of(context).please_choose);
  1161. return;
  1162. }
  1163. if (lovePeopleId.length == 0) {
  1164. showToast(I18n.of(context).please_choose2);
  1165. return;
  1166. }
  1167. // if (dateRangeId.length == 0) {
  1168. // showToast(I18n.of(context).please_choose3);
  1169. // return;
  1170. // }
  1171. if (beginTimeId == '') {
  1172. showToast(I18n.of(context).please_choose4);
  1173. return;
  1174. }
  1175. if (endTimeId == -1) {
  1176. showToast(I18n.of(context).please_choose5);
  1177. return;
  1178. }
  1179. } else {
  1180. if (_textCtrl.value.text.trim().length == 0 && imgUrlList.length == 0) {
  1181. showToast(I18n.of(context).enter_something);
  1182. return;
  1183. }
  1184. }
  1185. payCallback() {
  1186. if (Provider.of<MoneyChangeProvider>(context).money <
  1187. UserData().addProgramPrice) {
  1188. CustomUI.buildOneConfirm(
  1189. context,
  1190. I18n.of(context).balance_insufficien,
  1191. I18n.of(context).recharge, () {
  1192. Navigator.of(context).pop();
  1193. ChargeMoney.showChargeSheet(context, () {
  1194. setState(() {});
  1195. });
  1196. });
  1197. return;
  1198. }
  1199. Navigator.of(context).pop();
  1200. postAddProgram(UserData().addProgramPrice);
  1201. }
  1202. String title = widget.isProgram
  1203. ? I18n.of(context).release_program
  1204. : I18n.of(context).release_dynamics;
  1205. //非会员男士提示付费
  1206. if (!UserData().isVip && UserData().isMan()) {
  1207. bool isMan = UserData().isMan();
  1208. CustomUI.buildTowConfirm(
  1209. context,
  1210. title,
  1211. isMan
  1212. ? I18n.of(context).become_member2
  1213. : I18n.of(context).now_certification,
  1214. () {
  1215. Navigator.of(context).push(
  1216. new MaterialPageRoute(
  1217. builder: (context) {
  1218. return isMan ? VipPage() : VerificationCenterPage();
  1219. },
  1220. ),
  1221. );
  1222. },
  1223. I18n.of(context)
  1224. .raid_release
  1225. .replaceFirst('/s1', UserData().addProgramPrice.toString()),
  1226. payCallback,
  1227. );
  1228. return;
  1229. }
  1230. //免费次数用完提示付费
  1231. if (UserData().basicInfo.usedPublishNum >=
  1232. UserData().basicInfo.publishNum) {
  1233. CustomUI.buildOneConfirm(
  1234. context,
  1235. title,
  1236. I18n.of(context)
  1237. .pay_unlock
  1238. .replaceFirst('/s1', UserData().addProgramPrice.toString()),
  1239. payCallback);
  1240. return;
  1241. }
  1242. HttpUtil().userFreeTime(context, UserData().basicInfo.userId, 3, () {
  1243. UserData().basicInfo.usedPublishNum++;
  1244. postAddProgram(0);
  1245. });
  1246. }
  1247. return new Container(
  1248. margin: EdgeInsets.only(top: 30, bottom: 10),
  1249. height: 44,
  1250. width: MediaQuery.of(context).size.width * 0.8,
  1251. child: ShadowButton().builder(gradientColor, text, callback),
  1252. );
  1253. }
  1254. postAddProgram(price) async {
  1255. var dateRangeStr = '';
  1256. dateRangeId.forEach((f) => dateRangeStr += dateRangeStr == '' ? f : ',$f');
  1257. var hopeObject = '';
  1258. lovePeopleId.forEach((f) => hopeObject += hopeObject == '' ? f : ',$f');
  1259. String temp='';
  1260. String postTemp='';
  1261. imgUrlList.forEach((str) {
  1262. temp += (temp == "" ? str : '|$str');
  1263. postTemp += (postTemp == ""
  1264. ? WebData().deleteDemain(str)
  1265. : '|${WebData().deleteDemain(str)}');
  1266. });
  1267. var type = widget.isProgram ? 0 : 1;
  1268. Map data = {
  1269. "userId": UserData().basicInfo.userId,
  1270. "type": type,
  1271. "price": price,
  1272. };
  1273. data['sign'] = TokenMgr().getSign(data);
  1274. //data['city'] = dateRangeStr;
  1275. data['programType'] = programId;
  1276. data['hopeObject'] = hopeObject;
  1277. data['aboutTime'] = beginTimeId;
  1278. data['content'] = _textCtrl.text;
  1279. data['imgUrl'] = postTemp;
  1280. data['evaluateStatus'] = isCanContent;
  1281. data['sexStatus'] = isHidden;
  1282. data['timeQuantum'] = endTimeId;
  1283. Response res = await HttpUtil()
  1284. .post('station/publish/program', data: data, isShowLoading: true);
  1285. var resData = res.data;
  1286. if (resData['code'] == 0) {
  1287. if (widget.isProgram) {
  1288. UserData().isCanProgram = false;
  1289. }
  1290. MessageMgr().emit('Add_program', {
  1291. 'Id': resData['data'],
  1292. 'UserId': UserData().basicInfo.userId,
  1293. 'NickName': UserData().basicInfo.nickName,
  1294. 'HeadimgUrl': UserData().basicInfo.headimgurl,
  1295. 'Type': type,
  1296. 'Sex': UserData().basicInfo.sex,
  1297. 'IsMember': UserData().basicInfo.isMember,
  1298. 'ProgramType': programId,
  1299. 'HopeObject': hopeObject,
  1300. 'City': dateRangeStr,
  1301. 'AboutTime': beginTimeId,
  1302. 'timeQuantum': endTimeId,
  1303. 'Content': _textCtrl.text,
  1304. 'ImgUrl': temp,
  1305. 'EvaluateStatus': isCanContent ? 1 : 0,
  1306. 'SexStatus': isHidden,
  1307. 'Status': 0,
  1308. 'CreateTime': DateTime.now().toIso8601String(),
  1309. 'FabulousNum': 0,
  1310. 'EvaluateNum': 0,
  1311. 'EnrollNum': 0,
  1312. 'IsAttestation': UserData().basicInfo.isAttestation ? 1 : 0,
  1313. 'IsFabulous': 0,
  1314. 'IsEnroll': 0,
  1315. 'EvaluateList': null,
  1316. "FabulousList": []
  1317. });
  1318. Navigator.of(context).pop();
  1319. focusNode.removeListener(_focusNodeListener);
  1320. } else {
  1321. showToast(resData['msg']);
  1322. }
  1323. }
  1324. }