all_view.dart 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. import 'package:clean/base/base_page.dart';
  2. import 'package:clean/module/contact/all/all_controller.dart';
  3. import 'package:clean/module/contact/contact_state.dart';
  4. import 'package:clean/resource/assets.gen.dart';
  5. import 'package:clean/utils/expand.dart';
  6. import 'package:flutter/Material.dart';
  7. import 'package:flutter_contacts/flutter_contacts.dart';
  8. import 'package:flutter_screenutil/flutter_screenutil.dart';
  9. import 'package:get/get.dart';
  10. import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
  11. class AllPage extends BasePage<AllController> {
  12. const AllPage({super.key});
  13. @override
  14. bool immersive() {
  15. return true;
  16. }
  17. @override
  18. bool statusBarDarkFont() => false;
  19. @override
  20. Widget buildBody(BuildContext context) {
  21. return Stack(
  22. children: [
  23. buildMain(context),
  24. IgnorePointer(
  25. child: Assets.images.bgHome.image(
  26. width: 360.w,
  27. ),
  28. ),
  29. ],
  30. );
  31. }
  32. Widget buildMain(BuildContext context) {
  33. return SafeArea(
  34. child: Container(
  35. padding: EdgeInsets.only(left: 16.w, top: 14.h, right: 16.w),
  36. child: Obx(() {
  37. return Column(
  38. mainAxisAlignment: MainAxisAlignment.start,
  39. crossAxisAlignment: CrossAxisAlignment.start,
  40. children: [
  41. !controller.isEdit.value
  42. ? Row(
  43. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  44. children: [
  45. GestureDetector(
  46. onTap: () {
  47. Get.back();
  48. },
  49. child: Assets.images.iconCommonBack
  50. .image(width: 28.w, height: 28.w),
  51. ),
  52. GestureDetector(
  53. onTap: () {
  54. controller.isEdit.value = true;
  55. },
  56. child: Container(
  57. width: 71.w,
  58. height: 30.h,
  59. decoration: BoxDecoration(
  60. color: "#1F2D3F".color,
  61. borderRadius: BorderRadius.all(
  62. Radius.circular(15.h),
  63. ),
  64. ),
  65. child: Center(
  66. child: Text(
  67. "Select",
  68. style: TextStyle(
  69. color: Colors.white,
  70. fontSize: 14.sp,
  71. ),
  72. ),
  73. ),
  74. ),
  75. ),
  76. ],
  77. )
  78. : Row(
  79. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  80. children: [
  81. GestureDetector(
  82. onTap: () {
  83. controller.isEdit.value = false;
  84. },
  85. child: Container(
  86. width: 71.w,
  87. height: 30.h,
  88. decoration: BoxDecoration(
  89. color: "#1F2D3F".color,
  90. borderRadius: BorderRadius.all(
  91. Radius.circular(15.h),
  92. ),
  93. ),
  94. child: Center(
  95. child: Text(
  96. "Cancel",
  97. style: TextStyle(
  98. color: Colors.white,
  99. fontSize: 14.sp,
  100. ),
  101. ),
  102. ),
  103. ),
  104. ),
  105. GestureDetector(
  106. onTap: () {
  107. controller.toggleSelectAll();
  108. },
  109. child: Text(
  110. controller.isAllSelected.value
  111. ? "Deselect all"
  112. : "Select All",
  113. style: TextStyle(
  114. color: Colors.white.withOpacity(0.65),
  115. fontSize: 14.sp,
  116. ),
  117. ),
  118. ),
  119. ],
  120. ),
  121. SizedBox(
  122. height: 12.h,
  123. ),
  124. Row(
  125. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  126. children: [
  127. Text(
  128. "All Contacts",
  129. style: TextStyle(
  130. color: Colors.white,
  131. fontWeight: FontWeight.w700,
  132. fontSize: 24.sp,
  133. ),
  134. ),
  135. ],
  136. ),
  137. Expanded(
  138. child: Row(
  139. children: [
  140. Expanded(
  141. child: Obx(() {
  142. return ScrollablePositionedList.builder(
  143. itemCount: ContactState.initials.length,
  144. itemScrollController: controller.itemScrollController,
  145. itemPositionsListener: controller
  146. .itemPositionsListener,
  147. itemBuilder: (context, index) {
  148. String initial = ContactState.initials[index];
  149. return Column(
  150. crossAxisAlignment: CrossAxisAlignment.start,
  151. children: [
  152. SizedBox(
  153. height: 12.h,
  154. ),
  155. Padding(
  156. padding: EdgeInsets.symmetric(vertical: 8.h),
  157. child: Text(
  158. initial,
  159. style: TextStyle(
  160. color: Colors.white.withOpacity(0.7),
  161. fontSize: 14.sp,
  162. fontWeight: FontWeight.w500,
  163. ),
  164. ),
  165. ),
  166. ...ContactState.groupedContacts[initial]!
  167. .asMap()
  168. .entries
  169. .map((entry) {
  170. int index = entry.key; // 当前联系人的索引
  171. Contact contact = entry.value; // 当前联系人
  172. bool isFirst = index == 0; // 是否是第一个
  173. bool isLast = index ==
  174. (ContactState.groupedContacts[initial]
  175. ?.length ??
  176. 0) -
  177. 1; // 是否是最后一个
  178. return Container(
  179. padding: EdgeInsets.all(10.w),
  180. width: double.infinity,
  181. // height: 62.h,
  182. decoration: BoxDecoration(
  183. borderRadius: BorderRadius.vertical(
  184. top: isFirst
  185. ? Radius.circular(12)
  186. : Radius.zero, // 第一个设置上圆角
  187. bottom: isLast
  188. ? Radius.circular(12)
  189. : Radius.zero, // 最后一个设置下圆角
  190. ),
  191. color: Colors.white.withOpacity(0.12),
  192. ),
  193. child: Row(
  194. mainAxisAlignment:
  195. MainAxisAlignment.spaceBetween,
  196. children: [
  197. Column(
  198. mainAxisAlignment:
  199. MainAxisAlignment.start,
  200. crossAxisAlignment:
  201. CrossAxisAlignment.start,
  202. children: [
  203. Text(
  204. contact.displayName ?? '未命名',
  205. style: TextStyle(
  206. color: Colors.white,
  207. fontSize: 14.sp,
  208. fontWeight: FontWeight.w500,
  209. ),
  210. ),
  211. SizedBox(
  212. height: 5.h,
  213. ),
  214. Text(
  215. contact.phones.isEmpty
  216. ? 'No contact number'
  217. : contact.phones.first.number,
  218. style: TextStyle(
  219. color: Colors.white,
  220. fontSize: 14.sp,
  221. fontWeight: FontWeight.w500,
  222. ),
  223. ),
  224. ],
  225. ),
  226. // 删除按钮
  227. Visibility(
  228. visible: controller.isEdit.value,
  229. child: GestureDetector(
  230. onTap: () {
  231. controller.toggleSelectContact(
  232. contact);
  233. },
  234. child: Container(
  235. child: controller.selectedContacts
  236. .contains(contact.id)
  237. ? Center(
  238. child: Assets
  239. .images.iconSelected
  240. .image(
  241. width: 16.w,
  242. height: 16.h,
  243. ),
  244. )
  245. : Center(
  246. child: Assets
  247. .images.iconUnselected
  248. .image(
  249. width: 16.w,
  250. height: 16.h,
  251. ),
  252. ),
  253. ),
  254. ),
  255. ),
  256. ],
  257. ),
  258. );
  259. }),
  260. SizedBox(
  261. height: 12.h,
  262. ),
  263. ],
  264. );
  265. },
  266. );
  267. }),
  268. ),
  269. Container(
  270. width: 30,
  271. child: ListView.builder(
  272. // physics: NeverScrollableScrollPhysics(),
  273. itemCount: ContactState.initials.length,
  274. itemBuilder: (context, index) {
  275. return GestureDetector(
  276. onTap: () =>
  277. controller
  278. .scrollToInitial(
  279. ContactState.initials[index]),
  280. child: Padding(
  281. padding: EdgeInsets.symmetric(vertical: 2),
  282. child: Text(
  283. ContactState.initials[index],
  284. textAlign: TextAlign.center,
  285. style: TextStyle(
  286. fontSize: 14,
  287. color: "#0279FB".color,
  288. fontWeight: FontWeight.bold,
  289. ),
  290. ),
  291. ),
  292. );
  293. },
  294. ),
  295. ),
  296. ],
  297. ),
  298. ),
  299. Visibility(
  300. visible: controller.isEdit.value,
  301. child: GestureDetector(
  302. onTap: () {
  303. controller.deleteBtnClick();
  304. },
  305. child: Container(
  306. width: 328.w,
  307. height: 48.h,
  308. decoration: BoxDecoration(
  309. color: "#0279FB".color,
  310. borderRadius: BorderRadius.all(
  311. Radius.circular(10.r),
  312. ),
  313. ),
  314. child: Center(
  315. child: Row(
  316. mainAxisAlignment: MainAxisAlignment.center,
  317. children: [
  318. Text(
  319. "Delete",
  320. style: TextStyle(
  321. color: Colors.white,
  322. fontSize: 16.sp,
  323. fontWeight: FontWeight.w500,
  324. ),
  325. ),
  326. ],
  327. ),
  328. ),
  329. ),
  330. ),
  331. )
  332. ],
  333. );
  334. }),
  335. ),
  336. );
  337. }
  338. }