YSSquareVideo.dart 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532
  1. import 'package:flutter/cupertino.dart';
  2. import 'package:flutter/gestures.dart';
  3. import 'package:flutter/material.dart';
  4. import 'package:flutter_easyrefresh/easy_refresh.dart';
  5. import 'package:ysairplane/tools/YSNetWorking.dart';
  6. import 'package:ysairplane/tools/YSTools.dart';
  7. import 'package:video_player/video_player.dart';
  8. class YSSquareVideo extends StatefulWidget {
  9. final squareId,typeId;
  10. const YSSquareVideo({Key key, this.squareId, this.typeId}) : super(key: key);
  11. @override
  12. _YSSquareVideoState createState() => _YSSquareVideoState();
  13. }
  14. class _YSSquareVideoState extends State<YSSquareVideo> {
  15. VideoPlayerController _controller;
  16. bool _isPlaying = false;
  17. Map _dict;
  18. int page = 1;
  19. List comments = [];
  20. var ysState;
  21. @override
  22. void initState() {
  23. Future.delayed(Duration(seconds: 0)).then((value){
  24. _getSquareDetailData();
  25. });
  26. super.initState();
  27. }
  28. @override
  29. void dispose() {
  30. _controller.dispose();
  31. super.dispose();
  32. }
  33. @override
  34. Widget build(BuildContext context) {
  35. return CupertinoPageScaffold(
  36. child: SingleChildScrollView(
  37. child: Column(
  38. children: [
  39. Container(
  40. height: MediaQuery.of(context).size.height-50,
  41. width: MediaQuery.of(context).size.width,
  42. color: Color(0xFF1D1D1D),
  43. child: SingleChildScrollView(
  44. child: Column(
  45. crossAxisAlignment: CrossAxisAlignment.start,
  46. children: [
  47. Container(
  48. child: GestureDetector(
  49. child: Icon(Icons.arrow_back_ios,size: 20,color: Colors.white,),
  50. onTap: (){
  51. Navigator.pop(context);
  52. },
  53. ),
  54. margin: EdgeInsets.only(top: MediaQuery.of(context).padding.top+15,left: 15,bottom: 65),
  55. ),
  56. if (_controller==null) Container(
  57. height: 200,
  58. color: Colors.black12,
  59. ) else Container(
  60. height: 200,
  61. child: Stack(
  62. alignment: Alignment.bottomCenter,
  63. children: <Widget>[
  64. VideoPlayer(_controller),
  65. _PlayPauseOverlay(controller: _controller),
  66. Container(
  67. height:6.5,
  68. child: VideoProgressIndicator(
  69. _controller,
  70. allowScrubbing: true,
  71. colors: VideoProgressColors(playedColor: Color(0xFF1961E3),backgroundColor: Colors.white),
  72. )
  73. ),
  74. ],
  75. ),
  76. ),
  77. _dict==null?Container():Container(
  78. margin: EdgeInsets.only(top: 50),
  79. height: 60,
  80. padding: EdgeInsets.only(left: 15,right: 15,top: 10,bottom: 10),
  81. child: Row(
  82. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  83. children: [
  84. Container(
  85. height: 40,
  86. width: 40,
  87. decoration: BoxDecoration(
  88. borderRadius: BorderRadius.all(Radius.circular(20)),
  89. image: DecorationImage(image: NetworkImage('${_dict['user']['avatar']}'),fit: BoxFit.fill)
  90. ),
  91. margin: EdgeInsets.only(right: 6),
  92. ),
  93. Column(
  94. mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  95. children: [
  96. Container(
  97. width: MediaQuery.of(context).size.width-170,
  98. child: Text('${_dict['user']['nickname']}',style: TextStyle(fontSize: 14,color: Colors.white,decoration: TextDecoration.none),),
  99. ),
  100. Container(
  101. width: MediaQuery.of(context).size.width-170,
  102. child: Text('旅游达人',style: TextStyle(fontSize: 10,color: Colors.white,decoration: TextDecoration.none,fontWeight: FontWeight.normal),),
  103. )
  104. ],
  105. ),
  106. Container(
  107. height: 30,
  108. width: 65,
  109. child: Image.asset('lib/images/look.png',color: Colors.white,),
  110. ),
  111. ],
  112. ),
  113. ),
  114. _dict==null?Container():Container(
  115. width: MediaQuery.of(context).size.width,
  116. padding: EdgeInsets.only(top: 15,left: 10,right: 10,bottom: 15),
  117. child: Text('${_dict['videoTitle']}',style: TextStyle(fontSize: 17,color: Colors.white,decoration: TextDecoration.none),),
  118. ),
  119. _dict==null?Container():Container(
  120. width: MediaQuery.of(context).size.width,
  121. height: 100,
  122. padding: EdgeInsets.only(left: 10,right: 10,bottom: 15),
  123. child: SingleChildScrollView(
  124. child: Text('${_dict['videoContent']}',
  125. style: TextStyle(fontSize: 14,color: Colors.white,decoration: TextDecoration.none,fontWeight: FontWeight.normal),),
  126. ),
  127. ),
  128. ],
  129. ),
  130. ),
  131. ),
  132. Container(
  133. height: 50,
  134. padding: EdgeInsets.only(left: 15,right: 15),
  135. color: Color(0xFF000000),
  136. child: Row(
  137. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  138. children: [
  139. Container(
  140. width: MediaQuery.of(context).size.width-120,
  141. padding: EdgeInsets.only(left: 15,right: 15),
  142. height: 30,
  143. decoration: BoxDecoration(
  144. color: Color(0xFF3B3B3B),
  145. borderRadius: BorderRadius.all(Radius.circular(15))
  146. ),
  147. child: Row(
  148. children: [
  149. GestureDetector(
  150. onTap: (){
  151. _createCommentView();
  152. },
  153. child: Container(
  154. width: MediaQuery.of(context).size.width-175,
  155. child: Text('我来说两句',style: TextStyle(fontSize: 14,color: Color(0xFF9A9A9A),decoration: TextDecoration.none,fontWeight: FontWeight.normal),),
  156. ),
  157. ),
  158. Icon(Icons.tag_faces,size: 25,color: Color(0xFFA1A1A2),),
  159. ],
  160. ),
  161. ),
  162. GestureDetector(
  163. onTap: (){
  164. _postAgreementData(1);
  165. },
  166. child: Container(
  167. height: 20,
  168. width: 20,
  169. child: Image.asset(_dict==null?'lib/images/love.png':_dict['likeStatus']==1?'lib/images/love2.png':'lib/images/love.png',color: Colors.white,),
  170. ),
  171. ),
  172. GestureDetector(
  173. child: Icon(_dict==null?Icons.star_border:_dict['collectStatus']==1?Icons.star:Icons.star_border,size: 20,color: Colors.white,),
  174. onTap: (){
  175. _postAgreementData(0);
  176. },
  177. ),
  178. Icon(Icons.share,size: 20,color: Colors.white,),
  179. ],
  180. ),
  181. )
  182. ],
  183. ),
  184. ),
  185. );
  186. }
  187. _createCommentView() async{
  188. page = 1;
  189. Map dict = await ysRequestHttp(context,type: requestType.get,api: '/app/piazza/SquareCommunity/comment/list',parameter: {'pageNo':page,'pageSize':10,'id':widget.squareId,'type':widget.typeId});
  190. if(dict!=null){
  191. comments = dict['data']['resultList'];
  192. showModalBottomSheet(
  193. backgroundColor: Colors.transparent,
  194. isScrollControlled: true,
  195. context: context,
  196. builder: (context){
  197. return StatefulBuilder(
  198. builder: (context,stateSub){
  199. ysState = stateSub;
  200. return Container(
  201. height: MediaQuery.of(context).size.height*0.6,
  202. color: Color(0xFF2A2628),
  203. child: Column(
  204. children: [
  205. Container(
  206. height: 40,
  207. padding: EdgeInsets.only(left: 15,right: 15),
  208. child: Row(
  209. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  210. children: [
  211. Container(),
  212. Text('335210条评论',style: TextStyle(fontSize: 14,color: Colors.white,decoration: TextDecoration.none),),
  213. Icon(Icons.close,size: 20,color: Colors.white,)
  214. ],
  215. ),
  216. ),
  217. Container(
  218. height: MediaQuery.of(context).size.height*0.6-90,
  219. child: EasyRefresh(
  220. onRefresh: _refreshData,
  221. onLoad: _loadMore,
  222. header: MaterialHeader(
  223. ),
  224. footer: BezierBounceFooter(
  225. backgroundColor: Colors.transparent,
  226. color: Colors.transparent,
  227. ),
  228. child: ListView.separated(
  229. padding: EdgeInsets.only(top: 15),
  230. shrinkWrap: true,
  231. itemBuilder: (context,index){
  232. return Container(
  233. child: Column(
  234. children: [
  235. Container(
  236. padding: EdgeInsets.only(left: 10,right: 10,bottom: 10),
  237. child: Row(
  238. crossAxisAlignment: CrossAxisAlignment.start,
  239. children: [
  240. Container(
  241. height: 40,
  242. width: 40,
  243. decoration: BoxDecoration(
  244. borderRadius: BorderRadius.all(Radius.circular(20)),
  245. image: DecorationImage(image: NetworkImage('${comments[index]['avatar']}'),fit: BoxFit.fill)
  246. ),
  247. ),
  248. Container(
  249. margin: EdgeInsets.only(left: 10),
  250. width: MediaQuery.of(context).size.width-70,
  251. child: Column(
  252. crossAxisAlignment: CrossAxisAlignment.start,
  253. children: [
  254. GestureDetector(
  255. child: Text('${comments[index]['nickname']}',style: TextStyle(fontSize: 14,color: Color(0xFF929293),decoration: TextDecoration.none,fontWeight: FontWeight.bold),),
  256. onTap: (){
  257. _showInputView(type: 1,toUserid: int.parse('${comments[index]['fromUserId']}'),
  258. fatherCommentId: int.parse('${comments[index]['id']}'),fromUserId: int.parse('${comments[index]['fromUserId']}'));
  259. },
  260. ),
  261. Text('${comments[index]['comment']}',style: TextStyle(fontSize: 15,color: Colors.white,decoration: TextDecoration.none,fontWeight: FontWeight.normal)),
  262. ],
  263. ),
  264. )
  265. ],
  266. ),
  267. ),
  268. Container(
  269. child: ListView.separated(
  270. itemBuilder: (context,indexSub){
  271. return Row(
  272. crossAxisAlignment: CrossAxisAlignment.start,
  273. children: [
  274. Container(
  275. height: 20,
  276. width: 20,
  277. decoration: BoxDecoration(
  278. borderRadius: BorderRadius.all(Radius.circular(20)),
  279. image: DecorationImage(image: NetworkImage('${comments[index]['dtSquareCommentsList'][indexSub]['avatar']}'),fit: BoxFit.fill)
  280. ),
  281. ),
  282. Container(
  283. margin: EdgeInsets.only(left: 10),
  284. width: MediaQuery.of(context).size.width-130,
  285. child: Column(
  286. crossAxisAlignment: CrossAxisAlignment.start,
  287. children: [
  288. GestureDetector(
  289. child: Text('${comments[index]['dtSquareCommentsList'][indexSub]['nickname']}',
  290. style: TextStyle(fontSize: 14,color: Color(0xFF929293),decoration: TextDecoration.none,fontWeight: FontWeight.bold),),
  291. onTap: (){
  292. _showInputView(type: 1,toUserid: comments[index]['dtSquareCommentsList'][indexSub]['toUserId'],
  293. fatherCommentId: comments[index]['dtSquareCommentsList'][indexSub]['fatherCommentId'],fromUserId: comments[index]['dtSquareCommentsList'][indexSub]['fromUserId']);
  294. },
  295. ),
  296. RichText(
  297. text: TextSpan(
  298. style: TextStyle(fontSize: 14,color: Colors.white,decoration: TextDecoration.none,fontWeight: FontWeight.normal),
  299. text: '回复',
  300. children: [
  301. TextSpan(
  302. text: ' ${comments[index]['dtSquareCommentsList'][indexSub]['otherNickname']}:',
  303. style: TextStyle(color: Color(0xFF929293),fontWeight: FontWeight.bold),
  304. recognizer: TapGestureRecognizer()..onTap = (){
  305. _showInputView(type: 1,toUserid: comments[index]['dtSquareCommentsList'][indexSub]['toUserId'],
  306. fatherCommentId: comments[index]['dtSquareCommentsList'][indexSub]['fatherCommentId'],fromUserId: comments[index]['dtSquareCommentsList'][indexSub]['fromUserId']);
  307. }
  308. ),
  309. TextSpan(
  310. text: '${comments[index]['dtSquareCommentsList'][indexSub]['comment']}',
  311. style: TextStyle(color: Colors.white)
  312. ),
  313. TextSpan(
  314. text: ' ${comments[index]['dtSquareCommentsList'][indexSub]['timeNode']}',
  315. style: TextStyle(color: Color(0xFF929293),fontSize: 12)
  316. )
  317. ]
  318. ),
  319. )
  320. ],
  321. ),
  322. )
  323. ],
  324. );
  325. },
  326. separatorBuilder: (context,index){
  327. return Container(
  328. height: 5,
  329. );
  330. },
  331. itemCount: (comments[index]['dtSquareCommentsList']).length,
  332. shrinkWrap: true,
  333. padding: EdgeInsets.only(left: 60,right: 40),
  334. physics: NeverScrollableScrollPhysics(),
  335. ),
  336. )
  337. ],
  338. ),
  339. );
  340. },
  341. separatorBuilder: (context,index){
  342. return Container(
  343. height: 5,
  344. );
  345. },
  346. itemCount: comments.length,
  347. ),
  348. ),
  349. ),
  350. Container(
  351. height: 50,
  352. padding: EdgeInsets.only(left: 15,right: 15),
  353. child: Row(
  354. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  355. children: [
  356. GestureDetector(
  357. child: Text('有爱评论,说点儿好听的~',style: TextStyle(fontSize: 15,color: Color(0xFF5A5A5A),decoration: TextDecoration.none,fontWeight: FontWeight.normal),),
  358. onTap: (){
  359. _showInputView(type: 0);
  360. }
  361. ),
  362. Icon(Icons.tag_faces,size: 25,color: Color(0xFFA1A1A2),),
  363. ],
  364. ),
  365. )
  366. ],
  367. ),
  368. );
  369. },
  370. );
  371. }
  372. );
  373. }
  374. }
  375. _showInputView({int type,int toUserid,int fatherCommentId,int fromUserId}){
  376. TextEditingController _text = TextEditingController();
  377. Navigator.push(context, PopRoute(child: BottomInputDialog(
  378. height: 140,
  379. inputView: Column(
  380. children: [
  381. Row(
  382. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  383. children: [
  384. Text('评论',style: TextStyle(fontSize: 15,color: Color(0xFF424242),decoration: TextDecoration.none,fontWeight: FontWeight.bold),),
  385. GestureDetector(
  386. child: Text('发布',style: TextStyle(fontSize: 15,color: Color(0xFF4187D9),decoration: TextDecoration.none,fontWeight: FontWeight.bold),),
  387. onTap: (){
  388. if(type==0){
  389. _postCommentData({'comment':_text.text,'squareId':widget.squareId,'fatherCommentId':0,'fromUserId':0});
  390. }else{
  391. _postCommentData({'comment':_text.text,'squareId':widget.squareId,'fatherCommentId':fatherCommentId,'toUserId':toUserid,'fromUserId':fromUserId});
  392. }
  393. },
  394. ),
  395. ],
  396. ),
  397. Container(
  398. height: 50,
  399. decoration: BoxDecoration(
  400. color: Color(0xFFF7F7F7),
  401. borderRadius: BorderRadius.all(Radius.circular(10))
  402. ),
  403. margin: EdgeInsets.only(top: 10,bottom: 10),
  404. child: CupertinoTextField(
  405. placeholder: '友善发言,理性讨论,阳光你我',
  406. style: TextStyle(fontSize: 14,color: Color(0xFF999999),decoration: TextDecoration.none,fontWeight: FontWeight.normal),
  407. placeholderStyle: TextStyle(fontSize: 14,color: Color(0xFF999999),decoration: TextDecoration.none,fontWeight: FontWeight.normal),
  408. decoration: BoxDecoration(),
  409. maxLines: 50,
  410. autofocus: true,
  411. controller: _text,
  412. ),
  413. ),
  414. Row(
  415. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  416. children: [
  417. Container(),
  418. Icon(Icons.tag_faces,size: 25,color: Color(0xFF5C5C5C),),
  419. ],
  420. )
  421. ],
  422. ),
  423. )));
  424. }
  425. Future<void> _refreshData() async{
  426. page = 1;
  427. Map dict = await ysRequestHttp(context,type: requestType.get,api: '/app/piazza/SquareCommunity/comment/list',parameter: {'pageNo':page,'pageSize':10,'id':widget.squareId,'type':widget.typeId});
  428. if(dict!=null){
  429. ysState(() {
  430. comments = dict['data']['resultList'];
  431. });
  432. }
  433. }
  434. Future<void> _loadMore() async{
  435. page++;
  436. Map dict = await ysRequestHttp(context,type: requestType.get,api: '/app/piazza/SquareCommunity/comment/list',parameter: {'pageNo':page,'pageSize':10,'id':widget.squareId,'type':widget.typeId});
  437. if(dict!=null){
  438. ysState(() {
  439. comments.addAll(dict['data']['resultList']);
  440. });
  441. }
  442. }
  443. _postCommentData(Map parma) async{
  444. Map dict = await ysRequestHttp(context,type: requestType.post,api: '/app/piazza/SquareCommunity/comment/add',parameter: parma,isLoading: false,isToken: true);
  445. if(dict!=null){
  446. FocusScope.of(context).requestFocus(FocusNode());
  447. _refreshData();
  448. }
  449. }
  450. Future<void> _getSquareDetailData() async{
  451. Map dict = await ysRequestHttp(context,type: requestType.get,api: '/app/piazza/SquareCommunity/details',parameter: {'id':widget.squareId,'type':widget.typeId},isLoading: true,isToken: true,refresh: (){
  452. _getSquareDetailData();
  453. });
  454. if(dict!=null){
  455. _controller = VideoPlayerController.network('${dict['data']['videoPath']}')
  456. // 播放状态
  457. ..addListener(() {
  458. final bool isPlaying = _controller.value.isPlaying;
  459. if (isPlaying != _isPlaying) {
  460. setState(() { _isPlaying = isPlaying; });
  461. }
  462. })
  463. // 在初始化完成后必须更新界面
  464. ..initialize().then((_) {
  465. _controller.setLooping(true);
  466. _controller.play();
  467. setState(() {});
  468. });
  469. setState(() {
  470. _dict = dict['data'];
  471. });
  472. }
  473. }
  474. _postAgreementData(int type) async{
  475. Map request = {'type':type};
  476. request['topicId'] = widget.squareId;
  477. Map dict = await ysRequestHttp(context,type: requestType.post,api: '/app/piazza/SquareCommunity/likeAndCollect',parameter: request,isLoading: false,isToken: true,refresh: (){
  478. });
  479. if(dict!=null){
  480. setState(() {
  481. if(type==1){
  482. _dict['likeStatus'] = dict['data'];
  483. }else{
  484. _dict['collectStatus'] = dict['data'];
  485. }
  486. });
  487. }
  488. }
  489. }
  490. class _PlayPauseOverlay extends StatelessWidget {
  491. const _PlayPauseOverlay({Key key, this.controller}) : super(key: key);
  492. final VideoPlayerController controller;
  493. @override
  494. Widget build(BuildContext context) {
  495. return Stack(
  496. children: <Widget>[
  497. AnimatedSwitcher(
  498. duration: Duration(milliseconds: 50),
  499. reverseDuration: Duration(milliseconds: 200),
  500. child: controller.value.isPlaying? SizedBox.shrink():Container(
  501. color: Colors.black26,
  502. child: Center(
  503. child: Icon(
  504. Icons.play_circle_filled,
  505. color: Colors.white,
  506. size: 50,
  507. ),
  508. ),
  509. ),
  510. ),
  511. GestureDetector(
  512. onTap: () {
  513. controller.value.isPlaying ? controller.pause() : controller.play();
  514. },
  515. ),
  516. ],
  517. );
  518. }
  519. }