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. var groupedContacts =
  150. ContactState.groupedContacts[initial];
  151. return Column(
  152. crossAxisAlignment: CrossAxisAlignment.start,
  153. children: [
  154. SizedBox(
  155. height: 12.h,
  156. ),
  157. Padding(
  158. padding: EdgeInsets.symmetric(vertical: 8.h),
  159. child: Text(
  160. initial,
  161. style: TextStyle(
  162. color: Colors.white.withOpacity(0.7),
  163. fontSize: 14.sp,
  164. fontWeight: FontWeight.w500,
  165. ),
  166. ),
  167. ),
  168. ...ContactState.groupedContacts[initial]!
  169. .asMap()
  170. .entries
  171. .map((entry) {
  172. int index = entry.key; // 当前联系人的索引
  173. Contact contact = entry.value; // 当前联系人
  174. bool isFirst = index == 0; // 是否是第一个
  175. bool isLast = index ==
  176. (ContactState.groupedContacts[initial]
  177. ?.length ??
  178. 0) -
  179. 1; // 是否是最后一个
  180. return Container(
  181. padding: EdgeInsets.all(10.w),
  182. width: double.infinity,
  183. // height: 62.h,
  184. decoration: BoxDecoration(
  185. borderRadius: BorderRadius.vertical(
  186. top: isFirst
  187. ? Radius.circular(12)
  188. : Radius.zero, // 第一个设置上圆角
  189. bottom: isLast
  190. ? Radius.circular(12)
  191. : Radius.zero, // 最后一个设置下圆角
  192. ),
  193. color: Colors.white.withOpacity(0.12),
  194. ),
  195. child: Row(
  196. mainAxisAlignment:
  197. MainAxisAlignment.spaceBetween,
  198. children: [
  199. Column(
  200. mainAxisAlignment:
  201. MainAxisAlignment.start,
  202. crossAxisAlignment:
  203. CrossAxisAlignment.start,
  204. children: [
  205. Text(
  206. contact.displayName ?? '未命名',
  207. style: TextStyle(
  208. color: Colors.white,
  209. fontSize: 14.sp,
  210. fontWeight: FontWeight.w500,
  211. ),
  212. ),
  213. SizedBox(
  214. height: 5.h,
  215. ),
  216. Text(
  217. contact.phones.first.number ??
  218. '无号码',
  219. style: TextStyle(
  220. color: Colors.white,
  221. fontSize: 14.sp,
  222. fontWeight: FontWeight.w500,
  223. ),
  224. ),
  225. ],
  226. ),
  227. // 删除按钮
  228. Visibility(
  229. visible: controller.isEdit.value,
  230. child: GestureDetector(
  231. onTap: () {
  232. controller.toggleSelectContact(
  233. contact);
  234. },
  235. child: Container(
  236. child: controller.selectedContacts
  237. .contains(contact.id)
  238. ? Center(
  239. child: Assets
  240. .images.iconSelected
  241. .image(
  242. width: 16.w,
  243. height: 16.h,
  244. ),
  245. )
  246. : Center(
  247. child: Assets
  248. .images.iconUnselected
  249. .image(
  250. width: 16.w,
  251. height: 16.h,
  252. ),
  253. ),
  254. ),
  255. ),
  256. ),
  257. ],
  258. ),
  259. );
  260. }),
  261. SizedBox(
  262. height: 12.h,
  263. ),
  264. ],
  265. );
  266. },
  267. );
  268. }),
  269. ),
  270. Container(
  271. width: 30,
  272. child: ListView.builder(
  273. // physics: NeverScrollableScrollPhysics(),
  274. itemCount: ContactState.initials.length,
  275. itemBuilder: (context, index) {
  276. return GestureDetector(
  277. onTap: () =>
  278. controller
  279. .scrollToInitial(
  280. ContactState.initials[index]),
  281. child: Padding(
  282. padding: EdgeInsets.symmetric(vertical: 2),
  283. child: Text(
  284. ContactState.initials[index],
  285. textAlign: TextAlign.center,
  286. style: TextStyle(
  287. fontSize: 14,
  288. color: "#0279FB".color,
  289. fontWeight: FontWeight.bold,
  290. ),
  291. ),
  292. ),
  293. );
  294. },
  295. ),
  296. ),
  297. ],
  298. ),
  299. ),
  300. Visibility(
  301. visible: controller.isEdit.value,
  302. child: GestureDetector(
  303. onTap: () {
  304. controller.deleteBtnClick();
  305. },
  306. child: Container(
  307. width: 328.w,
  308. height: 48.h,
  309. decoration: BoxDecoration(
  310. color: "#0279FB".color,
  311. borderRadius: BorderRadius.all(
  312. Radius.circular(10.r),
  313. ),
  314. ),
  315. child: Center(
  316. child: Row(
  317. mainAxisAlignment: MainAxisAlignment.center,
  318. children: [
  319. Text(
  320. "Delete",
  321. style: TextStyle(
  322. color: Colors.white,
  323. fontSize: 16.sp,
  324. fontWeight: FontWeight.w500,
  325. ),
  326. ),
  327. ],
  328. ),
  329. ),
  330. ),
  331. ),
  332. )
  333. ],
  334. );
  335. }),
  336. ),
  337. );
  338. }
  339. }