import 'package:azlistview/azlistview.dart'; import 'package:flutter/material.dart'; import 'package:lpinyin/lpinyin.dart'; class ContactInfo extends ISuspensionBean { final String name; final String avatar; String? tagIndex; String? namePinyin; ContactInfo({ required this.name, required this.avatar, this.tagIndex, this.namePinyin, }); @override String getSuspensionTag() => tagIndex ?? '#'; } /// ================= Page ================= class ContactsPage extends StatefulWidget { const ContactsPage({super.key}); @override State createState() => _ContactsPageState(); } class _ContactsPageState extends State { List contactList = []; List topList = []; @override void initState() { super.initState(); _loadFakeData(); } void _loadFakeData() { contactList = [ ContactInfo(name: '张三', avatar: 'https://picsum.photos/id/1011/200'), ContactInfo(name: '李四', avatar: 'https://picsum.photos/id/1012/200'), ContactInfo(name: '王五', avatar: 'https://picsum.photos/id/1013/200'), ContactInfo(name: '赵六', avatar: 'https://picsum.photos/id/1014/200'), ContactInfo(name: '陈七', avatar: 'https://picsum.photos/id/1015/200'), ContactInfo(name: '刘八', avatar: 'https://picsum.photos/id/1016/200'), ContactInfo(name: '周九', avatar: 'https://picsum.photos/id/1017/200'), ContactInfo(name: '吴十', avatar: 'https://picsum.photos/id/1018/200'), ContactInfo(name: '欧阳峰', avatar: 'https://picsum.photos/id/1021/200'), ContactInfo(name: '诸葛青', avatar: 'https://picsum.photos/id/1022/200'), ContactInfo(name: '司马光', avatar: 'https://picsum.photos/id/1023/200'), ContactInfo(name: '慕容复', avatar: 'https://picsum.photos/id/1024/200'), ContactInfo(name: '安琪拉', avatar: 'https://picsum.photos/id/1031/200'), ContactInfo(name: '亚瑟', avatar: 'https://picsum.photos/id/1032/200'), ContactInfo(name: '李白', avatar: 'https://picsum.photos/id/1033/200'), ContactInfo(name: '韩信', avatar: 'https://picsum.photos/id/1034/200'), ContactInfo(name: '孙尚香', avatar: 'https://picsum.photos/id/1035/200'), ContactInfo(name: '鲁班', avatar: 'https://picsum.photos/id/1036/200'), ContactInfo(name: '妲己', avatar: 'https://picsum.photos/id/1037/200'), ContactInfo(name: '甄姬', avatar: 'https://picsum.photos/id/1038/200'), ]; _handleList(contactList); } void _handleList(List list) { for (var item in list) { final pinyin = PinyinHelper.getPinyinE(item.name); final tag = pinyin.substring(0, 1).toUpperCase(); item.namePinyin = pinyin; item.tagIndex = RegExp(r'[A-Z]').hasMatch(tag) ? tag : '#'; } SuspensionUtil.sortListBySuspensionTag(list); SuspensionUtil.setShowSuspensionStatus(list); setState(() {}); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.transparent, appBar: _buildAppBar(), body: Column( children: [_buildSearchBar(), Expanded(child: _buildAzListView())], ), ); } PreferredSizeWidget _buildAppBar() { return AppBar( automaticallyImplyLeading: false, backgroundColor: Color(0xFF120D25), elevation: 0, centerTitle: true, title: const Text( '通讯录', style: TextStyle( fontSize: 18, fontWeight: FontWeight.w600, color: Colors.white, ), ), ); } Widget _buildAzListView() { return AzListView( data: contactList, itemCount: contactList.length, itemBuilder: (_, index) { final c = contactList[index]; return Container( child: ListTile( leading: CircleAvatar( backgroundImage: NetworkImage(c.avatar), onBackgroundImageError: (_, __) {}, ), title: Text( c.name, style: const TextStyle(fontSize: 16, color: Colors.white), ), ), ); }, susItemBuilder: (_, index) { final tag = contactList[index].getSuspensionTag(); return Container( height: 28, padding: const EdgeInsets.symmetric(horizontal: 16), alignment: Alignment.centerLeft, color: const Color(0xFF2B2744), child: Text( tag, style: const TextStyle(fontSize: 13, color: Colors.grey), ), ); }, indexBarData: [...kIndexBarData], indexBarOptions: IndexBarOptions( textStyle: const TextStyle(fontSize: 12, color: Color(0xFF8E8E93)), selectItemDecoration: const BoxDecoration( shape: BoxShape.circle, color: Colors.green, ), ), ); } Widget _buildSearchBar() { return Container( height: 44, decoration: BoxDecoration(color: Color(0xFF2F2A47)), child: TextField( textAlignVertical: TextAlignVertical.center, style: const TextStyle(color: Colors.white), decoration: InputDecoration( isDense: true, hintText: '搜索联系人', hintStyle: const TextStyle(fontSize: 15, color: Colors.white), prefixIcon: const Icon(Icons.search, size: 20, color: Colors.white), border: InputBorder.none, ), ), ); } }