Hibok
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。
 
 
 
 
 
 

383 行
13 KiB

  1. import 'package:cached_network_image/cached_network_image.dart';
  2. import 'package:chat/data/WebData.dart';
  3. import 'package:chat/data/constants.dart';
  4. import 'package:chat/generated/i18n.dart';
  5. import 'package:chat/home/ProfilePage.dart';
  6. import 'package:chat/utils/IconToggle.dart';
  7. import 'package:chat/utils/MessageMgr.dart';
  8. import 'package:chat/utils/UserChips.dart';
  9. import 'package:chat/utils/screen.dart';
  10. import 'package:flutter/material.dart';
  11. import 'package:oktoast/oktoast.dart';
  12. import '../utils/HttpUtil.dart';
  13. import 'package:dio/dio.dart';
  14. import "../data/UserData.dart";
  15. class UserCard extends StatelessWidget {
  16. final String userName;
  17. final bool isReal;
  18. final String city; //城市
  19. final int age; //年龄
  20. final String constellation; //星座
  21. final String professional; //职业
  22. final String isOnline;
  23. final double distance;
  24. final int userId;
  25. final bool isLove;
  26. final bool isBalck;
  27. final String headUrl;
  28. final bool payImg;
  29. final int imgNum;
  30. final int sex;
  31. final bool isHidden;
  32. final int member;
  33. final bool hiddenDistince;
  34. final int nameSize;
  35. UserCard(
  36. {Key key,
  37. this.userName,
  38. this.isReal: false,
  39. this.city,
  40. this.age,
  41. this.constellation,
  42. this.professional,
  43. this.isOnline,
  44. this.distance,
  45. this.userId,
  46. this.isLove: false,
  47. this.sex,
  48. this.headUrl: '',
  49. this.payImg: false,
  50. this.imgNum: 0,
  51. this.isHidden: false,
  52. this.member: 0,
  53. this.hiddenDistince: false,
  54. this.nameSize = 8,
  55. this.isBalck: false})
  56. : super(key: key);
  57. @override
  58. Widget build(BuildContext context) {
  59. bool isVIP = member > 0;
  60. bool isSVIP = member == 2;
  61. //头像
  62. Widget headImg() {
  63. double height = 69.4;
  64. return Stack(
  65. children: <Widget>[
  66. Container(
  67. height: height,
  68. width: height,
  69. child: ClipRRect(
  70. borderRadius: BorderRadius.circular(10),
  71. child: headUrl == '' || headUrl == null
  72. ? Image.asset(
  73. Constants.DefaultHeadImgUrl,
  74. )
  75. : CachedNetworkImage(
  76. imageUrl: headUrl,
  77. placeholder: (context, url) => Image.asset(
  78. Constants.DefaultHeadImgUrl,
  79. width: height,
  80. height: height,
  81. ),
  82. fit: BoxFit.cover,
  83. )),
  84. ),
  85. Positioned(
  86. left: 0,
  87. bottom: 0,
  88. child: Container(
  89. height: 15,
  90. width: 40,
  91. decoration: BoxDecoration(
  92. color: Colors.black54,
  93. borderRadius: BorderRadius.only(
  94. bottomLeft: Radius.circular(10),
  95. topRight: Radius.circular(10))),
  96. child: Row(
  97. //mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  98. children: <Widget>[
  99. Padding(
  100. padding: EdgeInsets.only(left: 6),
  101. child:
  102. Icon(Icons.image, size: 12, color: Colors.white)),
  103. Padding(
  104. padding: EdgeInsets.only(left: 5, top: 2),
  105. child: fixedText(imgNum.toString(),
  106. color: Colors.white, fontSize: 12),
  107. ),
  108. ],
  109. ),
  110. ))
  111. ],
  112. );
  113. }
  114. //名字以及认证状态
  115. Widget nameState() {
  116. return Row(
  117. children: <Widget>[
  118. fixedText(WebData().subUserName(userName, size: nameSize),
  119. fontSize: 15),
  120. isReal && sex == 2
  121. ? Container(
  122. margin: EdgeInsets.only(left: 5),
  123. padding:
  124. EdgeInsets.only(top: 2, bottom: 2, left: 5, right: 5),
  125. alignment: Alignment.center,
  126. decoration: BoxDecoration(
  127. borderRadius: BorderRadius.circular(10),
  128. color: Constants.PurpleBackgroundColor,
  129. ),
  130. child: fixedText('Real', fontSize: 8, color: Colors.white))
  131. : Container(),
  132. isVIP && sex == 1
  133. ? Container(
  134. margin: EdgeInsets.only(left: 5),
  135. child: isSVIP ? Constants.svipIcon : Constants.vipIcon)
  136. : Container(),
  137. ],
  138. );
  139. }
  140. //距离、在线以及相册
  141. Widget otherWidget() {
  142. var greyColor = const Color(0xFFB2B2B2);
  143. return Row(
  144. children: <Widget>[
  145. InfoTile(
  146. icon: IconData(0xe630, fontFamily: Constants.IconFontFamily),
  147. title: hiddenDistince
  148. ? I18n.of(context).secrecy
  149. : (UserData().hasLocationPermission
  150. ? WebData().getDistanceString(distance)
  151. : I18n.of(context).unknown),
  152. titleColor: greyColor,
  153. isDivider: true),
  154. InfoTile(
  155. title: isOnline,
  156. titleColor: greyColor,
  157. isDivider: payImg || isHidden),
  158. isHidden
  159. ? InfoTile(
  160. icon: IconData(0xe645, fontFamily: 'iconfont'),
  161. iconHeight: 22,
  162. title: I18n.of(context).application_view,
  163. titleColor: greyColor,
  164. isDivider: false,
  165. onTap: () {
  166. print('click');
  167. })
  168. : Container(),
  169. payImg
  170. ? InfoTile(
  171. icon: IconData(0xe632, fontFamily: Constants.IconFontFamily),
  172. title: I18n.of(context).paid_photo,
  173. titleColor: greyColor,
  174. isDivider: false,
  175. onTap: () {
  176. print('click');
  177. })
  178. : Container(),
  179. ],
  180. );
  181. }
  182. return InkWell(
  183. onTap: () {
  184. // if (sex == UserData().basicInfo.sex) {
  185. // showToast(UserData().basicInfo.sex == 1
  186. // ? I18n.of(context).cant_see
  187. // : I18n.of(context).cant_see2);
  188. // return;
  189. // }
  190. Navigator.of(context).push(
  191. new MaterialPageRoute(
  192. builder: (context) {
  193. return ProfilePage(
  194. userId: userId,
  195. );
  196. },
  197. ),
  198. );
  199. },
  200. child: Column(
  201. children: <Widget>[
  202. Container(
  203. //背景
  204. padding: EdgeInsets.only(left: 18, top: 14.5, bottom: 14.5),
  205. color: Colors.white,
  206. child: Stack(
  207. children: <Widget>[
  208. Row(
  209. children: <Widget>[
  210. //头像图片
  211. Padding(
  212. padding:
  213. EdgeInsets.only(right: 16.5, top: 5, bottom: 5),
  214. child: headImg()),
  215. //信息
  216. Container(
  217. width: MediaQuery.of(context).size.width - 104,
  218. child: Column(
  219. crossAxisAlignment: CrossAxisAlignment.start,
  220. mainAxisAlignment: MainAxisAlignment.end,
  221. children: <Widget>[
  222. nameState(), //名字以及状态
  223. //用户的信息标记
  224. Padding(padding: EdgeInsets.only(top: 9)),
  225. UserChips(
  226. city: city,
  227. age: age,
  228. constellation: constellation,
  229. professional: professional),
  230. Padding(padding: EdgeInsets.only(top: 4)),
  231. otherWidget(),
  232. ],
  233. )),
  234. ],
  235. ),
  236. Positioned(
  237. child: //赞
  238. sex == UserData().basicInfo.sex
  239. ? InkWell(
  240. onTap: () {
  241. showToast(UserData().isMan()
  242. ? I18n.of(context).not_love
  243. : I18n.of(context).not_love2);
  244. },
  245. child: Container(
  246. padding: EdgeInsets.only(
  247. left: 15, right: 15, bottom: 15),
  248. child: Icon(
  249. IconData(
  250. 0xe625,
  251. fontFamily: Constants.IconFontFamily,
  252. ),
  253. size: 15,
  254. color: Constants.GreyTextColor,
  255. )))
  256. : IconToggle(
  257. key: key,
  258. icon: IconData(
  259. 0xe625,
  260. fontFamily: Constants.IconFontFamily,
  261. ),
  262. activeIcon: IconData(
  263. 0xe623,
  264. fontFamily: Constants.IconFontFamily,
  265. ),
  266. defaultColor: Constants.GreyTextColor,
  267. activeColor: Constants.RedTextColor,
  268. isActive: isLove,
  269. size: 16,
  270. onTap: (bool isActive) async {
  271. if (isActive) {
  272. HttpUtil().setLove(userId, () {
  273. MessageMgr().emit('refresh_love_list',
  274. {'UserId': userId, 'flag': 0});
  275. });
  276. } else {
  277. HttpUtil().cancleLove(userId, () {
  278. MessageMgr().emit('refresh_love_list',
  279. {'UserId': userId, 'flag': 2});
  280. });
  281. }
  282. }),
  283. right: 0,
  284. top: 1,
  285. )
  286. ],
  287. )),
  288. Container(
  289. color: Colors.white,
  290. padding: EdgeInsets.only(
  291. left: Screen.width * 0.1, right: Screen.width * 0.1),
  292. child: Divider(
  293. height: 1,
  294. color: Constants.DividerLineColor,
  295. ),
  296. )
  297. ],
  298. ));
  299. }
  300. }
  301. const double TileHeight = 14;
  302. class InfoTile extends StatelessWidget {
  303. @required
  304. final String title;
  305. final Color titleColor;
  306. final IconData icon;
  307. final double iconHeight;
  308. final VoidCallback onTap;
  309. final bool isDivider;
  310. const InfoTile(
  311. {Key key,
  312. this.title,
  313. this.titleColor,
  314. this.icon,
  315. this.onTap,
  316. this.iconHeight: TileHeight,
  317. this.isDivider = false})
  318. : super(key: key);
  319. @override
  320. Widget build(BuildContext context) {
  321. List<Widget> elements = [];
  322. if (icon != null) {
  323. elements.add(Padding(
  324. padding: EdgeInsets.only(bottom: 2),
  325. child: Icon(icon, size: TileHeight, color: titleColor)));
  326. }
  327. elements.add(
  328. Container(
  329. alignment: Alignment.bottomCenter,
  330. constraints: BoxConstraints(minHeight: 17),
  331. padding: EdgeInsets.only(right: 5,bottom: 1.5),
  332. child: Text(title,
  333. textScaleFactor: 1.0,
  334. style: TextStyle(
  335. fontSize: 11,
  336. color: titleColor,
  337. fontWeight: FontWeight.normal))),
  338. );
  339. if (isDivider) {
  340. elements.add(Container(
  341. height: 16,
  342. child: VerticalDivider(
  343. width: 1,
  344. indent: 0,
  345. endIndent: 0,
  346. color: Colors.black26,
  347. )));
  348. }
  349. var tileWidget = Container(
  350. padding: EdgeInsets.only(right: 5),
  351. child: Row(
  352. //crossAxisAlignment: CrossAxisAlignment.start,
  353. children: elements,
  354. ));
  355. if (onTap != null) {
  356. return InkWell(
  357. child: tileWidget,
  358. onTap: onTap,
  359. );
  360. } else {
  361. return tileWidget;
  362. }
  363. }
  364. }