「这是我参与11月更文应战的第11天,活动详情查看:2021最终一次更文应战」

Hi

  • Wechat: RyukieW
  • 微信公众号:LabLawliet
  • 技术文章归档
  • Github
我的个人项目 扫雷Elic 无尽天梯 梦见账本 隐私拜访记录
类型 游戏 财政 工具
AppStore Elic Umemi 隐私拜访记录

更多专栏:

Lawliet的独立开发碎碎念

Lawliet的iOS游园会

Lawliet的iOS底层实验室

Lawliet的iOS逆向实验室

Lawliet的刷题小本本

Lawliet的Flutter实验室

Flutter小技巧|从侧索引条封装看手势处理与clamp函数

Flutter小技巧|Widget初始化方法重写&链式调用&排序

Flutter小技巧|通过多款式Cell看断语

前语

在进行列表视图的开发场景中,通过索引快速滑动到指定 section 是常见的功用。那么在 flutter 中咱们该怎么完成这种功用呢? 本文就将以联系人页面为例进行解说。

Flutter小技巧|ListView滑动到分组头部

分析ListView

在 iOS 开发中咱们常运用 open func scrollToItem(at indexPath: IndexPath, at scrollPosition: UICollectionView.ScrollPosition, animated: Bool) 这类方法来完成 CollectionView 和 TableView 下的滚动到指定方位的效果。

但 flutter 的 ListView 并不含有这种分组的概念,也没有供给这种便当的方法,但是有根底API可认为咱们供给一些思路。

ScrollController

咱们能够在为 ListView 绑定一个 ScrollController ,它的效果能够理解为咱们进行 iOS 开发中的 相关署理,但是他的效果会更富一些。

Flutter小技巧|ListView滑动到分组头部

为来滚动到指定方位,这儿供给了两个 API,更具体的阐明能够点进头文件查看注释,这儿就不再赘述。

animateTo

有动画

  Future<void> animateTo(
    double offset, {
    required Duration duration,
    required Curve curve,
  }) async {
    assert(_positions.isNotEmpty, 'ScrollController not attached to any scroll views.');
    await Future.wait<void>(<Future<void>>[
      for (int i = 0; i < _positions.length; i += 1) _positions[i].animateTo(offset, duration: duration, curve: curve),
    ]);
  }

jumpTo

无动画

  void jumpTo(double value) {
    assert(_positions.isNotEmpty, 'ScrollController not attached to any scroll views.');
    for (final ScrollPosition position in List<ScrollPosition>.from(_positions))
      position.jumpTo(value);
  }

这儿为了完成通讯录滑动到组头部的效果,挑选运用 jumpTo

提早计算好每组的偏移量

class _ContactsPageState extends State<ContactsPage> {
  final List<Friends> _contacts = [];// 联系人数组
  final List<Friends> _systems = []; // 顶部体系进口数组
  final List<String> _indexs = []; // 索引
  ScrollController _scroller = ScrollController();
  Map<int, double> _indexOffsets = {}; // 偏移量Map
  @override
  void initState() {
    super.initState();
    double offsetY = 0;
    _contacts
      ..addAll(friendsData)
      ..addAll(friendsData)
      ..sort((a, b) {
        if (a.indexLetter == null || b.indexLetter == null) {
          return 0;
        }
        return a.indexLetter!.compareTo(b.indexLetter!);
      });
    _systems
        .addAll(friendsHeaderData);
    offsetY = ContactCell.baseCellHeight * friendsHeaderData.length.toDouble();// 第一个联系人组的顶部偏移量为顶部体系进口的总高度
    var index = 0;
    _contacts.forEach((element) {
      if (element.indexLetter != null && _indexs.contains(element.indexLetter) == false) {
        _indexs.add(element.indexLetter!);
        _indexOffsets.addAll({ index : offsetY });
        index += 1;
        // 根底Cell高度,加上顶部分组头部高度
        offsetY += ContactCell.baseCellHeight + ContactCell.indexHeight;
      }
      else {
        // 根底Cell高度
        offsetY += ContactCell.baseCellHeight;
      }
    });
  }
  ...
}

IndexBar的事件处理

IndexBar(
    dataSource: _indexs,
    callBack: (index, title) {
        if (_indexOffsets[index] != null) {
        _scroller.jumpTo(_indexOffsets[index]!);
        }
    },
)

项目完整代码

GitHub