mirror of
https://github.com/lakaola/chat-flutter.git
synced 2026-06-02 03:43:20 +08:00
289 lines
7.3 KiB
Dart
289 lines
7.3 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:get/get.dart';
|
|
import 'package:demo/config/app_theme.dart';
|
|
import 'package:demo/component/component_common.dart';
|
|
import 'package:grouped_list/grouped_list.dart';
|
|
import 'package:lpinyin/lpinyin.dart';
|
|
import 'package:tdesign_flutter/tdesign_flutter.dart';
|
|
|
|
// 通讯录组件
|
|
class ComponentContact extends StatefulWidget {
|
|
// 选中文字
|
|
final String mark;
|
|
// 数据列表
|
|
final List<ContactModel> dataList;
|
|
// 选中列表
|
|
final List<String>? selectList;
|
|
// 单击事件
|
|
final Function(ContactModel model)? onTap;
|
|
// 多选事件
|
|
final Function(List<String> selectList)? onSelect;
|
|
const ComponentContact({
|
|
super.key,
|
|
this.mark = '选中',
|
|
required this.dataList,
|
|
this.selectList,
|
|
this.onTap,
|
|
this.onSelect,
|
|
});
|
|
|
|
@override
|
|
createState() => _ComponentContactState();
|
|
}
|
|
|
|
class _ComponentContactState extends State<ComponentContact> {
|
|
List<ContactModel> displayList = [];
|
|
List<String> selectList = [];
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
displayList = widget.dataList;
|
|
selectList = widget.selectList ?? [];
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
// 处理参数
|
|
List<ContactModel> dataList = _handle(displayList);
|
|
return GestureDetector(
|
|
behavior: HitTestBehavior.translucent,
|
|
onPanDown: (details) {
|
|
FocusScope.of(context).requestFocus(FocusNode());
|
|
},
|
|
child: Column(
|
|
children: [
|
|
_buildSearch(),
|
|
Expanded(
|
|
child: _buildList(dataList),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
// 搜索框
|
|
_buildSearch() {
|
|
return TDSearchBar(
|
|
placeHolder: '请输内容',
|
|
onTextChanged: (values) {
|
|
setState(() {
|
|
// 过滤数据
|
|
displayList = widget.dataList.where((data) {
|
|
if (data.select) {
|
|
return true;
|
|
}
|
|
String nickname = data.nickname.toLowerCase();
|
|
String extend = data.extend.toLowerCase();
|
|
String value = values.toLowerCase();
|
|
return nickname.contains(value) || extend.contains(value);
|
|
}).toList();
|
|
});
|
|
},
|
|
);
|
|
}
|
|
|
|
_buildList(List<ContactModel> dataList) {
|
|
return GroupedListView(
|
|
// 数据列表
|
|
elements: dataList,
|
|
// 分组类型
|
|
groupBy: (element) {
|
|
return element.tag;
|
|
},
|
|
// 分组排序
|
|
groupComparator: (value1, value2) {
|
|
// 排序
|
|
if (value1 == "#" || value2 == "#") {
|
|
return -1;
|
|
}
|
|
// 选中
|
|
if (value1 == widget.mark || value2 == widget.mark) {
|
|
return -1;
|
|
}
|
|
return value1.compareTo(value2);
|
|
},
|
|
// 分组间隔
|
|
groupSeparatorBuilder: (value) {
|
|
return _buildTag(value);
|
|
},
|
|
// 单条排序
|
|
itemComparator: (item1, item2) {
|
|
return item1.pinyin.compareTo(item2.pinyin);
|
|
},
|
|
// 单条数据
|
|
indexedItemBuilder: (context, element, index) {
|
|
bool divider = true;
|
|
if (index + 1 < dataList.length) {
|
|
divider = dataList[index].tag == dataList[index + 1].tag;
|
|
}
|
|
return _buildItem(element, divider);
|
|
},
|
|
);
|
|
}
|
|
|
|
// 分组标签
|
|
_buildTag(String value) {
|
|
return Container(
|
|
height: 40,
|
|
width: context.width,
|
|
padding: const EdgeInsets.only(left: 16.0),
|
|
color: const Color(0xFFF3F4F5),
|
|
alignment: Alignment.centerLeft,
|
|
child: Text(
|
|
value,
|
|
softWrap: false,
|
|
style: const TextStyle(
|
|
fontSize: 14.0,
|
|
color: Color(0xFF666666),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
// 处理参数
|
|
List<ContactModel> _handle(List<ContactModel> displayList) {
|
|
List<ContactModel> dataList = [];
|
|
// 处理数据
|
|
if (displayList.isNotEmpty) {
|
|
for (int i = 0, length = displayList.length; i < length; i++) {
|
|
String nickname = displayList[i].nickname;
|
|
String pinyin = PinyinHelper.getPinyinE(nickname);
|
|
String tag = pinyin.substring(0, 1).toUpperCase();
|
|
if (displayList[i].select) {
|
|
tag = widget.mark;
|
|
}
|
|
// 其他
|
|
else if (!RegExp("[A-Z]").hasMatch(tag)) {
|
|
tag = '#';
|
|
}
|
|
displayList[i].tag = tag;
|
|
displayList[i].pinyin = pinyin;
|
|
}
|
|
// A-Z sort.
|
|
sortTag(displayList);
|
|
// 放入列表
|
|
dataList.addAll(displayList);
|
|
}
|
|
setState(() {});
|
|
return dataList;
|
|
}
|
|
|
|
// 排序
|
|
void sortTag(List<ContactModel> dataList) {
|
|
if (dataList.isNotEmpty) {
|
|
dataList.sort((a, b) {
|
|
// 所有人
|
|
if (a.userId == "0") {
|
|
return -1;
|
|
}
|
|
// 选中
|
|
if (a.tag == widget.mark) {
|
|
return -1;
|
|
}
|
|
// 选中
|
|
if (b.tag == "#") {
|
|
return -1;
|
|
}
|
|
// 选中
|
|
if (a.tag == "#") {
|
|
return 1;
|
|
}
|
|
// 选中
|
|
if (b.tag == widget.mark) {
|
|
return 1;
|
|
}
|
|
int sort = a.tag.compareTo(b.tag);
|
|
if (sort == 0) {
|
|
return a.userId.compareTo(b.userId);
|
|
}
|
|
return sort;
|
|
});
|
|
}
|
|
}
|
|
|
|
// 详情
|
|
_buildItem(ContactModel model, bool divider) {
|
|
String portrait = model.portrait;
|
|
String nickname = model.nickname;
|
|
String userId = model.userId;
|
|
String extend = model.extend;
|
|
return Column(
|
|
children: [
|
|
ListTile(
|
|
leading: ComponentCommon.showAvatar(
|
|
portrait,
|
|
size: 40,
|
|
),
|
|
title: Text(nickname),
|
|
subtitle: extend.isEmpty ? null : Text(extend),
|
|
trailing: widget.onSelect != null
|
|
? Checkbox(
|
|
value: model.select,
|
|
fillColor: WidgetStateColor.resolveWith((states) {
|
|
// 开启状态
|
|
if (states.contains(WidgetState.selected)) {
|
|
// 选中
|
|
if (model.select) {
|
|
return AppTheme.color;
|
|
}
|
|
// 未选中
|
|
return Colors.grey;
|
|
}
|
|
// 关闭状态
|
|
return Colors.white;
|
|
}),
|
|
onChanged: (value) {
|
|
model.select = value!;
|
|
if (value) {
|
|
selectList.add(userId);
|
|
} else {
|
|
selectList.remove(userId);
|
|
}
|
|
setState(() {});
|
|
widget.onSelect?.call(selectList);
|
|
},
|
|
)
|
|
: null,
|
|
onTap: () {
|
|
if (widget.onTap != null) {
|
|
widget.onTap?.call(
|
|
ContactModel(
|
|
userId: userId,
|
|
nickname: nickname,
|
|
portrait: portrait,
|
|
),
|
|
);
|
|
}
|
|
},
|
|
),
|
|
if (divider) ComponentCommon.divider()
|
|
],
|
|
);
|
|
}
|
|
}
|
|
|
|
class ContactModel {
|
|
String userId;
|
|
String nickname;
|
|
String portrait;
|
|
String pinyin;
|
|
bool select;
|
|
String extend;
|
|
String tag;
|
|
|
|
ContactModel({
|
|
required this.userId,
|
|
required this.nickname,
|
|
required this.portrait,
|
|
this.select = false,
|
|
this.extend = '',
|
|
String remark = '',
|
|
this.tag = '',
|
|
this.pinyin = '',
|
|
}) {
|
|
if (remark.isNotEmpty) {
|
|
nickname = remark;
|
|
}
|
|
}
|
|
}
|