YSLive.dart 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. import 'package:flutter/cupertino.dart';
  2. import 'package:flutter/material.dart';
  3. import 'package:flutter/services.dart';
  4. import 'package:flutterappfuyou/code/base/YSNetWorking.dart';
  5. import 'package:flutterappfuyou/code/base/YSTools.dart';
  6. import 'package:flutterappfuyou/code/live/YSLiveAdd.dart';
  7. import 'package:flutterappfuyou/code/live/YSLiveDetail.dart';
  8. import 'package:flutterappfuyou/code/live/YSVideoDetail.dart';
  9. class YSLive extends StatefulWidget {
  10. const YSLive({Key key}) : super(key: key);
  11. @override
  12. _YSLiveState createState() => _YSLiveState();
  13. }
  14. class _YSLiveState extends State<YSLive> with SingleTickerProviderStateMixin{
  15. List _titleArray = [
  16. {'title':'视频','type':'1'},
  17. {'title':'培训','type':'2'}
  18. ];
  19. TabController _tabController;
  20. bool _isChange = false;
  21. @override
  22. void initState() {
  23. _tabController = TabController(
  24. vsync: this,
  25. length: _titleArray.length
  26. );
  27. super.initState();
  28. }
  29. @override
  30. Widget build(BuildContext context) {
  31. return AnnotatedRegion<SystemUiOverlayStyle>(
  32. value: SystemUiOverlayStyle.dark,
  33. child: Scaffold(
  34. backgroundColor: Color(0xFFFAF8F5),
  35. body: Container(
  36. width: MediaQuery.of(context).size.width,
  37. child: SingleChildScrollView(
  38. child: Column(
  39. children: [
  40. Container(
  41. height: MediaQuery.of(context).padding.top+50,
  42. color: Colors.white,
  43. padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top),
  44. child: Row(
  45. children: [
  46. Container(
  47. width: MediaQuery.of(context).size.width-100,
  48. height: 50,
  49. alignment: Alignment.center,
  50. child: Text('视频培训',style: TextStyle(fontSize: 20,color: Colors.black),),
  51. margin: EdgeInsets.only(left: 50),
  52. ),
  53. Container(
  54. width: 50,
  55. // child: PopupMenuButton<String>(
  56. // icon: Icon(Icons.more_horiz),
  57. // onSelected: (value){
  58. // if(value=='1'){
  59. // Navigator.of(context,rootNavigator: true).push(
  60. // CupertinoPageRoute(builder: (context,){
  61. // return YSLiveAdd();
  62. // })
  63. // ).then((value) {
  64. // if(value!=null){
  65. // _isChange = !_isChange;
  66. // setState(() {});
  67. // }
  68. // });
  69. // }
  70. // },
  71. // itemBuilder: (context) {
  72. // return _moreArray.map((e) {
  73. // return PopupMenuItem<String>(
  74. // value: e['type'],
  75. // child: Text('${e['title']}',style: TextStyle(fontSize: 12),),
  76. // );
  77. // }).toList();
  78. // },
  79. // )
  80. )
  81. ],
  82. ),
  83. ),
  84. DefaultTabController(
  85. length: _titleArray.length,
  86. child: Column(
  87. children: [
  88. Container(
  89. height: 40,
  90. color: Colors.white,
  91. width: MediaQuery.of(context).size.width,
  92. child: TabBar(
  93. controller: _tabController,
  94. isScrollable: true,
  95. indicatorColor: Color(0xFFFA4444),
  96. labelColor: Color(0xFFFA4444),
  97. indicatorWeight: 2,
  98. indicatorSize: TabBarIndicatorSize.label,
  99. labelStyle: TextStyle(fontSize: 15),
  100. unselectedLabelColor: Color(0xFF5D6978),
  101. tabs: _titleArray.map((f) {
  102. return Tab(text: '${f['title']}');
  103. }).toList(),
  104. )
  105. ),
  106. Container(
  107. height: MediaQuery.of(context).size.height-MediaQuery.of(context).padding.top-140,
  108. width: MediaQuery.of(context).size.width,
  109. child: TabBarView(
  110. controller: _tabController,
  111. children: _titleArray.map((f) {
  112. return _isChange?Container(
  113. child: YSLiveView(f: f,callback: (){
  114. _isChange = !_isChange;
  115. setState(() {});
  116. },),
  117. ):YSLiveView(f: f,callback: (){
  118. _isChange = !_isChange;
  119. setState(() {});
  120. },);
  121. }).toList(),
  122. ),
  123. ),
  124. ],
  125. )
  126. )
  127. ],
  128. ),
  129. ),
  130. ),
  131. ),
  132. );
  133. }
  134. }
  135. class YSLiveView extends StatefulWidget {
  136. final Map f;
  137. final VoidCallback callback;
  138. const YSLiveView({Key key, this.f, this.callback}) : super(key: key);
  139. @override
  140. _YSLiveViewState createState() => _YSLiveViewState();
  141. }
  142. class _YSLiveViewState extends State<YSLiveView> {
  143. List _dataArray = [];
  144. TextEditingController _editingController = TextEditingController();
  145. @override
  146. void dispose() {
  147. _editingController.dispose();
  148. super.dispose();
  149. }
  150. @override
  151. Widget build(BuildContext context) {
  152. return YSRefreshLoad(
  153. url: widget.f['type']=='1'?'train/video/list':'train/live2/list',
  154. request: {},
  155. postData: (value){
  156. _dataArray = value;
  157. setState(() {});
  158. },
  159. dataWidget: SingleChildScrollView(
  160. child: GridView.builder(gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
  161. childAspectRatio: 0.8,
  162. crossAxisCount: 2,
  163. mainAxisSpacing: 10,
  164. crossAxisSpacing: 10
  165. ), itemBuilder: (context,index){
  166. Map item = _dataArray[index];
  167. return GestureDetector(
  168. onTap: () async{
  169. if(widget.f['type']=='2'&&item['have_password']==true){
  170. ysShowCenterAlertView(context, YSLivePassWordView(
  171. editingController: _editingController,
  172. callback: () async{
  173. Map request = {'live_id':item['id']};
  174. request['password'] = _editingController.text;
  175. Map dict = await ysRequestHttpNoLoading(context, requestType.get, 'train/live2/info', request);
  176. if(dict!=null){
  177. Navigator.of(context,rootNavigator: true).push(
  178. CupertinoPageRoute(builder: (context){
  179. return YSLiveDetail(liveId: item['id'],passWord: _editingController.text,);
  180. })
  181. ).then((value) {
  182. if(value!=null){
  183. widget.callback();
  184. }
  185. });
  186. }
  187. },
  188. ));
  189. }else{
  190. Navigator.of(context,rootNavigator: true).push(
  191. CupertinoPageRoute(builder: (context){
  192. return widget.f['type']=='1'?YSVideoDetail(videoId: item['id'],):YSLiveDetail(liveId: item['id']);
  193. })
  194. );
  195. }
  196. },
  197. behavior: HitTestBehavior.opaque,
  198. child: ClipRRect(
  199. borderRadius: BorderRadius.all(Radius.circular(5)),
  200. child: Container(
  201. color: Colors.white,
  202. child: LayoutBuilder(
  203. builder: (context,conSize){
  204. return widget.f['type']=='1'?Column(
  205. children: [
  206. Container(
  207. height: conSize.maxHeight*0.6,
  208. child: Stack(
  209. children: [
  210. Image.network(item['cover'],fit: BoxFit.cover,width: double.infinity,height: double.infinity,),
  211. if(item['is_recommend']==true)Image.asset('lib/images/tuijian.png',height: 40,width: 40,),
  212. ],
  213. )
  214. ),
  215. Container(
  216. height: conSize.maxHeight*0.25,
  217. decoration: BoxDecoration(
  218. border: Border(bottom: BorderSide(color: Colors.grey,width: 0.1))
  219. ),
  220. padding: EdgeInsets.only(left: 5,right: 5),
  221. child: RichText(
  222. text: TextSpan(
  223. style: TextStyle(fontSize: 12,color: Color(0xFF707070)),
  224. children: [
  225. // if(item['is_recommend']==true)WidgetSpan(child: Container(
  226. // padding: EdgeInsets.only(left: 5,right: 5,top: 2,bottom: 2),
  227. // decoration: BoxDecoration(
  228. // border: Border.all(color: Colors.red,width: 0.5),
  229. // color: Colors.red.withOpacity(0.3)
  230. // ),
  231. // child: Text('推荐',style: TextStyle(fontSize: 12,color: Colors.red),),
  232. // ),alignment: PlaceholderAlignment.middle),
  233. TextSpan(text: ' ${item['title']}')
  234. ]
  235. ),
  236. maxLines: 1,
  237. ),
  238. alignment: Alignment.centerLeft,
  239. ),
  240. Container(
  241. height: conSize.maxHeight*0.15,
  242. child: RichText(
  243. text: TextSpan(
  244. style: TextStyle(fontSize: 12,color: Color(0xFF707070)),
  245. children: [
  246. WidgetSpan(child: Icon(Icons.remove_red_eye_outlined,size: 15,color: Color(0xFF707070))),
  247. TextSpan(text: ' ${item['views']??'0'}')
  248. ]
  249. ),
  250. ),
  251. padding: EdgeInsets.only(left: 5,right: 5),
  252. alignment: Alignment.centerLeft,
  253. )
  254. ],
  255. ):Column(
  256. children: [
  257. Container(
  258. height: conSize.maxHeight*0.5,
  259. child: Image.network(item['cover'],fit: BoxFit.cover,height: double.infinity,width: double.infinity,),
  260. ),
  261. Container(
  262. height: conSize.maxHeight*0.15,
  263. child: RichText(
  264. text: TextSpan(
  265. style: TextStyle(fontSize: 12,color: Color(0xFF707070)),
  266. children: [
  267. // WidgetSpan(child: Container(
  268. // padding: EdgeInsets.only(left: 5,right: 5,top: 2,bottom: 2),
  269. // decoration: BoxDecoration(
  270. // border: Border.all(color: Colors.red,width: 0.5),
  271. // color: Colors.red.withOpacity(0.3)
  272. // ),
  273. // child: Text('培训中',style: TextStyle(fontSize: 12,color: Colors.red),),
  274. // )),
  275. TextSpan(text: ' ${item['title']}')
  276. ]
  277. ),
  278. maxLines: 1,
  279. ),
  280. padding: EdgeInsets.only(left: 5,right: 5,top: 10),
  281. alignment: Alignment.centerLeft,
  282. ),
  283. Container(
  284. height: conSize.maxHeight*0.15,
  285. child: RichText(
  286. text: TextSpan(
  287. style: TextStyle(fontSize: 12,color: Color(0xFF707070)),
  288. children: [
  289. WidgetSpan(child: Icon(Icons.person,size: 15,color: Color(0xFF707070))),
  290. TextSpan(text: ' ${item['watch_number']}')
  291. ]
  292. ),
  293. ),
  294. padding: EdgeInsets.only(left: 5,right: 5),
  295. alignment: Alignment.centerLeft,
  296. decoration: BoxDecoration(
  297. border: Border(bottom: BorderSide(color: Colors.grey,width: 0.2))
  298. ),
  299. ),
  300. Container(
  301. height: conSize.maxHeight*0.2,
  302. child: RichText(
  303. text: TextSpan(
  304. style: TextStyle(fontSize: 12,color: Color(0xFF707070)),
  305. children: [
  306. WidgetSpan(child: ClipRRect(
  307. child: Image.network(item['cast_avatar'],height: 15,width: 15,),
  308. borderRadius: BorderRadius.all(Radius.circular(50)),
  309. )),
  310. TextSpan(text: ' ${item['cast_name']}'),
  311. TextSpan(text: ' ${item['expect_start']??''}',style: TextStyle(color: Color(0xFFD3D3D3)))
  312. ]
  313. ),
  314. ),
  315. padding: EdgeInsets.only(left: 5,right: 5),
  316. alignment: Alignment.centerLeft,
  317. decoration: BoxDecoration(
  318. border: Border(bottom: BorderSide(color: Colors.grey,width: 0.2))
  319. ),
  320. )
  321. ],
  322. );
  323. },
  324. ),
  325. ),
  326. ),
  327. );
  328. },padding: EdgeInsets.all(10),itemCount: _dataArray.length,physics: NeverScrollableScrollPhysics(),shrinkWrap: true,),
  329. ),
  330. );
  331. }
  332. }
  333. class YSLivePassWordView extends StatelessWidget {
  334. final TextEditingController editingController;
  335. final VoidCallback callback;
  336. const YSLivePassWordView({Key key, this.editingController, this.callback}) : super(key: key);
  337. @override
  338. Widget build(BuildContext context) {
  339. return Center(
  340. child: ClipRRect(
  341. borderRadius: BorderRadius.all(Radius.circular(5)),
  342. child: Container(
  343. height: 200,
  344. width: MediaQuery.of(context).size.width-100,
  345. color: Colors.white,
  346. child: Column(
  347. children: [
  348. Container(
  349. height: 50,
  350. decoration: BoxDecoration(
  351. border: Border(bottom: BorderSide(color: Colors.black,width: 0.1))
  352. ),
  353. alignment: Alignment.center,
  354. child: Text('提示',style: TextStyle(fontSize: 14,color: Colors.black,decoration: TextDecoration.none),),
  355. ),
  356. Container(
  357. height: 100,
  358. padding: EdgeInsets.all(20),
  359. child: CupertinoTextField(
  360. padding: EdgeInsets.only(left: 20,right: 20),
  361. placeholder: '请输入房间密码',
  362. style: TextStyle(fontSize: 14,color: Colors.black,decoration: TextDecoration.none),
  363. textAlign: TextAlign.center,
  364. controller: editingController,
  365. maxLength: 10,
  366. ),
  367. ),
  368. Row(
  369. children: [
  370. GestureDetector(
  371. onTap: (){
  372. Navigator.pop(context);
  373. },
  374. behavior: HitTestBehavior.opaque,
  375. child: Container(
  376. width: (MediaQuery.of(context).size.width-100)/2,
  377. height: 50,
  378. decoration: BoxDecoration(
  379. border: Border(top: BorderSide(color: Colors.black,width: 0.1)),
  380. color: Colors.white,
  381. ),
  382. alignment: Alignment.center,
  383. child: Text('取消',style: TextStyle(fontSize: 14,color: Colors.grey,decoration: TextDecoration.none),),
  384. ),
  385. ),
  386. GestureDetector(
  387. onTap: (){
  388. Navigator.pop(context);
  389. if(editingController.text.isEmpty){
  390. ysFlutterToast(context, '请输入房间密码');
  391. return;
  392. }
  393. callback();
  394. },
  395. behavior: HitTestBehavior.opaque,
  396. child: Container(
  397. width: (MediaQuery.of(context).size.width-100)/2,
  398. height: 50,
  399. decoration: BoxDecoration(
  400. border: Border(top: BorderSide(color: Colors.black,width: 0.1)),
  401. color: Colors.blue,
  402. ),
  403. alignment: Alignment.center,
  404. child: Text('确定',style: TextStyle(fontSize: 14,color: Colors.white,decoration: TextDecoration.none),),
  405. ),
  406. )
  407. ],
  408. )
  409. ],
  410. ),
  411. ),
  412. ),
  413. );
  414. }
  415. }