flutter - 如何将英雄小部件动画到另一个页面中轮播的第一个元素?

标签 flutter dart widget carousel

我正在尝试将 Hero Widget 和 Carousel 集成到 flutter 中。
我有一个产品列表,onTap 产品的图像通过 Hero Widget 动画到详细信息页面。
我已经能够在没有轮播的情况下成功实现英雄小部件,但是在详细信息页面上,我希望能够使用轮播查看同一产品的不同图片。
我怎样才能使轮播上的第一个项目与之前的页面具有相同的英雄标签,如下图所示?
enter image description here
第 1 页

GestureDetector(
                  onTap: () {
                    Navigator.push(
                      context,
                      MaterialPageRoute(
                          builder: (context) => DetailsPage(
                              url: widget.url,
                              title: widget.url,
                              index: widget.index)),
                    );
                  },
                  child: Hero(
                    tag: "product-image+${widget.index}",
                    child: Container(
                      padding: EdgeInsets.all(16.0),
                      decoration: BoxDecoration(
                          borderRadius: BorderRadius.circular(10)),
                      child: FadeInImage.memoryNetwork(
                        placeholder: kTransparentImage,
                        image:
                            'https://i.dlpng.com/static/png/6838599_preview.png',
                      ),
                    ),
                  ))),
详情页
import 'package:carousel_slider/carousel_slider.dart';
import 'package:flutter/material.dart';

class DetailsPage extends StatefulWidget {
  final String url;
  final String title;
  final int index;
  DetailsPage({this.url, this.title, this.index});

  @override
  _DetailsPageState createState() => _DetailsPageState();
}

class _DetailsPageState extends State<DetailsPage> {
  List imgList = [
    'https://i.dlpng.com/static/png/6838599_preview.png',
    'https://i.dlpng.com/static/png/6838599_preview.png',
    'https://i.dlpng.com/static/png/6838599_preview.png',
    'https://i.dlpng.com/static/png/6838599_preview.png',
  ];
  int _current = 0;

  List<T> map<T>(List list, Function handler) {
    List<T> result = [];
    for (var i = 0; i < list.length; i++) {
      result.add(handler(i, list[i]));
    }
    return result;
  }

