Search code examples
flutterdartflutter-animationflutter-listview

Hero animation and scroll to position between two list in Flutter


I am displaying files as thumbnails such as the Instagram user's profile.

When i click on an item (thumbnail) i have to perform a Hero animation that will reveal the full screen page.

I also want to open the full screen page with the whole list which is directly starting at the given index of the selected post, exactly like in Instagram.

Here is a short GIF that shows better what i mean :

Open post in full screen

I have tried the scroll_to_index package but this does not meet my needs (animation is broken and too slow).

How can i achieve this please ?


Solution

  • this is what i've done, try:

    import 'package:flutter/material.dart';
    
    import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          debugShowCheckedModeBanner: false,
          home: HomePage(),
        );
      }
    }
    
    class HomePage extends StatefulWidget {
      @override
      _HomePageState createState() => _HomePageState();
    }
    
    class _HomePageState extends State<HomePage> {
      @override
      void initState() {
        super.initState();
      }
    
      @override
      void dispose() {
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: GridView.count(
            crossAxisCount: 3,
            children: List.generate(99, (index) {
              return Container(
                width: double.infinity,
                height: double.infinity,
                child: GestureDetector(
                  onTap: () {
                    Navigator.push(
                      context,
                      MaterialPageRoute(
                          builder: (context) => ListPage(index: index)),
                    );
                  },
                  child: Hero(
                    tag: 'photo$index',
                    child: Image.network(
                      'https://images.unsplash.com/photo-1628701621033-50564c683bb0?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=80',
                      fit: BoxFit.cover,
                    ),
                  ),
                ),
              );
            }),
          ),
        );
      }
    }
    
    class ListPage extends StatefulWidget {
      final int index;
    
      ListPage({Key key, @required this.index}) : super(key: key);
    
      @override
      _ListPageState createState() => _ListPageState();
    }
    
    class _ListPageState extends State<ListPage> {
      final ItemScrollController itemScrollController = ItemScrollController();
      final ItemPositionsListener itemPositionsListener =
          ItemPositionsListener.create();
    
      @override
      void initState() {
        super.initState();
      }
    
      @override
      void dispose() {
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return ScrollablePositionedList.builder(
          initialScrollIndex: widget.index,
          itemCount: 99,
          itemBuilder: (context, index) {
            return Column(
              children: [
                AspectRatio(
                  aspectRatio: 1,
                  child: Hero(
                    tag: 'photo$index',
                    child: Image.network(
                      'https://images.unsplash.com/photo-1628701621033-50564c683bb0?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=80',
                      fit: BoxFit.cover,
                    ),
                  ),
                ),
                Container(
                  height: 50,
                  width: MediaQuery.of(context).size.width,
                  child: Text('$index'),
                ),
              ],
            );
          },
          itemScrollController: itemScrollController,
          itemPositionsListener: itemPositionsListener,
        );
      }
    }