Skip to content

Instantly share code, notes, and snippets.

@debuggerx01
Created August 10, 2018 03:58
Show Gist options
  • Save debuggerx01/b8ef756ee02b3eb82ec3702f14ba94e6 to your computer and use it in GitHub Desktop.
Save debuggerx01/b8ef756ee02b3eb82ec3702f14ba94e6 to your computer and use it in GitHub Desktop.
JumpToIndexDemoForFlutter
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
// 来源:掘金
// 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment