返回

如何在鼠标悬停时缩放列表项,使其始终可见(Web 平台上的 Flutter)

发布时间:2022-08-07 01:44:24 341
# less# flutter# 容器

问题是这样描述的。

在网络环境中,我必须构建一个水平图像列表(如在 Netflix 中),当用户将鼠标光标放在元素上时,它应该会增加元素的大小。为了实现这一点,我使用堆栈(clipBehavior等于Clip.none)来呈现列表中的每个项目,当我检测到鼠标悬停事件时,我添加一个新容器(大于原始项目的大小)来绘制一个 AnimatedContainer里面会长出来填满它。

动画效果很好,但是容器被定位到列表中的下一个正确的项目,但是,我需要它在项目上方。

这是代码:

    import 'package:flutter/material.dart';

    void main() {

      runApp(const MyApp());

    }

    class MyApp extends StatelessWidget {

      const MyApp({Key? key}) : super(key: key);

      @override

      Widget build(BuildContext context) {

        return MaterialApp(

          title: 'Flutter Demo',

          theme: ThemeData(

            primarySwatch: Colors.blue,

          ),

          home: const MyHomePage(title: 'Flutter Demo Home Page'),

        );

      }

    }

    class MyHomePage extends StatefulWidget {

      const MyHomePage({Key? key, required this.title}) : super(key: key);

      final String title;

      @override

      State createState() => _MyHomePageState();

    }

    class _MyHomePageState extends State {

      final double zoomTargetHeight = 320;

      final double zoomTargetWidth = 500;

      final double zoomOriginalHeight = 225;

      final double zoomOriginalWidth = 400;

      double _zoomHeight = 225;

      double _zoomWidth = 400;

      @override

      Widget build(BuildContext context) {

        return Scaffold(

          appBar: AppBar(

            title: Text(widget.title),

          ),

          body: SingleChildScrollView(

            child: Column(

              children: [

                Image.network("https://source.unsplash.com/random/1600x900?cars"),

                Container(

                  color: Colors.black87,

                  child: Padding(

                    padding: const EdgeInsets.all(20.0),

                    child: Column(

                      crossAxisAlignment: CrossAxisAlignment.start,

                      children: [

                        const SizedBox(

                          height: 12,

                        ),

                        const Text(

                          "List of items",

                          style: TextStyle(color: Colors.white),

                        ),

                        const SizedBox(

                          height: 12,

                        ),

                        SizedBox(

                          height: 235,

                          child: ListView.separated(

                            clipBehavior: Clip.none,

                            scrollDirection: Axis.horizontal,

                            itemBuilder: (context, index) {

                              return buildCard(index);

                            },

                            separatorBuilder: (context, index) {

                              return const SizedBox(

                                width: 12,

                              );

                            },

                            itemCount: 10,

                          ),

                        ),

                        const SizedBox(

                          height: 200,

                        ),

                      ],

                    ),

                  ),

                ),

              ],

            ),

          ),

        );

      }

      Map _showZoom = {};

      Widget buildCard(int index) {

        Stack stack = Stack(

          clipBehavior: Clip.none,

          children: [

            MouseRegion(

              onEnter: (event) {

                setState(() {

                  _showZoom["$index"] = true;

                });

              },

              child: ClipRRect(

                borderRadius: BorderRadius.circular(20),

                child: Stack(

                  children: [

                    Image.network(

                        "https://source.unsplash.com/random/400x225?sig=$index&cars"),

                    Container(

                      color: Colors.black.withAlpha(100),

                      height: zoomOriginalHeight,

                      width: zoomOriginalWidth,

                    ),

                  ],

                ),

              ),

            ),

            if (_showZoom["$index"] != null && _showZoom["$index"]!)

              Positioned(

                left: (zoomOriginalWidth - zoomTargetWidth) / 2,

                top: (zoomOriginalHeight - zoomTargetHeight) / 2,

                child: MouseRegion(

                  onHover: (_) {

                    setState(() {

                      _zoomHeight = zoomTargetHeight;

                      _zoomWidth = zoomTargetWidth;

                    });

                  },

                  onExit: (event) {

                    setState(() {

                      _showZoom["$index"] = false;

                      _zoomHeight = zoomOriginalHeight;

                      _zoomWidth = zoomOriginalWidth;

                    });

                  },

                  child: SizedBox(

                    width: zoomTargetWidth,

                    height: zoomTargetHeight,

                    child: Center(

                      child: AnimatedContainer(

                        duration: const Duration(milliseconds: 400),

                        width: _zoomWidth,

                        height: _zoomHeight,

                        // color: Colors.green.withAlpha(100),

                        decoration: BoxDecoration(

                          borderRadius: BorderRadius.circular(20.0),

                          image: DecorationImage(

                            image: NetworkImage(

                                "https://source.unsplash.com/random/400x225?sig=$index&cars"),

                            fit: BoxFit.cover,

                          ),

                        ),

                      ),

                    ),

                  ),

                ),

              ),

          ],

        );

        return stack;

      }

    }

记住flutter config --enable-web

特别声明:以上内容(图片及文字)均为互联网收集或者用户上传发布,本站仅提供信息存储服务!如有侵权或有涉及法律问题请联系我们。
举报
评论区(2)
按点赞数排序
用户头像
下一篇
SQL从逗号分隔的信息导入数据库 2022-08-06 23:45:05