Reputation: 41
I have a ListView, and I want the first visible item to increase its size. I've been trying to set a GlobalKey for each element in the listview to get its RenderBox object and get the 'dx' property, so the element with the less 'dx' value greater than 0 is the element which I'm increasing its size.
It only works when the user scrolls the first items, but then I found out it's not possible for the next elements because their RenderBox object is null. As far as I know this is happening because of listview lazy loading, but I don't understand why is it null if I can see that item.
Is there a way to get its renderbox or another way to increase the size of the first visible element?
Upvotes: 1
Views: 1417
Reputation: 2529
You will need to rebuild list items while scrolling in order for this to work. You can use ScrollController
as animation for AnimatedBuilder
.
Working example:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(home: MyPage());
}
}
class MyPage extends StatefulWidget {
@override
_MyPageState createState() => _MyPageState();
}
class _MyPageState extends State<MyPage> {
// We will use this for AnimatedBuilder and ListView
final scrollController = ScrollController();
@override
void dispose() {
scrollController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) => Scaffold(
body: SafeArea(
child: ListView.separated(
controller: scrollController,
itemCount: 100,
separatorBuilder: (context, index) => SizedBox(height: 8.0),
itemBuilder: (context, index) => ItemView(
index: index,
scrollController: scrollController,
),
),
),
);
}
class ItemView extends StatelessWidget {
final int index;
final ScrollController scrollController;
const ItemView({
Key key,
@required this.index,
@required this.scrollController,
}) : super(key: key);
@override
Widget build(BuildContext context) => AnimatedBuilder(
animation: scrollController,
builder: (context, widget) {
final renderObject = context.findRenderObject() as RenderBox;
final offsetY = renderObject?.localToGlobal(Offset.zero)?.dy ?? 0;
print('$index: $offsetY');
// Use offsetY(or X) for your effect
return Container(
height: 44.0,
color: Colors.pink[100],
alignment: Alignment.center,
child: Text(index.toString()),
);
},
);
}
Upvotes: 2