all_view.dart 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  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.first.number ??
  216. '无号码',
  217. style: TextStyle(
  218. color: Colors.white,
  219. fontSize: 14.sp,
  220. fontWeight: FontWeight.w500,
  221. ),
  222. ),
  223. ],
  224. ),
  225. // 删除按钮
  226. Visibility(
  227. visible: controller.isEdit.value,
  228. child: GestureDetector(
  229. onTap: () {
  230. controller.toggleSelectContact(
  231. contact);
  232. },
  233. child: Container(
  234. child: controller.selectedContacts
  235. .contains(contact.id)
  236. ? Center(
  237. child: Assets
  238. .images.iconSelected
  239. .image(
  240. width: 16.w,
  241. height: 16.h,
  242. ),
  243. )
  244. : Center(
  245. child: Assets
  246. .images.iconUnselected
  247. .image(
  248. width: 16.w,
  249. height: 16.h,
  250. ),
  251. ),
  252. ),
  253. ),
  254. ),
  255. ],
  256. ),
  257. );
  258. }),
  259. SizedBox(
  260. height: 12.h,
  261. ),
  262. ],
  263. );
  264. },
  265. );
  266. }),
  267. ),
  268. Container(
  269. width: 30,
  270. child: ListView.builder(
  271. // physics: NeverScrollableScrollPhysics(),
  272. itemCount: ContactState.initials.length,
  273. itemBuilder: (context, index) {
  274. return GestureDetector(
  275. onTap: () =>
  276. controller
  277. .scrollToInitial(
  278. ContactState.initials[index]),
  279. child: Padding(
  280. padding: EdgeInsets.symmetric(vertical: 2),
  281. child: Text(
  282. ContactState.initials[index],
  283. textAlign: TextAlign.center,
  284. style: TextStyle(
  285. fontSize: 14,
  286. color: "#0279FB".color,
  287. fontWeight: FontWeight.bold,
  288. ),
  289. ),
  290. ),
  291. );
  292. },
  293. ),
  294. ),
  295. ],
  296. ),
  297. ),
  298. Visibility(
  299. visible: controller.isEdit.value,
  300. child: GestureDetector(
  301. onTap: () {
  302. controller.deleteBtnClick();
  303. },
  304. child: Container(
  305. width: 328.w,
  306. height: 48.h,
  307. decoration: BoxDecoration(
  308. color: "#0279FB".color,
  309. borderRadius: BorderRadius.all(
  310. Radius.circular(10.r),
  311. ),
  312. ),
  313. child: Center(
  314. child: Row(
  315. mainAxisAlignment: MainAxisAlignment.center,
  316. children: [
  317. Text(
  318. "Delete",
  319. style: TextStyle(
  320. color: Colors.white,
  321. fontSize: 16.sp,
  322. fontWeight: FontWeight.w500,
  323. ),
  324. ),
  325. ],
  326. ),
  327. ),
  328. ),
  329. ),
  330. )
  331. ],
  332. );
  333. }),
  334. ),
  335. );
  336. }
  337. }