  @override
  Widget build(BuildContext context) {
    final double height = MediaQuery.of(context).size.height;
    return Scaffold(
      backgroundColor: Theme.of(context).canvasColor,
      appBar: AppBar(
        title: Center(
          child: Text(
            'Details',
            style: TextStyle(
                fontFamily: 'OpenSansLight',
                fontSize: 26,
                color: Theme.of(context).textTheme.headline1.color),
          ),
        ),
        elevation: 0,
        backgroundColor: Theme.of(context).canvasColor,
        leading: IconButton(
            icon: Icon(Icons.arrow_back,
                color: Theme.of(context).iconTheme.color),
            onPressed: () {
              Navigator.of(context).pop();
            }),
      ),
      body: Container(
        height: height,
        child: SingleChildScrollView(
          child: Column(
            children: <Widget>[
              Hero(
                tag: "product-image+${widget.index}",
                child: Container(
                  padding: EdgeInsets.all(8.0),
                  height: 200.0,
                  alignment: Alignment.topCenter,
                  decoration: BoxDecoration(
                      image: DecorationImage(
                          image: NetworkImage(
                            widget.url ??
                                'https://i.dlpng.com/static/png/6838599_preview.png',
                          ),
                          fit: BoxFit.contain)),
                ),
              ),
              CarouselSlider(
                options: CarouselOptions(
                    height: 200.0,
                    initialPage: 0,
                    reverse: false,
                    autoPlay: false,
                    enableInfiniteScroll: false,
                   
                    scrollDirection: Axis.horizontal,
                    onPageChanged: (index, fn) {
                      setState(() {
                        _current = index;
                      });
                    }),
                items: imgList.map((imgUrl) {
                  return Builder(
                    builder: (BuildContext context) {
                      return Container(
                        width: MediaQuery.of(context).size.width,
                        margin: EdgeInsets.symmetric(horizontal: 5.0),
                        decoration: BoxDecoration(color: Theme.of(context).cardColor, borderRadius: BorderRadius.circular(10),),
                        child: 
                        
                        Image.network(
                          imgUrl,
                          fit: BoxFit.cover,
                        ),
                      );
                    },
                  );
                }).toList(),
              ),
              SizedBox(height: 10),
              Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: map<Widget>(imgList, (index, url) {
                  return Container(
                    width: 30.0,
                    height: 2.0,
                    margin:
                        EdgeInsets.symmetric(vertical: 10.0, horizontal: 4.0),
                    decoration: BoxDecoration(
                      shape: BoxShape.rectangle,
                      borderRadius: BorderRadius.circular(10.0),
                      color:
                          _current == index ? Colors.deepPurple : Colors.grey,
                    ),
                  );
                }),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

最佳答案

一个相当愚蠢的问题。我不假思索地做到了。我刚刚将 Hero Widget 包裹在 Carousel slider 上

 Container(
        height: height,
        child: SingleChildScrollView(
          child: Column(
            children: <Widget>[
              Padding(
                padding: const EdgeInsets.all(8.0),
                child: Container(
                  width: MediaQuery.of(context).size.width,
                  margin: EdgeInsets.symmetric(horizontal: 5.0),
                  decoration: BoxDecoration(
                    color: Theme.of(context).cardColor,
                    borderRadius: BorderRadius.circular(10),
                  ),
                  child: Column(
                    children: <Widget>[
                      Hero(
                        tag: "product-image+${widget.index}",
                        child: CarouselSlider(
                          options: CarouselOptions(
                              height: 200.0,
                              enlargeCenterPage: true,
                              enlargeStrategy: CenterPageEnlargeStrategy.height,
                              initialPage: 0,
                              reverse: false,
                              autoPlay: false,
                              enableInfiniteScroll: false,
                              scrollDirection: Axis.horizontal,
                              onPageChanged: (index, fn) {
                                setState(() {
                                  _current = index;
                                });
                              }),
                          items: imgList.map((imgUrl) {
                            return Builder(
                              builder: (BuildContext context) {
                                return Image.network(
                                  imgUrl,
                                  fit: BoxFit.cover,
                                );
                              },
                            );
                          }).toList(),
                        ),
                      ),
                      SizedBox(height: 10),
                      Row(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: map<Widget>(imgList, (index, url) {
                          return Container(
                            width: 30.0,
                            height: 2.0,
                            margin: EdgeInsets.symmetric(
                                vertical: 10.0, horizontal: 4.0),
                            decoration: BoxDecoration(
                              shape: BoxShape.rectangle,
                              borderRadius: BorderRadius.circular(10.0),
                              color: _current == index
                                  ? Colors.deepPurple
                                  : Colors.grey,
                            ),
                          );
                        }),
                      ),
                    ],
                  ),
                ),
              ),
            ],
          ),
        ),
      ),
猜猜我只是害怕什么:D

关于flutter - 如何将英雄小部件动画到另一个页面中轮播的第一个元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63376126/

相关文章:

javascript - 我如何在 firestore 字段的数组字段中循环并检索最后一个对其具有真实值(value)的结果?

random - 在flutter中计算两个随机数

flutter - 如何使用 Dart 扩展函数?

flutter - 如何删除 Flutter IconButton 大填充?

dart - Dart 'SdkAnalysisContext'未加载

Flutter - 找不到 Assets : lib/assets/images 的文件或变体

jquery - 是否有一个 Jquery 选项卡控件可以很好地处理多行选项卡?

c++ - QT - 将小部件添加到水平布局

android - 我可以在小部件中向 AdapterViewFlipper 添加垂直滑动手势吗?

listview - Flutter: Animation - 如何制作动画列表?