Hibok
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

916 lines
41 KiB

  1. import 'dart:async';
  2. import 'dart:io';
  3. import 'dart:math';
  4. import 'package:chat/data/UserData.dart';
  5. import 'package:chat/data/WebData.dart';
  6. import 'package:chat/data/constants.dart';
  7. import 'package:chat/generated/i18n.dart';
  8. import 'package:chat/home/VipPage.dart';
  9. import 'package:chat/models/money_change.dart';
  10. import 'package:chat/utils/CustomUI.dart';
  11. import 'package:chat/utils/HttpUtil.dart';
  12. import 'package:chat/utils/MessageMgr.dart';
  13. import 'package:chat/utils/TokenMgr.dart';
  14. import 'package:chat/utils/flutter_windowmanager.dart';
  15. import 'package:chat/utils/screen.dart';
  16. import 'package:dio/dio.dart';
  17. import 'package:extended_image/extended_image.dart';
  18. import 'dart:ui' as ui;
  19. import 'package:flutter/material.dart';
  20. import 'package:flutter/rendering.dart';
  21. import 'package:oktoast/oktoast.dart';
  22. import 'package:provider/provider.dart';
  23. import 'ChargeMoney.dart';
  24. double initScale({Size imageSize, Size size, double initialScale}) {
  25. var n1 = imageSize.height / imageSize.width;
  26. var n2 = size.height / size.width;
  27. if (n1 > n2) {
  28. final FittedSizes fittedSizes =
  29. applyBoxFit(BoxFit.contain, imageSize, size);
  30. //final Size sourceSize = fittedSizes.source;
  31. Size destinationSize = fittedSizes.destination;
  32. return size.width / destinationSize.width;
  33. } else if (n1 / n2 < 1 / 4) {
  34. final FittedSizes fittedSizes =
  35. applyBoxFit(BoxFit.contain, imageSize, size);
  36. //final Size sourceSize = fittedSizes.source;
  37. Size destinationSize = fittedSizes.destination;
  38. return size.height / destinationSize.height;
  39. }
  40. return initialScale;
  41. }
  42. class PicSwiper extends StatefulWidget {
  43. final int id;
  44. final List<PicSwiperItem> pics;
  45. PicSwiper({this.id, this.pics});
  46. @override
  47. _PicSwiperState createState() => _PicSwiperState();
  48. }
  49. class _PicSwiperState extends State<PicSwiper>
  50. with SingleTickerProviderStateMixin {
  51. var rebuildIndex = StreamController<int>.broadcast();
  52. var rebuildSwiper = StreamController<bool>.broadcast();
  53. AnimationController _animationController;
  54. Animation<double> _animation;
  55. Function animationListener;
  56. // CancellationToken _cancelToken;
  57. // CancellationToken get cancelToken {
  58. // if (_cancelToken == null || _cancelToken.isCanceled)
  59. // _cancelToken = CancellationToken();
  60. //
  61. // return _cancelToken;
  62. // }
  63. List<double> doubleTapScales = <double>[1.0, 2.0];
  64. GlobalKey<ExtendedImageSlidePageState> slidePagekey =
  65. GlobalKey<ExtendedImageSlidePageState>();
  66. int currentIndex;
  67. bool _showSwiper = true;
  68. int _seconds = 0;
  69. bool isMyself = false;
  70. @override
  71. void initState() {
  72. setDisableScreenshots();
  73. for (int i = 0; i < widget.pics.length; i++) {
  74. if (widget.id == widget.pics[i].id) {
  75. currentIndex = i;
  76. break;
  77. }
  78. }
  79. isMyself = widget.pics[0].userId == UserData().basicInfo.userId;
  80. _animationController = AnimationController(
  81. duration: const Duration(milliseconds: 150), vsync: this);
  82. super.initState();
  83. }
  84. setDisableScreenshots() async {
  85. print('Platform.isAndroid ${Platform.isAndroid}');
  86. if (Platform.isAndroid) {
  87. await FlutterWindowManager.addFlags(FlutterWindowManager.FLAG_SECURE);
  88. }
  89. }
  90. clearFalgs() async {
  91. if (Platform.isAndroid) {
  92. await FlutterWindowManager.clearFlags(FlutterWindowManager.FLAG_SECURE);
  93. }
  94. }
  95. @override
  96. void dispose() {
  97. rebuildIndex.close();
  98. rebuildSwiper.close();
  99. _animationController?.dispose();
  100. clearGestureDetailsCache();
  101. clearFalgs();
  102. //cancelToken?.cancel();
  103. super.dispose();
  104. }
  105. void browsePhoto(id, userId, type, callback, {price = 0}) async {
  106. if (Provider.of<MoneyChangeProvider>(context).money < price) {
  107. CustomUI.buildOneConfirm(context, I18n.of(context).balance_insufficien,
  108. I18n.of(context).recharge, () {
  109. Navigator.of(context).pop();
  110. ChargeMoney.showChargeSheet(context, () {
  111. setState(() {});
  112. });
  113. });
  114. return;
  115. }
  116. var data = {
  117. "visitUserId": UserData().basicInfo.userId,
  118. "userId": userId,
  119. "pId": id,
  120. 'type': type,
  121. };
  122. data['sign'] = TokenMgr().getSign(data);
  123. data['price'] = price;
  124. Response res = await HttpUtil().post('user/browse/photo', data: data);
  125. Map resData = res.data;
  126. print(resData);
  127. if (resData['code'] == 0) {
  128. MessageMgr().emit('refresh_photo', id);
  129. callback();
  130. }
  131. }
  132. @override
  133. Widget build(BuildContext context) {
  134. var size = MediaQuery.of(context).size;
  135. bool isAgree = (widget.pics[currentIndex].type == PhotoType.destroy.index ||
  136. widget.pics[currentIndex].type == PhotoType.destroyMoney.index);
  137. var id = widget.pics[currentIndex].id;
  138. Widget result = Scaffold(
  139. // StreamBuilder(
  140. // builder: (BuildContext context, data) {},
  141. // initialData: true,
  142. // stream: rebuildSwiper.stream,
  143. // ),
  144. appBar: AppBar(
  145. backgroundColor: AppColors.NewAppbarBgColor,
  146. title: StreamBuilder<int>(
  147. builder: (BuildContext context, data) {
  148. return Text(
  149. '${data.data + 1} / ${widget.pics.length}',
  150. style: TextStyle(
  151. fontSize: 16, color: AppColors.NewAppbarTextColor),
  152. textScaleFactor: 1.0,
  153. );
  154. },
  155. initialData: currentIndex,
  156. stream: rebuildIndex.stream,
  157. ),
  158. leading: CustomUI.buildCustomLeading(context),
  159. centerTitle: true,
  160. elevation: 1,
  161. actions: <Widget>[
  162. isMyself
  163. ? InkWell(
  164. onTap: () {
  165. CustomUI.buildOneConfirm(
  166. context,
  167. I18n.of(context).sure_delete,
  168. I18n.of(context).determine, () {
  169. var id = widget.pics[currentIndex].id;
  170. HttpUtil().setPhote(context, id, 2, () {
  171. widget.pics.removeAt(currentIndex);
  172. MessageMgr().emit('refresh_photo', id);
  173. if (widget.pics.length == 0) {
  174. Navigator.of(context).pop();
  175. } else {
  176. setState(() {
  177. if (currentIndex != 0) currentIndex--;
  178. });
  179. }
  180. });
  181. Navigator.of(context).pop();
  182. });
  183. },
  184. child: Container(
  185. margin: EdgeInsets.only(right: 10),
  186. child: CircleAvatar(
  187. backgroundColor: Constants.GreyBackgroundColor,
  188. radius: 13.75,
  189. child: Icon(
  190. Icons.delete,
  191. color: Constants.BlackTextColor,
  192. size: 20,
  193. ))),
  194. )
  195. : Container()
  196. ],
  197. ),
  198. backgroundColor: Colors.black,
  199. /// if you use ExtendedImageSlidePage and slideType =SlideType.onlyImage,
  200. /// make sure your page is transparent background
  201. // color: Colors.white,
  202. // shadowColor: Colors.transparent,
  203. bottomNavigationBar: isMyself
  204. ? Container(
  205. decoration: BoxDecoration(
  206. color: Colors.white,
  207. border: Border(top: Constants.GreyBorderSide)),
  208. height: 40,
  209. child: Row(
  210. mainAxisAlignment: MainAxisAlignment.start,
  211. children: <Widget>[
  212. Checkbox(
  213. value: isAgree,
  214. activeColor: Colors.blue,
  215. onChanged: (bool val) {
  216. if(widget.pics[currentIndex].isCheck){
  217. showToast(I18n.of(context).reviewing);
  218. return;
  219. }
  220. HttpUtil().setPhote(context, id, isAgree ? 0 : 1, () {
  221. this.setState(() {
  222. isAgree = !isAgree;
  223. //如果是红包照片焚阅照片则变成红包照片
  224. //如果是普通焚阅照片则变成普通照片
  225. MessageMgr().emit('refresh_photo');
  226. if (isAgree) {
  227. if (widget.pics[currentIndex].type ==
  228. PhotoType.free.index) {
  229. widget.pics[currentIndex].type =
  230. PhotoType.destroy.index;
  231. }
  232. if (widget.pics[currentIndex].type ==
  233. PhotoType.money.index) {
  234. widget.pics[currentIndex].type =
  235. PhotoType.destroyMoney.index;
  236. }
  237. } else {
  238. if (widget.pics[currentIndex].type ==
  239. PhotoType.destroy.index) {
  240. widget.pics[currentIndex].type =
  241. PhotoType.free.index;
  242. }
  243. if (widget.pics[currentIndex].type ==
  244. PhotoType.destroyMoney.index) {
  245. widget.pics[currentIndex].type =
  246. PhotoType.money.index;
  247. }
  248. }
  249. });
  250. });
  251. },
  252. ),
  253. fixedText(I18n.of(context).destroy_after)
  254. ],
  255. ),
  256. )
  257. : Container(
  258. height: 0,
  259. ),
  260. body: Stack(
  261. //fit: StackFit.expand,
  262. children: <Widget>[
  263. ExtendedImageGesturePageView.builder(
  264. itemBuilder: (BuildContext context, int index) {
  265. var item = widget.pics[index];
  266. var picUrl = item.picUrl;
  267. var file = item.file;
  268. var _timer;
  269. bool isShow = _seconds != 0;
  270. _cancelTimer() {
  271. item.isWatch = true;
  272. _seconds = 0;
  273. _timer?.cancel();
  274. }
  275. _startTimer() {
  276. if (UserData().isMan()) {
  277. _seconds =
  278. UserData().isSuperVip ? 6 : (UserData().isVip ? 4 : 2);
  279. } else {
  280. _seconds = UserData().basicInfo.isAttestation ? 6 : 2;
  281. }
  282. _timer =
  283. new Timer.periodic(new Duration(seconds: 1), (timer) {
  284. _seconds--;
  285. setState(() {});
  286. if (_seconds <= 0) {
  287. _cancelTimer();
  288. }
  289. });
  290. }
  291. Widget image;
  292. if (file != null) {
  293. image = ExtendedImage.file(
  294. file,
  295. fit: BoxFit.contain,
  296. //enableSlideOutPage: true,
  297. mode: ExtendedImageMode.gesture,
  298. initGestureConfigHandler: (state) {
  299. double initialScale = 1.0;
  300. if (state.extendedImageInfo != null &&
  301. state.extendedImageInfo.image != null) {
  302. initialScale = initScale(
  303. size: size,
  304. initialScale: initialScale,
  305. imageSize: Size(
  306. state.extendedImageInfo.image.width.toDouble(),
  307. state.extendedImageInfo.image.height
  308. .toDouble()));
  309. }
  310. return GestureConfig(
  311. inPageView: true,
  312. initialScale: initialScale,
  313. maxScale: max(initialScale, 5.0),
  314. initialAlignment: InitialAlignment.topCenter,
  315. animationMaxScale: max(initialScale, 5.0),
  316. //you can cache gesture state even though page view page change.
  317. //remember call clearGestureDetailsCache() method at the right time.(for example,this page dispose)
  318. cacheGesture: false);
  319. },
  320. onDoubleTap: (ExtendedImageGestureState state) {
  321. //you can use define pointerDownPosition as you can,
  322. //default value is double tap pointer down postion.
  323. var pointerDownPosition = state.pointerDownPosition;
  324. double begin = state.gestureDetails.totalScale;
  325. double end;
  326. //remove old
  327. _animation?.removeListener(animationListener);
  328. //stop pre
  329. _animationController.stop();
  330. //reset to use
  331. _animationController.reset();
  332. if (begin == doubleTapScales[0]) {
  333. end = doubleTapScales[1];
  334. } else {
  335. end = doubleTapScales[0];
  336. }
  337. animationListener = () {
  338. //print(_animation.value);
  339. state.handleDoubleTap(
  340. scale: _animation.value,
  341. doubleTapPosition: pointerDownPosition);
  342. };
  343. _animation = _animationController
  344. .drive(Tween<double>(begin: begin, end: end));
  345. _animation.addListener(animationListener);
  346. _animationController.forward();
  347. },
  348. );
  349. } else {
  350. image = ExtendedImage.network(
  351. picUrl,
  352. fit: BoxFit.contain,
  353. // enableSlideOutPage: true,
  354. mode: ExtendedImageMode.gesture,
  355. initGestureConfigHandler: (state) {
  356. double initialScale = 1.0;
  357. if (state.extendedImageInfo != null &&
  358. state.extendedImageInfo.image != null) {
  359. initialScale = initScale(
  360. size: size,
  361. initialScale: initialScale,
  362. imageSize: Size(
  363. state.extendedImageInfo.image.width.toDouble(),
  364. state.extendedImageInfo.image.height
  365. .toDouble()));
  366. }
  367. return GestureConfig(
  368. inPageView: true,
  369. initialScale: initialScale,
  370. maxScale: max(initialScale, 5.0),
  371. initialAlignment: InitialAlignment.topCenter,
  372. animationMaxScale: max(initialScale, 5.0),
  373. //you can cache gesture state even though page view page change.
  374. //remember call clearGestureDetailsCache() method at the right time.(for example,this page dispose)
  375. cacheGesture: false);
  376. },
  377. onDoubleTap: (ExtendedImageGestureState state) {
  378. //you can use define pointerDownPosition as you can,
  379. //default value is double tap pointer down postion.
  380. var pointerDownPosition = state.pointerDownPosition;
  381. double begin = state.gestureDetails.totalScale;
  382. double end;
  383. //remove old
  384. _animation?.removeListener(animationListener);
  385. //stop pre
  386. _animationController.stop();
  387. //reset to use
  388. _animationController.reset();
  389. if (begin == doubleTapScales[0]) {
  390. end = doubleTapScales[1];
  391. } else {
  392. end = doubleTapScales[0];
  393. }
  394. animationListener = () {
  395. //print(_animation.value);
  396. state.handleDoubleTap(
  397. scale: _animation.value,
  398. doubleTapPosition: pointerDownPosition);
  399. };
  400. _animation = _animationController
  401. .drive(Tween<double>(begin: begin, end: end));
  402. _animation.addListener(animationListener);
  403. _animationController.forward();
  404. },
  405. );
  406. }
  407. image = GestureDetector(
  408. child: Container(
  409. child: image,
  410. ),
  411. onTap: () {
  412. slidePagekey.currentState.popPage();
  413. Navigator.pop(context);
  414. },
  415. );
  416. //滤镜背景
  417. var bg = Center(
  418. child: ClipRect(
  419. //裁切长方形
  420. child: BackdropFilter(
  421. //背景滤镜器
  422. filter: ui.ImageFilter.blur(
  423. sigmaX: 20.0, sigmaY: 20.0), //图片模糊过滤,横向竖向都设置5.0
  424. child: Opacity(
  425. //透明控件
  426. opacity: 0.5,
  427. child: Container(
  428. alignment: Alignment.center,
  429. width: Screen.width,
  430. height: Screen.height,
  431. color: Colors.black,
  432. ),
  433. ),
  434. ),
  435. ),
  436. );
  437. //焚阅照片
  438. if ((item.type == PhotoType.destroy.index ||
  439. item.type == PhotoType.destroyMoney.index &&
  440. item.isBuy) &&
  441. item.userId != UserData().basicInfo.userId) {
  442. image = GestureDetector(
  443. onLongPress: item.isWatch
  444. ? null
  445. : () {
  446. browsePhoto(item.id, item.userId, 1, () {
  447. _startTimer();
  448. setState(() {});
  449. });
  450. },
  451. onLongPressEnd: item.isWatch
  452. ? null
  453. : (detail) {
  454. _cancelTimer();
  455. setState(() {});
  456. },
  457. onTap: () {
  458. slidePagekey.currentState.popPage();
  459. Navigator.pop(context);
  460. },
  461. child: Container(
  462. color: Colors.grey.shade200,
  463. child: Stack(
  464. alignment: Alignment.center,
  465. children: <Widget>[
  466. image,
  467. isShow
  468. ? Container()
  469. : Stack(
  470. alignment: Alignment.center,
  471. children: <Widget>[
  472. bg,
  473. item.isWatch
  474. ? Container(
  475. height: 211,
  476. width: 275.5,
  477. decoration: BoxDecoration(
  478. color: Colors.white,
  479. borderRadius:
  480. BorderRadius.all(
  481. Radius.circular(
  482. 5))),
  483. child: Column(
  484. mainAxisAlignment:
  485. MainAxisAlignment.center,
  486. children: <Widget>[
  487. Icon(
  488. IconData(
  489. 0xe634,
  490. fontFamily: 'iconfont',
  491. ),
  492. color: const Color(
  493. 0xFFA7A7A7),
  494. size: 50,
  495. ),
  496. fixedText(
  497. I18n.of(context)
  498. .destroyed,
  499. fontSize: 16,
  500. color: const Color(
  501. 0xFFA7A7A7)),
  502. UserData().isVip ||
  503. UserData()
  504. .basicInfo
  505. .sex ==
  506. 2
  507. ? Container()
  508. : fixedText(
  509. I18n.of(context)
  510. .longTime,
  511. color: Colors
  512. .grey[700],
  513. fontSize: 12),
  514. UserData().isVip ||
  515. UserData()
  516. .basicInfo
  517. .sex ==
  518. 2
  519. ? Container()
  520. : SizedBox(height: 10),
  521. UserData().isVip ||
  522. UserData()
  523. .basicInfo
  524. .sex ==
  525. 2
  526. ? Container()
  527. : RaisedButton(
  528. color: Colors.blue,
  529. onPressed: () {
  530. Navigator.of(
  531. context)
  532. .push(
  533. new MaterialPageRoute(
  534. builder:
  535. (context) {
  536. return VipPage();
  537. },
  538. ),
  539. );
  540. },
  541. child: fixedText(
  542. I18n.of(context)
  543. .joinvip,
  544. color: Colors
  545. .white),
  546. )
  547. ],
  548. ))
  549. : Container(
  550. height: 211,
  551. width: 275.5,
  552. decoration: BoxDecoration(
  553. color: Colors.white,
  554. borderRadius:
  555. BorderRadius.all(
  556. Radius.circular(
  557. 5))),
  558. child: Column(
  559. mainAxisAlignment:
  560. MainAxisAlignment.start,
  561. children: <Widget>[
  562. Padding(
  563. padding:
  564. EdgeInsets.only(
  565. top: 10,
  566. bottom: 2),
  567. child: Icon(
  568. IconData(
  569. 0xe634,
  570. fontFamily:
  571. 'iconfont',
  572. ),
  573. color: const Color(
  574. 0xFFF44236),
  575. size: 50,
  576. )),
  577. fixedText(
  578. I18n.of(context)
  579. .destroy_after,
  580. color: const Color(
  581. 0xFFF44236),
  582. fontSize: 15),
  583. Padding(
  584. padding: EdgeInsets.only(
  585. top: 25, bottom: 15),
  586. child: fixedText(
  587. I18n.of(context)
  588. .longClick,
  589. color: const Color(
  590. 0xFFFA8880),
  591. fontSize: 12),
  592. ),
  593. Image.asset(
  594. 'assets/images/zhiwen.png',
  595. height: 55,
  596. )
  597. ],
  598. ))
  599. ],
  600. )
  601. ],
  602. )));
  603. }
  604. //红包照片
  605. if ((item.type == PhotoType.money.index ||
  606. (item.type == PhotoType.destroyMoney.index &&
  607. !item.isBuy)) &&
  608. item.userId != UserData().basicInfo.userId) {
  609. image = GestureDetector(
  610. onTap: () {
  611. slidePagekey.currentState.popPage();
  612. Navigator.pop(context);
  613. },
  614. child: Container(
  615. color: Colors.grey.shade200,
  616. child: Stack(
  617. alignment: Alignment.center,
  618. children: <Widget>[
  619. image,
  620. item.isBuy
  621. ? Container()
  622. : Stack(
  623. alignment: Alignment.center,
  624. children: <Widget>[
  625. bg,
  626. Stack(
  627. alignment: Alignment.center,
  628. children: <Widget>[
  629. Image.asset(
  630. 'assets/images/login/money.png',
  631. fit: BoxFit.fitWidth,
  632. width: 220,
  633. ),
  634. Container(
  635. margin: EdgeInsets.only(top: 65),
  636. child: fixedText(
  637. I18n.of(context)
  638. .less_coin
  639. .replaceFirst(
  640. '/s1',
  641. UserData()
  642. .redPhotoPrice
  643. .toString()),
  644. color:
  645. const Color(0xFFFAE6B4),
  646. fontSize: 25),
  647. ),
  648. InkWell(
  649. onTap: () {
  650. CustomUI.buildOneConfirm(
  651. context,
  652. I18n.of(context)
  653. .pay_unlock
  654. .replaceFirst(
  655. '/s1',
  656. UserData()
  657. .redPhotoPrice
  658. .toString()),
  659. I18n.of(context)
  660. .confirm_pay, () {
  661. browsePhoto(
  662. item.id, item.userId, 2,
  663. () {
  664. setState(() {
  665. Navigator.of(context)
  666. .pop();
  667. MessageMgr().emit(
  668. 'refresh_photo',
  669. item.id);
  670. item.isBuy = true;
  671. });
  672. },
  673. price: UserData()
  674. .redPhotoPrice);
  675. });
  676. },
  677. child: Container(
  678. decoration: BoxDecoration(
  679. color: const Color(
  680. 0xFFFAE6B4),
  681. borderRadius:
  682. BorderRadius.all(
  683. Radius.circular(
  684. 30))),
  685. padding: EdgeInsets.only(
  686. left: 40,
  687. right: 40,
  688. top: 5,
  689. bottom: 5),
  690. margin:
  691. EdgeInsets.only(top: 140),
  692. child: fixedText(
  693. I18n.of(context)
  694. .determine,
  695. color: const Color(
  696. 0xFF7B0408)),
  697. ))
  698. ],
  699. )
  700. ],
  701. )
  702. ],
  703. )));
  704. }
  705. if (index == currentIndex) {
  706. return Hero(
  707. tag: picUrl + index.toString(),
  708. child: image,
  709. flightShuttleBuilder: (BuildContext flightContext,
  710. Animation<double> animation,
  711. HeroFlightDirection flightDirection,
  712. BuildContext fromHeroContext,
  713. BuildContext toHeroContext) {
  714. final Hero hero =
  715. flightDirection == HeroFlightDirection.pop
  716. ? fromHeroContext.widget
  717. : toHeroContext.widget;
  718. return hero.child;
  719. },
  720. );
  721. } else {
  722. return image;
  723. }
  724. },
  725. itemCount: widget.pics.length,
  726. onPageChanged: (int index) {
  727. currentIndex = index;
  728. rebuildIndex.add(index);
  729. },
  730. controller: PageController(
  731. initialPage: currentIndex,
  732. ),
  733. scrollDirection: Axis.horizontal,
  734. physics: BouncingScrollPhysics(),
  735. ),
  736. _seconds == 0
  737. ? Container()
  738. : Container(
  739. padding: EdgeInsets.only(bottom: 30),
  740. alignment: Alignment.bottomCenter,
  741. child: Stack(
  742. alignment: Alignment.center,
  743. children: <Widget>[
  744. CircularProgressIndicator(
  745. strokeWidth: 4.0,
  746. backgroundColor: Colors.grey,
  747. value: _seconds / 6,
  748. valueColor:
  749. new AlwaysStoppedAnimation<Color>(Colors.red),
  750. ),
  751. fixedText(_seconds.toString(), color: Colors.red)
  752. // Positioned(
  753. // top: 8,
  754. // left: 13,
  755. // child:
  756. // fixedText(_seconds.toString(), color: Colors.red),
  757. // )
  758. ],
  759. )),
  760. ],
  761. ));
  762. result = ExtendedImageSlidePage(
  763. key: slidePagekey,
  764. child: result,
  765. slideAxis: SlideAxis.both,
  766. slideType: SlideType.onlyImage,
  767. onSlidingPage: (state) {
  768. ///you can change other widgets' state on page as you want
  769. ///base on offset/isSliding etc
  770. //var offset= state.offset;
  771. var showSwiper = !state.isSliding;
  772. if (showSwiper != _showSwiper) {
  773. // do not setState directly here, the image state will change,
  774. // you should only notify the widgets which are needed to change
  775. // setState(() {
  776. // _showSwiper = showSwiper;
  777. // });
  778. _showSwiper = showSwiper;
  779. rebuildSwiper.add(_showSwiper);
  780. }
  781. },
  782. );
  783. return result;
  784. }
  785. }
  786. class MySwiperPlugin extends StatelessWidget {
  787. final List<PicSwiperItem> pics;
  788. final int index;
  789. final StreamController<int> reBuild;
  790. final bool isMyself;
  791. final callback;
  792. MySwiperPlugin(
  793. this.pics, this.index, this.reBuild, this.isMyself, this.callback);
  794. @override
  795. Widget build(BuildContext context) {
  796. return StreamBuilder<int>(
  797. builder: (BuildContext context, data) {
  798. return DefaultTextStyle(
  799. style: TextStyle(color: Colors.white),
  800. child: Container(
  801. //alignment: Alignment.center,
  802. height: 50.0,
  803. width: double.infinity,
  804. color: Colors.white,
  805. child: Row(
  806. children: <Widget>[
  807. InkWell(
  808. onTap: () {
  809. Navigator.of(context).pop();
  810. },
  811. child: Container(
  812. margin: EdgeInsets.only(left: 10),
  813. child: Icon(
  814. Icons.chevron_left,
  815. color: Constants.BlackTextColor,
  816. )),
  817. ),
  818. Expanded(
  819. child: Container(
  820. alignment: Alignment.center,
  821. child: fixedText("${data.data + 1} / ${pics.length}",
  822. color: Constants.BlackTextColor))),
  823. isMyself
  824. ? InkWell(
  825. onTap: () {
  826. CustomUI.buildOneConfirm(
  827. context,
  828. I18n.of(context).sure_delete,
  829. I18n.of(context).determine, () {
  830. callback(index);
  831. Navigator.of(context).pop();
  832. });
  833. },
  834. child: Container(
  835. margin: EdgeInsets.only(right: 10),
  836. child: Icon(
  837. Icons.delete,
  838. color: Constants.BlackTextColor,
  839. )),
  840. )
  841. : Container(),
  842. ],
  843. )),
  844. );
  845. },
  846. initialData: index,
  847. stream: reBuild.stream,
  848. );
  849. }
  850. }
  851. class PicSwiperItem {
  852. var userId;
  853. int id;
  854. String picUrl;
  855. String des;
  856. File file;
  857. int type;
  858. bool isBuy; //是否购买
  859. bool isWatch; //是否观看
  860. bool isCheck;//是否审核中
  861. PicSwiperItem(
  862. this.picUrl, {
  863. this.file,
  864. this.id,
  865. this.des = "",
  866. this.type = 0,
  867. this.isBuy = false,
  868. this.isWatch = false,
  869. this.userId,
  870. this.isCheck = false,
  871. });
  872. }