演示 overlay 的用法
import 'package:flutter/material.dart'; | |
class OverlayBasic extends StatefulWidget { | |
@override | |
_OverlayBasicState createState() => _OverlayBasicState(); | |
} | |
class _OverlayBasicState extends State<OverlayBasic> { | |
OverlayEntry _entry; | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: AppBar(title: Text('Overlay基本用法')), | |
body: Center( | |
child: Row( | |
mainAxisAlignment: MainAxisAlignment.spaceAround, | |
children: <Widget>[ | |
RaisedButton( | |
onPressed: () { | |
if (_entry == null) { | |
_entry = OverlayEntry(builder: (BuildContext context) { | |
return Positioned( | |
top: 0, | |
left: 0, | |
width: 100, | |
child: SafeArea( | |
child: Material( | |
child: Container( | |
width: 100, | |
alignment: Alignment.center, | |
color: Colors.grey[800].withOpacity(0.7), | |
child: Text('hello'), | |
), | |
), | |
)); | |
}); | |
} | |
Overlay.of(context).insert(_entry); | |
}, | |
child: Text('show overlay'), | |
), | |
RaisedButton( | |
onPressed: () { | |
_entry?.remove(); | |
_entry = null; | |
}, | |
child: Text('hide overlay'), | |
), | |
], | |
)), | |
); | |
} | |
} |
import 'package:flutter/material.dart'; | |
class OverlayPos extends StatefulWidget { | |
@override | |
_OverlayPosState createState() => _OverlayPosState(); | |
} | |
class _MyButton extends StatefulWidget { | |
final PosCallback callback; | |
const _MyButton({Key key, this.callback}) : super(key: key); | |
@override | |
__MyButtonState createState() => __MyButtonState(); | |
} | |
class __MyButtonState extends State<_MyButton> { | |
List<double> _calcPos() { | |
RenderBox renderBox = context.findRenderObject(); | |
var size = renderBox.size; | |
var offset = renderBox.localToGlobal(Offset.zero); | |
return [offset.dx, offset.dy + size.height]; | |
} | |
@override | |
Widget build(BuildContext context) { | |
return RaisedButton( | |
onPressed: () { | |
List<double> list = _calcPos(); | |
widget.callback(list[0], list[1]); | |
}, | |
child: Text('show overlay'), | |
); | |
} | |
} | |
class _OverlayPosState extends State<OverlayPos> { | |
OverlayEntry _entry; | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: AppBar(title: Text('Overlay的位置')), | |
body: Center( | |
child: Row( | |
mainAxisAlignment: MainAxisAlignment.spaceAround, | |
children: <Widget>[ | |
_MyButton( | |
callback: _callback, | |
), | |
RaisedButton( | |
onPressed: () { | |
_entry?.remove(); | |
_entry = null; | |
}, | |
child: Text('hide overlay'), | |
), | |
], | |
)), | |
); | |
} | |
_callback(double left, double top) { | |
if (_entry == null) { | |
_entry = OverlayEntry(builder: (BuildContext context) { | |
return Positioned( | |
top: top,//680, //list[1], | |
left: left,//0, //list[0], | |
width: 100, | |
child: Material( | |
child: Container( | |
width: 100, | |
alignment: Alignment.center, | |
color: Colors.grey[800].withOpacity(0.7), | |
child: Text('hello'), | |
), | |
)); | |
}); | |
} | |
Overlay.of(context).insert(_entry); | |
} | |
} | |
typedef PosCallback = Function(double left, double top); |
import 'package:flutter/material.dart'; | |
class OverlayScrollFollow extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: AppBar( | |
title: Text( | |
'Overlay跟随滚动', | |
), | |
), | |
body: ListView.builder( | |
itemBuilder: (BuildContext context, int index) { | |
return MyListTile( | |
pos: index + 1, | |
); | |
}, | |
itemCount: 100, | |
), | |
); | |
} | |
} | |
class MyListTile extends StatefulWidget { | |
final int pos; | |
MyListTile({Key key, this.pos}) : super(key: key); | |
@override | |
_MyListTileState createState() => _MyListTileState(); | |
} | |
class _MyListTileState extends State<MyListTile> { | |
OverlayEntry _entry; | |
List<double> _calcPos(BuildContext context) { | |
RenderBox renderBox = context.findRenderObject(); | |
var size = renderBox.size; | |
var offset = renderBox.localToGlobal(Offset.zero); | |
return [offset.dx, offset.dy + size.height]; | |
} | |
@override | |
Widget build(BuildContext context) { | |
return CompositedTransformTarget( | |
link: _layerLink, | |
child: ListTile( | |
title: Text('hello ${widget.pos}'), | |
onTap: () { | |
if (_entry != null) { | |
_entry.remove(); | |
_entry = null; | |
} else { | |
List<double> list = _calcPos(context); | |
if (widget.pos % 2 == 1) { | |
_showEntry(context, top: list[1], left: list[0]); | |
} else { | |
_showFollowEntry(context, top: list[1], left: list[0]); | |
} | |
} | |
}, | |
), | |
); | |
} | |
_showEntry(BuildContext context, {double top, double left}) { | |
if (_entry == null) { | |
_entry = OverlayEntry(builder: (BuildContext context) { | |
return Positioned( | |
top: top, //680, //list[1], | |
left: left, //0, //list[0], | |
width: 100, | |
child: Material( | |
child: Container( | |
width: 100, | |
alignment: Alignment.center, | |
color: Colors.grey[800].withOpacity(0.7), | |
child: Text('tip overlay for ${widget.pos}'), | |
), | |
)); | |
}); | |
} | |
Overlay.of(context).insert(_entry); | |
} | |
_showFollowEntry(BuildContext context, {double top, double left}) { | |
if (_entry == null) { | |
_entry = OverlayEntry(builder: (BuildContext context) { | |
return Positioned( | |
top: top, //680, //list[1], | |
left: left, //0, //list[0], | |
width: 100, | |
child: CompositedTransformFollower( | |
link: _layerLink, | |
showWhenUnlinked: false, | |
child: Material( | |
child: Container( | |
width: 100, | |
alignment: Alignment.center, | |
color: Colors.grey[800].withOpacity(0.7), | |
child: Text('tip overlay for ${widget.pos}'), | |
), | |
), | |
)); | |
}); | |
} | |
Overlay.of(context).insert(_entry); | |
} | |
final LayerLink _layerLink = LayerLink(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment