Skip to content

Instantly share code, notes, and snippets.

@debuggerx01
Created August 10, 2018 03:58

Revisions

  1. debuggerx01 created this gist Aug 10, 2018.
    157 changes: 157 additions & 0 deletions JumpToIndexDemo.dart
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,157 @@
    import 'dart:async';

    import 'package:flutter/material.dart';
    import 'package:rect_getter/rect_getter.dart';

    void main() => runApp(new MyApp());

    class MyApp extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
    return new MaterialApp(
    title: 'Flutter Demo',
    theme: new ThemeData(
    primarySwatch: Colors.blue,
    ),
    home: new MyHomePage(title: 'Flutter Demo Home Page'),
    );
    }
    }

    class MyHomePage extends StatefulWidget {
    MyHomePage({Key key, this.title}) : super(key: key);

    final String title;

    @override
    _MyHomePageState createState() => new _MyHomePageState();
    }

    class _MyHomePageState extends State<MyHomePage> {
    var _keys = {};

    @override
    Widget build(BuildContext context) {
    /// 给整个ListView设置Rect信息获取能力
    var listViewKey = RectGetter.createGlobalKey();
    var _ctl = new ScrollController();

    var listView = RectGetter(
    key: listViewKey,
    child: ListView.builder(
    controller: _ctl,
    itemCount: 1000,
    itemBuilder: (BuildContext context, int index) {
    print('build : $index');

    /// 给每个build出来的item设置Rect信息获取能力
    /// 并将用于获取Rect的key及index存入map中备用
    _keys[index] = RectGetter.createGlobalKey();
    return RectGetter(
    key: _keys[index],
    child: Container(
    color: Colors.primaries[index % Colors.primaries.length],
    child: SizedBox(
    width: 100.0,
    height: 50.0 + ((27 * index) % 15) * 3.14,
    child: Center(
    child: Text('$index'),
    ),
    ),
    ),
    );
    },
    ),
    );

    var _textCtl = TextEditingController(
    text: '0',
    );

    List<int> getVisible() {
    /// 先获取整个ListView的rect信息,然后遍历map
    /// 利用map中的key获取每个item的rect,如果该rect与ListView的rect存在交集
    /// 则将对应的index加入到返回的index集合中
    var rect = RectGetter.getRectFromKey(listViewKey);
    var _items = <int>[];
    _keys.forEach((index, key) {
    var itemRect = RectGetter.getRectFromKey(key);
    if (itemRect != null && !(itemRect.top > rect.bottom || itemRect.bottom < rect.top)) _items.add(index);
    });

    /// 这个集合中存的就是当前处于显示状态的所有item的index
    return _items;
    }

    void scrollLoop(int target, Rect listRect) {
    var first = getVisible().first;
    bool direction = first < target;
    Rect _rect;
    if (_keys.containsKey(target)) _rect = RectGetter.getRectFromKey(_keys[target]);
    if (_rect == null || (direction ? _rect.bottom < listRect.top : _rect.top > listRect.bottom)) {
    var offset = _ctl.offset + (direction ? listRect.height / 2 : -listRect.height / 2);
    offset = offset < 0.0 ? 0.0 : offset;
    offset = offset > _ctl.position.maxScrollExtent ? _ctl.position.maxScrollExtent : offset;
    _ctl.jumpTo(offset);
    Timer(Duration.zero, () {
    scrollLoop(target, listRect);
    });
    return;
    }

    _ctl.jumpTo(_ctl.offset + _rect.top - listRect.top);
    }

    void jumpTo(int target) {
    var visible = getVisible();
    if (visible.contains(target)) return;

    var listRect = RectGetter.getRectFromKey(listViewKey);
    scrollLoop(target, listRect);
    }

    return new Scaffold(
    appBar: new AppBar(
    title: new Text(widget.title),
    ),
    body: Column(
    mainAxisAlignment: MainAxisAlignment.start,
    children: <Widget>[
    Expanded(
    child: NotificationListener<ScrollUpdateNotification>(
    onNotification: (notification) {
    getVisible();
    return true;
    },
    child: listView,
    ),
    ),
    Row(
    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
    children: <Widget>[
    SizedBox(
    width: 100.0,
    height: 50.0,
    child: TextField(
    controller: _textCtl,
    ),
    ),
    FlatButton(
    onPressed: () {
    print('${_textCtl.text}');
    jumpTo(int.parse(_textCtl.text));
    },
    child: Text('JUMP'),
    )
    ],
    ),
    ],
    ),
    );
    }
    }

    // 作者:debuggerx
    // 链接:https://juejin.im/post/5b6375f8e51d45190f4af4c2
    // 来源:掘金
    // 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。