Draw outside listview bounds in Flutter
1,625
If you try to use OverflowBox or Transform, content of an item will still clip and won't be drawn outside of its bounding box. But it's possible to use Overlay to draw an element on top of list and position it on a specific list item, though it's a bit complicated.
class _MyHomePageState extends State<MyHomePage> with WidgetsBindingObserver {
final elements = List.generate(12, (i) => i);
int selectedIndex;
OverlayEntry overlayEntry;
List<LayerLink> layerLinks;
@override
void initState() {
super.initState();
// Creating a layer link for each list cell
layerLinks = List.generate(elements.length, (i) => LayerLink());
}
void createOverlayEntry(int i, BuildContext context) {
// Removing an overlay entry, if there was one
overlayEntry?.remove();
final renderBox = context.findRenderObject() as RenderBox;
final size = renderBox.size;
final offset = renderBox.localToGlobal(Offset.zero);
// Creating a new overlay entry linked to specific list element
overlayEntry = OverlayEntry(
builder: (context) => Positioned(
left: 0,
top: 0,
child: CompositedTransformFollower(
link: layerLinks[i],
showWhenUnlinked: false,
offset: Offset(-20, 0),
child: Material(
color: Colors.yellow,
child: InkWell(
onTap: () {
setState(() {
selectedIndex = null;
});
overlayEntry?.remove();
overlayEntry = null;
},
child: Container(
alignment: Alignment.center,
width: 70,
height: elementHeight,
child: Text('$i')
),
)
),
)
)
);
// Inserting an entry
Overlay.of(context).insert(overlayEntry);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Container(
height: elementHeight,
child: ListView.separated(
scrollDirection: Axis.horizontal,
itemCount: elements.length,
itemBuilder: (c, i) {
return CompositedTransformTarget(
link: layerLinks[i],
child: Material(
color: Colors.red,
child: InkWell(
onTap: () {
setState(() {
selectedIndex = i;
});
createOverlayEntry(i, context);
},
child: Container(
alignment: Alignment.center,
width: 30,
child: Text('${elements[i]}'),
),
),
),
);
},
separatorBuilder: (c, i) {
return Container(width: 10, height: 10);
},
),
),
);
}
}

Comments
-
Koen Van Looveren 10 minutes
I want to transform my item that it is bigger than the listview itself. (intention for focused navigation)
My List:
Container( height: 100, child: ListView.builder( itemBuilder: (context, index) => HomeItem(title: '$index'), scrollDirection: Axis.horizontal, ), ),
My Item:
class HomeItem extends StatelessWidget { final String title; final bool expand; const HomeItem({ @required this.title, this.expand = false, }); @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.symmetric(horizontal: ThemeDimens.padding8), child: Transform.scale( scale: expand ? 1.5 : 1, child: AnimatedContainer( width: 50, height: 100, color: expand ? ThemeColors.accent : ThemeColors.primary, duration: ThemeDurations.shortAnimationDuration(), child: Center( child: Text(title), ), ), ), ); } }
-
ZeRj over 2 yearsHave a look at this widget, it should do the trick: api.flutter.dev/flutter/widgets/OverflowBox-class.html
-
Koen Van Looveren over 2 yearsI tried indeed with OverFlowBox but I couldn't figure it out. Where should I place it?
-
Igor Kharakhordin over 2 yearsOverflowBox won't work in this case. I'm gonna answer you in a moment.
-
-
LonelyWolf over 2 yearsNice work.. Vote up from me :) but I believe OP was asking to scale the button in y axis not x as you did it
-
Koen Van Looveren over 2 yearsYes I am looking for a solution that also draws out of bounds at the top of you list. (Y axis) This sollution is exactly the same as what I initially posted.
-
Igor Kharakhordin over 2 years@KoenVanLooveren My solution will also work for Y axis. Just change Y offset of an overlay entry (Offset(-20, -20), for example)