以代码为例, 记录相关函数的功能:
MyCell 作为ListView 中的一个cell; 使不在或者不完全在屏幕内的cell, 展示到屏幕中. 主要实现在 handleClick() 方法中, 如下:
class MyCell extends StatefulWidget { final int index; const MyCell({Key key, this.index}) : super(key: key); @override _MyCellState createState() => _MyCellState(); } class _MyCellState extends State<MyCell> { String _content = ""; @override Widget build(BuildContext context) { var content = Container( color: Colors.white, height: 100, child: Column( children: <Widget>[ Container( height: 1, color: Colors.black, ), Container( color: Colors.red, child: Text("${widget.index}"), ), Container( color: Colors.green, child: Text(_content), ), ], ), ); return GestureDetector( onTap: () { handleClick(); }, child: content, ); } void handleClick() {
// 获取父级可滚动的组件(ListView) ScrollableState scrollableState = Scrollable.of(context); ScrollPosition position = scrollableState.position; // 当前cell所对应的渲染对象 final RenderObject object = context.findRenderObject();
// 当前cell所在的视口(ListView) final RenderAbstractViewport viewport = RenderAbstractViewport.of(object);
// debug 内容 _content = position.pixels.toString() + " " + viewport.getOffsetToReveal(object, 0).offset.toString() + " " + viewport.getOffsetToReveal(object, 1).offset.toString(); setState(() {}); double alignment;
// 如果偏移量大于 (当前cell顶部与视口顶部之间的距离), 则当前cell靠上对齐滚入屏幕内(cell上边已经超出视口) if (position.pixels > viewport.getOffsetToReveal(object, 0.0).offset) { // Move down to the top of the viewport alignment = 0.0;
// 如果偏移量小于 (当前cell底部与视口底部之间的距离, 可能为负), 则当前cell靠下对齐滚入屏幕内(cell下边还未进入视口内)
} else if (position.pixels < viewport.getOffsetToReveal(object, 1.0).offset){
// Move up to the bottom of the viewport alignment = 1.0; } else { // No scrolling is necessary to reveal the child return; } position.ensureVisible( object, alignment: alignment, duration: Duration(milliseconds: 222), ); } }
讲解一下 getOffsetToReveal 函数的用法
RevealedOffset getOffsetToReveal(RenderObject target, double alignment, { Rect rect });
target: 所需要获取渲染对象
alignment: 传 0~1
0 子对象的位置必须尽可能靠近视口的后缘。(子对象上边 距离视口上边的距离)
0.5
1 子对象的位置必须尽可能靠近视口的后缘。(子对象下边 距离视口下边的距离)
参考:
https://zhuanlan.zhihu.com/p/50350480
Flutter 如何在 scrollview 监听子 widget https://yeungkc.com/flutter-how-to-listen-children-inside-scrollview/