Hero animation and scroll to position between two list in Flutter Hero animation and scroll to position between two list in Flutter dart dart

Hero animation and scroll to position between two list in Flutter


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,    );  }}


Pass the selected item to destinate widget and build Hero tag dynamically.

Main idea is to avoid too many matched Hero tags.

class MyImagesList extends Stateless Widget {  final String selectedItem;  final List<String> items;  const MyImagesList(this.selectedItem, this.items);  void build(BuildContext context) {    return Column(children: [      for (var item in items)        item == selectedItem          ? Hero(tag: item, child: Text(item))          : Text(item)     ]);  }}