我有一堆这样放置的容器:

enter image description here

我想水平滚动它们,并相应地将该容器带到前面,即当向右滚动时,将蓝色的带到前面,当向左滚动时,将黄色的带到前面.

Something like this but a scroll instead of clicks: enter image description here

我试着使用带有水平滚动的SingleChildScrollView,但不出所料,它不起作用.我try 的代码是:

SingleChildScrollView(
                scrollDirection: Axis.horizontal,
                child: Stack(
                  clipBehavior: Clip.none,
                  children: [
                    Container(),
                    Positioned(
                      top: 145.h,
                      left: 100.w,
                      height: 300.h,
                      width: 250.w,
                      child: ElevatedButton(
                        onPressed: () {},
                        style: ElevatedButton.styleFrom(
                          backgroundColor: Colors.blue,
                          elevation: 3.h,
                          shape: RoundedRectangleBorder(
                            borderRadius:
                                BorderRadius.circular(5.r), //// <-- Radius
                          ),
                        ),
                        child: Text("pp"),
                      ),
                    ),
                    Positioned(
                      top: 145.h,
                      left: 20.w,
                      height: 300.h,
                      width: 250.w,
                      child: ElevatedButton(
                        onPressed: () {},
                        style: ElevatedButton.styleFrom(
                          backgroundColor: Colors.yellow,
                          elevation: 3.h,
                          shape: RoundedRectangleBorder(
                            borderRadius:
                                BorderRadius.circular(5.r), //// <-- Radius
                          ),
                        ),
                        child: Text("Demo 3"),
                      ),
                    ),
                    Positioned(
                      top: 145.h,
                      left: 60.w,
                      height: 300.h,
                      width: 250.w,
                      child: ElevatedButton(
                        onPressed: () {},
                        style: ElevatedButton.styleFrom(
                          backgroundColor: Colors.red,
                          elevation: 3.h,
                          shape: RoundedRectangleBorder(
                            borderRadius:
                                BorderRadius.circular(5.r), //// <-- Radius
                          ),
                        ),
                        child: Text(
                          "Demo 2",
                          style: TextStyle(
                            fontSize: 20.sp,
                            fontWeight: FontWeight.w500,
                          ),
                        ),
                      ),
                    ),
                    Positioned(
                      top: 145.h,
                      left: 60.w,
                      height: 300.h,
                      width: 250.w,
                      child: ElevatedButton(
                        onPressed: () {},
                        style: ElevatedButton.styleFrom(
                          backgroundColor: Colors.red,
                          elevation: 3.h,
                          shape: RoundedRectangleBorder(
                            borderRadius:
                                BorderRadius.circular(5.r), //// <-- Radius
                          ),
                        ),
                        child: Text(
                          "Demo",
                          style: TextStyle(
                            fontSize: 20.sp,
                            fontWeight: FontWeight.w500,
                          ),
                        ),
                      ),
                    ),
                  ],
                ),

我知道的一个解决方案是使用墨水井,并使用ONTAP/ElevatedButton onPress来调整定位并将相应的容器放在前面,但用户体验不会像水平滚动一样好.

我还try 使用带有RotatedBox的ListWheelScrollView来模拟水平滚动,但效果不够好.

任何在这方面的帮助都将不胜感激!

推荐答案

嗯,我找到了一个PageView.builder而不是Stack的解决方案,这非常接近你想要的结果,

我们称之为 carousel 的主页:

import 'dart:math' as math;


class HomeScreen extends StatefulWidget {
  const HomeScreen({Key? key}) : super(key: key);

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  List items = List.generate(
      20,
      (index) => Color((math.Random().nextDouble() * 0xFFFFFF).toInt())
          .withOpacity(1.0)); // list for test

  late PageController _pageController; // controller of pageview

  @override
  void initState() {
    _pageController = PageController(initialPage: 0, viewportFraction: 0.8);
    super.initState();
  }

  @override
  void dispose() {
    _pageController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return ScrollConfiguration(
      behavior: CustomScrollBehavior(),
      child: Padding(
        padding: const EdgeInsets.all(20.0),
        child: CardCarousel(pageController: _pageController, items: items),
      ),
    );
  }
}

这是 carousel :

class CardCarousel extends StatelessWidget {
  final PageController pageController;
  final List items;

  const CardCarousel(
      {super.key, required this.pageController, required this.items});

  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.center,
      children: <Widget>[
        SizedBox(
          height: 400.0,
          width: 300,
          child: PageView.builder(
            controller: pageController,
            itemCount: items.length,
            itemBuilder: (BuildContext context, int index) {
              return _cardBuilder(context, index);
            },
          ),
        ),
      ],
    );
  }

  _cardBuilder(BuildContext context, int index) {
    var item = items[index];
    return AnimatedBuilder(
      animation: pageController,
      builder: (context, child) {
        double value = 1;
        if (pageController.position.haveDimensions) {
          value = (pageController.page! - index);
          value = (1 - (value.abs() * 0.25)).clamp(0.0, 1.0);
          // you can change these values to change the size
          // transformation that i found it
        }

        return Center(
          child: Container(
            color: item,
            // change animation right here
            // the value for transform have got above
            height: Curves.easeInOut.transform(value) * 400.0,
            child: child,
          ),
        );
      },
    );
  }
}

我希望这对你有帮助, 结果是这样的:

result

Flutter相关问答推荐

如何更新文本字段的基础上的选定下拉菜单?

修复容器`Text`和容器表单之间的重叠

try 在Flutter应用程序中传递变量到FirebaseFirestore Where子句

为什么在setState之后Ffltter Pageview重置为第0页

我怎样才能在Ffltter中显示html布局链接?

try 使用fl_Chart of Ffltter,但在导入它时遇到以下错误:Error:';TextScaler';is;t a type

将记录/元组用作SplayTreeMap中的键

如何使 dart 函数变得通用?

如何更改Flutter 中文本的混合模式?

Flutter中有没有办法区分鼠标左右平移?

为 flutter app/firebase 保存 chatgpt api-key 的正确方法是什么

围绕父组件旋转位置组件

Flutter - firebase_auth_web 5.4.0 依赖于 intl ^0.17.0 但我必须使用更高版本 (intl ^0.18.0)

setState 方法有时有效,有时无效

如何建立最近的文件列表?

如何使用 Rrect 或类似工具在 flutter 中绘制梯形线?

Flutter - 使用 pin 进行身份验证

Flutter 活跃的互联网连接

Firebase Cloud Messaging (Flutter):订阅主题时出现错误消息

Flutter:滚动一个ListWheelScrollView,无法获取选中项的状态