• Flutter实用工具Indexer列表索引和Search搜索帮助。


    1.列表索引

    效果图:

    indexer.dart

    1. import 'package:json_annotation/json_annotation.dart';
    2. abstract class Indexer {
    3. ///用于排序的字母
    4. @JsonKey(includeFromJson: false, includeToJson: false)
    5. String? sortLetter;
    6. ///用于排序的拼音
    7. @JsonKey(includeFromJson: false, includeToJson: false)
    8. String? fullLetter;
    9. ///用于继承类设置需要索引的字段
    10. String? getFullName();
    11. }

    indexer_util.dart

    1. import 'package:kq_flutter_widgets/utils/ex/string_ex.dart';
    2. import 'package:lpinyin/lpinyin.dart';
    3. import 'indexer.dart';
    4. class IndexerUtil {
    5. ///始终排在列表最顶端,可自己改为特定值
    6. static String ALWAYS_TOP_SYMBOL = "★";
    7. ///始终排在列表最底部,可自己改为特定值
    8. static String ALWAYS_BOTTOM_SYMBOL = "#";
    9. ///给数据排序,默认根据{@link IndexModel#getSortLetter()}内容升序排列,其中有两个特殊字符{@link #ALWAYS_TOP_SYMBOL}
    10. ///和{@link #ALWAYS_BOTTOM_SYMBOL}。如果{@link IndexModel#getSortLetter()}获取内容为{@link #ALWAYS_TOP_SYMBOL},
    11. ///则始终排在最顶端,如果{@link IndexModel#getSortLetter()}获取内容为{@link #ALWAYS_BOTTOM_SYMBOL},则始终排在最低端。
    12. ///通常情况下都无需调用{@link IndexModel#setSortLetter(String)},除非你想干预某个数据在列表的排序结果
    13. /// @param isIndexNumber 是否索引数字,如果不索引,则全部放到{@linkplain #ALWAYS_BOTTOM_SYMBOL #}号分组
    14. /// {@code true} 索引
    15. /// {@code false} 不索引
    16. /// @param isUserName 是否是人名,{@code true} 处理多音字作为姓氏时的正确读音
    17. static List<String> getIndexDataextends Indexer>(
    18. {required List data,
    19. LatterType type = LatterType.lowerCase,
    20. bool isIndexNumber = false}) {
    21. for (T t in data) {
    22. _swap(t, isIndexNumber, type);
    23. }
    24. _sortData(data);
    25. ///TODO 优化,从sectionData直接过去key
    26. List<String> indexData = [];
    27. for (T t in data) {
    28. if (t.sortLetter == null && !indexData.contains(ALWAYS_BOTTOM_SYMBOL)) {
    29. indexData.add(ALWAYS_BOTTOM_SYMBOL);
    30. } else if (!indexData.contains(t.sortLetter)) {
    31. indexData.add(t.sortLetter!);
    32. }
    33. }
    34. return indexData;
    35. }
    36. ///给数据排序,默认根据{@link IndexModel#getSortLetter()}内容升序排列,其中有两个特殊字符{@link #ALWAYS_TOP_SYMBOL}
    37. ///和{@link #ALWAYS_BOTTOM_SYMBOL}。如果{@link IndexModel#getSortLetter()}获取内容为{@link #ALWAYS_TOP_SYMBOL},
    38. ///则始终排在最顶端,如果{@link IndexModel#getSortLetter()}获取内容为{@link #ALWAYS_BOTTOM_SYMBOL},则始终排在最低端。
    39. ///通常情况下都无需调用{@link IndexModel#setSortLetter(String)},除非你想干预某个数据在列表的排序结果
    40. /// @param isIndexNumber 是否索引数字,如果不索引,则全部放到{@linkplain #ALWAYS_BOTTOM_SYMBOL #}号分组
    41. /// {@code true} 索引
    42. /// {@code false} 不索引
    43. /// @param isUserName 是否是人名,{@code true} 处理多音字作为姓氏时的正确读音
    44. static Map<String, List> getSectionDataextends Indexer>(
    45. {required List data,
    46. LatterType type = LatterType.lowerCase,
    47. bool isIndexNumber = false}) {
    48. for (T t in data) {
    49. _swap(t, isIndexNumber, type);
    50. }
    51. _sortData(data);
    52. Map<String, List> sectionData = {};
    53. List<String>? indexData = [];
    54. for (T t in data) {
    55. if (t.sortLetter == null && !indexData.contains(ALWAYS_BOTTOM_SYMBOL)) {
    56. indexData.add(ALWAYS_BOTTOM_SYMBOL);
    57. sectionData.putIfAbsent(ALWAYS_BOTTOM_SYMBOL, () => [t]);
    58. } else if (!indexData.contains(t.sortLetter)) {
    59. indexData.add(t.sortLetter!);
    60. sectionData.putIfAbsent(t.sortLetter!, () => [t]);
    61. } else {
    62. sectionData.update(t.sortLetter!, (value) {
    63. value.add(t);
    64. return value;
    65. });
    66. }
    67. }
    68. return sectionData;
    69. }
    70. ///排序
    71. static _sortDataextends Indexer>(List data) {
    72. data.sort((left, right) {
    73. if (left.sortLetter == ALWAYS_TOP_SYMBOL) {
    74. return -1;
    75. } else if (left.sortLetter != ALWAYS_TOP_SYMBOL &&
    76. right.sortLetter == ALWAYS_TOP_SYMBOL) {
    77. return 1;
    78. } else if (left.sortLetter == ALWAYS_BOTTOM_SYMBOL &&
    79. right.sortLetter != ALWAYS_BOTTOM_SYMBOL) {
    80. return 1;
    81. } else if (right.sortLetter == ALWAYS_BOTTOM_SYMBOL) {
    82. return -1;
    83. } else {
    84. return (left.sortLetter ?? "").compareTo(right.sortLetter ?? "");
    85. }
    86. });
    87. }
    88. ///获取汉字全拼首字母
    89. static String? _getSellingextends Indexer>(T t) {
    90. String? latter = t.getFullName();
    91. if (latter.isNullOrEmpty) {
    92. return null;
    93. }
    94. return PinyinHelper.getFirstWordPinyin(latter!);
    95. }
    96. ///根据全拼获取首字母
    97. static String _getFirstLetter(
    98. String pinyin, bool isIndexNumber, LatterType type) {
    99. if (pinyin.isNullOrEmpty) {
    100. return ALWAYS_BOTTOM_SYMBOL;
    101. }
    102. String sortString = pinyin.substring(0, 1);
    103. if (RegExp(r"[A-Za-z]").hasMatch(sortString)) {
    104. return type == LatterType.upperCase
    105. ? sortString.toUpperCase()
    106. : sortString.toLowerCase();
    107. } else if (isIndexNumber && RegExp(r"\d").hasMatch(sortString)) {
    108. return sortString;
    109. } else {
    110. return ALWAYS_BOTTOM_SYMBOL;
    111. }
    112. }
    113. ///数据转化
    114. static _swapextends Indexer>(T t, bool isIndexNumber, LatterType type) {
    115. t.fullLetter ??= _getSelling(t);
    116. t.sortLetter ??= _getFirstLetter(t.fullLetter!, isIndexNumber, type);
    117. if (t.sortLetter != null && t.sortLetter!.isEmpty) {
    118. t.sortLetter = ALWAYS_BOTTOM_SYMBOL;
    119. }
    120. }
    121. }
    122. enum LatterType {
    123. ///大写
    124. upperCase,
    125. ///小写
    126. lowerCase
    127. }

    上面的只是帮助类,帮助数据分组和索引,界面的分组和展示需要自己布局实现。

    2.搜索帮助

    search_able.dart

    1. abstract class SearchAble{
    2. String toSearch();
    3. }

    search_util.dart

    1. import 'package:kq_flutter_widgets/utils/ex/string_ex.dart';
    2. import 'package:kq_flutter_widgets/utils/search/search_able.dart';
    3. /// 搜索帮助类
    4. class SearchUtil {
    5. /// 根据搜索内容搜索出相关数据
    6. /// 用户需要搜索的数据类需要继承[SearchAble],并实现[toSearch]方法
    7. static List searchextends SearchAble>(String? searchText, List data) {
    8. List searchData = [];
    9. if (searchText.isNotNullOrEmpty) {
    10. for (T t in data) {
    11. if (t.toSearch().isNotNullOrEmpty &&
    12. t.toSearch().toLowerCase().trim().contains(searchText!.toLowerCase())) {
    13. searchData.add(t);
    14. }
    15. }
    16. }
    17. return searchData;
    18. }
    19. }

  • 相关阅读:
    excel每行按模板导出为一个excel文件,可以指定列文本生成二维码或者条形码
    编译GCC遇到的“pthread.h” not found问题
    【机器学习Python实战】logistic回归
    Spring bean 的生命周期(总结)
    java数组算法运用
    19_ue4进阶末日生存游戏开发[关联UI和数据]
    OpenAI发布Sora模型,可根据文字生成逼真AI视频
    如何开发一个基于node.js的CLI工具
    再谈VC++动态链接库中的结构成员与VB或C#调用
    大数据运维实战第五课 手动模式构建双 Namenode+Yarn 的 Hadoop 集群(上)
  • 原文地址:https://blog.csdn.net/u012800952/article/details/132711829