Created
July 14, 2024 23:02
-
-
Save Mastersam07/1006ce0f98fd8e088fae785c609be274 to your computer and use it in GitHub Desktop.
Find scrollables in viewport
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/material.dart'; | |
void main() { | |
runApp(MyApp()); | |
} | |
class MyApp extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return MaterialApp( | |
home: Scaffold( | |
appBar: AppBar( | |
title: Text('Scrollable Widgets in Viewport'), | |
), | |
body: HomeScreen(), | |
), | |
); | |
} | |
} | |
class HomeScreen extends StatefulWidget { | |
@override | |
_HomeScreenState createState() => _HomeScreenState(); | |
} | |
class _HomeScreenState extends State<HomeScreen> { | |
final GlobalKey _key = GlobalKey(); | |
List<Widget> scrollableWidgets = []; | |
@override | |
void initState() { | |
super.initState(); | |
WidgetsBinding.instance.addPostFrameCallback((_) { | |
findScrollableWidgets(); | |
}); | |
} | |
void findScrollableWidgets() { | |
final RenderObject? rootRenderObject = | |
_key.currentContext?.findRenderObject(); | |
if (rootRenderObject == null) return; | |
final List<Widget> foundScrollables = []; | |
void visitChildren(Element element) { | |
element.visitChildren((child) { | |
if (child.widget is ScrollView) { | |
final RenderObject renderObject = child.renderObject!; | |
if (_isWithinViewport(rootRenderObject as RenderBox, renderObject)) { | |
foundScrollables.add(child.widget); | |
} | |
} | |
visitChildren(child); | |
}); | |
} | |
visitChildren(_key.currentContext as Element); | |
setState(() { | |
scrollableWidgets = foundScrollables; | |
}); | |
} | |
bool _isWithinViewport(RenderBox viewport, RenderObject renderObject) { | |
final Size viewportSize = viewport.size; | |
final Offset viewportOffset = viewport.localToGlobal(Offset.zero); | |
final Rect viewportRect = viewportOffset & viewportSize; | |
final Size renderObjectSize = renderObject.paintBounds.size; | |
final Offset renderObjectOffset = | |
(renderObject as RenderBox).localToGlobal(Offset.zero); | |
final Rect renderObjectRect = renderObjectOffset & renderObjectSize; | |
return viewportRect.overlaps(renderObjectRect); | |
} | |
@override | |
Widget build(BuildContext context) { | |
return Column( | |
children: [ | |
Expanded( | |
child: SingleChildScrollView( | |
key: _key, | |
child: Column( | |
children: [ | |
ListView.builder( | |
shrinkWrap: true, | |
physics: NeverScrollableScrollPhysics(), | |
itemCount: 20, | |
itemBuilder: (context, index) { | |
return ListTile( | |
title: Text('Item $index'), | |
); | |
}, | |
), | |
GridView.builder( | |
shrinkWrap: true, | |
physics: NeverScrollableScrollPhysics(), | |
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( | |
crossAxisCount: 2, | |
), | |
itemCount: 20, | |
itemBuilder: (context, index) { | |
return Card( | |
child: Center(child: Text('Card $index')), | |
); | |
}, | |
), | |
], | |
), | |
), | |
), | |
ElevatedButton( | |
onPressed: () { | |
findScrollableWidgets(); | |
print('Found ${scrollableWidgets.length} scrollable widgets'); | |
for (var widget in scrollableWidgets) { | |
print(widget.runtimeType); | |
} | |
}, | |
child: Text('Find Scrollable Widgets'), | |
), | |
], | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment