【问题标题】:How to make ListWheelScrollView horizontal如何使 ListWheelScrollView 水平
【发布时间】:2019-03-05 19:45:10
【问题描述】:

我正在尝试使用一个水平的ListView 小部件来放大中心项目。我尝试使用普通的ListView,但我无法放大中心项目。然后在搜索颤振文档时,我遇到了ListWheelScrollView,但不幸的是,它似乎不支持水平子布局。所以基本上我想创建一个水平的ListView,中心项目放大。如果有人至少能指出我正确的方向,我将不胜感激。谢谢

【问题讨论】:

    标签: android listview dart flutter


    【解决方案1】:

    复制这段代码并使用它

    import 'package:flutter/material.dart';
    import 'package:flutter/rendering.dart';
    
    class ListWheelScrollViewX extends StatelessWidget {
      final Axis scrollDirection;
      final List<Widget>? children;
      final ScrollController? controller;
      final ScrollPhysics? physics;
      final double diameterRatio;
      final double perspective;
      final double offAxisFraction;
      final bool useMagnifier;
      final double magnification;
      final double overAndUnderCenterOpacity;
      final double itemExtent;
      final double squeeze;
      final ValueChanged<int>? onSelectedItemChanged;
      final bool renderChildrenOutsideViewport;
      final ListWheelChildDelegate? childDelegate;
      final Clip clipBehavior;
    
      const ListWheelScrollViewX({
        Key? key,
        this.scrollDirection = Axis.vertical,
        this.controller,
        this.physics,
        this.diameterRatio = RenderListWheelViewport.defaultDiameterRatio,
        this.perspective = RenderListWheelViewport.defaultPerspective,
        this.offAxisFraction = 0.0,
        this.useMagnifier = false,
        this.magnification = 1.0,
        this.overAndUnderCenterOpacity = 1.0,
        required this.itemExtent,
        this.squeeze = 1.0,
        this.onSelectedItemChanged,
        this.renderChildrenOutsideViewport = false,
        this.clipBehavior = Clip.hardEdge,
        required this.children,
      })  : childDelegate = null,
            super(key: key);
    
      const ListWheelScrollViewX.useDelegate({
        Key? key,
        this.scrollDirection = Axis.vertical,
        this.controller,
        this.physics,
        this.diameterRatio = RenderListWheelViewport.defaultDiameterRatio,
        this.perspective = RenderListWheelViewport.defaultPerspective,
        this.offAxisFraction = 0.0,
        this.useMagnifier = false,
        this.magnification = 1.0,
        this.overAndUnderCenterOpacity = 1.0,
        required this.itemExtent,
        this.squeeze = 1.0,
        this.onSelectedItemChanged,
        this.renderChildrenOutsideViewport = false,
        this.clipBehavior = Clip.hardEdge,
        required this.childDelegate,
      })  : children = null,
            super(key: key);
    
      @override
      Widget build(BuildContext context) {
        final _childDelegate = children != null
            ? ListWheelChildListDelegate(
                children: children!.map((child) {
                return RotatedBox(
                  quarterTurns: scrollDirection == Axis.horizontal ? 1 : 0,
                  child: child,
                );
              }).toList())
            : ListWheelChildBuilderDelegate(
                builder: (context, index) {
                  return RotatedBox(
                    quarterTurns: scrollDirection == Axis.horizontal ? 1 : 0,
                    child: childDelegate!.build(context, index),
                  );
                },
              );
    
        return RotatedBox(
          quarterTurns: scrollDirection == Axis.horizontal ? 3 : 0,
          child: ListWheelScrollView.useDelegate(
            controller: controller,
            physics: FixedExtentScrollPhysics(),
            diameterRatio: diameterRatio,
            perspective: perspective,
            offAxisFraction: offAxisFraction,
            useMagnifier: useMagnifier,
            magnification: magnification,
            overAndUnderCenterOpacity: overAndUnderCenterOpacity,
            itemExtent: itemExtent,
            squeeze: squeeze,
            onSelectedItemChanged: onSelectedItemChanged,
            renderChildrenOutsideViewport: renderChildrenOutsideViewport,
            clipBehavior: clipBehavior,
            childDelegate: _childDelegate,
          ),
        );
      }
    }
    

    例子

    ListWheelScrollViewX(
        scrollDirection: Axis.horizontal,
        itemExtent: 120,
        children:...
    ),
    

    参考 list_wheel_scroll_view_x

    变化: 转换为空安全

    【讨论】:

      【解决方案2】:

      您可以通过将内置 ListWheelScrollView 与 Rotated Box 配对来执行此操作。这是一种可行的技巧。

      RotatedBox(
         quarterTurns: -1,
         child: ListWheelScrollView(
         onSelectedItemChanged: (x) {
                        setState(() {
                          selected = x;
                        });
         },
         controller: _scrollController,
         children: List.generate(
                          itemCount,
                          (x) => RotatedBox(
                              quarterTurns: 1,
                              child: AnimatedContainer(
                                  duration: Duration(milliseconds: 400),
                                  width: x == selected ? 60 : 50,
                                  height: x == selected ? 60 : 50,
                                  alignment: Alignment.center,
                                  decoration: BoxDecoration(
                                      color: x == selected ? Colors.red : Colors.grey,
                                      shape: BoxShape.circle),
                                  child: Text('$x')))),
                      itemExtent: itemWidth,
                    )),
          );
      

      Full source Code here

      我建议在解决 this issue 之前使用这种方法

      这是输出

      【讨论】:

        【解决方案3】:
        Transform.rotate(
          angle: -math.pi / 2,
          child: ListWheelScrollView()
        }
        

        使用 Transform.rotate

        【讨论】:

          【解决方案4】:

          编辑: 我已经基于此发布了包。

          pub.dev/packages/list_wheel_scroll_view_x

          这是我的解决方法。

          import 'package:flutter/material.dart';
          import 'package:flutter/rendering.dart';
          
          class ListWheelScrollViewX extends StatelessWidget {
            final Widget Function(BuildContext, int) builder;
            final Axis scrollDirection;
            final FixedExtentScrollController controller;
            final double itemExtent;
            final double diameterRatio;
            final void Function(int) onSelectedItemChanged;
            const ListWheelScrollViewX({
              Key key,
              @required this.builder,
              @required this.itemExtent,
              this.controller,
              this.onSelectedItemChanged,
              this.scrollDirection = Axis.vertical,
              this.diameterRatio = 100000,
            }) : super(key: key);
          
            @override
            Widget build(BuildContext context) {
              return RotatedBox(
                quarterTurns: scrollDirection == Axis.horizontal ? 3 : 0,
                child: ListWheelScrollView.useDelegate(
                  onSelectedItemChanged: onSelectedItemChanged,
                  controller: controller,
                  itemExtent: itemExtent,
                  diameterRatio: diameterRatio,
                  physics: FixedExtentScrollPhysics(),
                  childDelegate: ListWheelChildBuilderDelegate(
                    builder: (context, index) {
                      return RotatedBox(
                        quarterTurns: scrollDirection == Axis.horizontal ? 1 : 0,
                        child: builder(context, index),
                      );
                    },
                  ),
                ),
              );
            }
          }
          

          【讨论】:

          • 我正在寻找类似的东西,想知道您是否有实现上述代码的示例?
          • @Vlad 您可以像使用 ListWheelScrollView 小部件一样使用它。但我添加了scrollDirection,您可以将其设置为 Axis.horizo​​ntal
          • 顺便说一句,我已经把它推送到包pub.dev/packages/list_wheel_scroll_view_x
          【解决方案5】:

          您可以在ListViewPageView 以及NotificationListener 的帮助下完成这项工作。 以下是我的相同代码 -

          import 'dart:math';
          import 'package:flutter/material.dart';        
          const SCALE_FRACTION = 0.9;
                  const FULL_SCALE = 1.0;
                  final PAGER_HEIGHT = SizeConfig.screenHeight*0.32;
                  const PAGER_WIDTH = double.infinity;
          
                  class PaymentWidget extends StatefulWidget {
                    @override
                    State<StatefulWidget> createState() => _PaymentState();
                  }
          
                  class _PaymentState extends State<PaymentWidget> {
                    double viewPortFraction = 0.9;
                    int currentPage = 1;
                    double page = 2.0;
          
                    PageController pageController;
          
                    final List<String> _cardsImages = ['image/path1', 'image/path2',
                      'image/path3', 'image/path4'];
          
                    @override
                    void initState() {
                      pageController = PageController(
                          initialPage: currentPage, viewportFraction: viewPortFraction);
                      super.initState();
                    }
          
                    @override
                    Widget build(BuildContext context) {
                      return Scaffold(
                        appBar: null,
                        body: _creditCardsList()
                  );
                  }
          
                 Widget _creditCardsList() {
                      return ListView(
                        shrinkWrap: true,
                            children: <Widget>[
                              Container(
                                height: PAGER_HEIGHT,
                                child: NotificationListener<ScrollNotification>(
                                  onNotification: (ScrollNotification notification) {
                                    if (notification is ScrollUpdateNotification) {
                                      setState(() {
                                        page = pageController.page;
                                      });
                                    }
                                  },
                                  child: PageView.builder(
                                    onPageChanged: (pos) {
                                      setState(() {
                                        currentPage = pos;
                                      });
                                    },
                                    physics: BouncingScrollPhysics(),
                                    controller: pageController,
                                    itemCount: _cardsImages.length,
                                    itemBuilder: (context, index) {
                                      final scale =
                                      max(SCALE_FRACTION, (FULL_SCALE - (index - page).abs()) + viewPortFraction);
                                      return CreditCardTile(
                                          _cardsImages[index], scale);
                                    },
                                  ),
                                ),
                              ),
                            ],
                      );
          
                    }
          
                  Widget CreditCardTile(String image, double scale) {
                      return Align(
                        alignment: Alignment.bottomCenter,
                        child:Container(
                            height: PAGER_HEIGHT * scale,
                            width: PAGER_WIDTH * scale,
                            child: Card(
                              elevation: 5,
                              shadowColor: constColors.blueWhiteShade,
                              shape: RoundedRectangleBorder(
                                borderRadius: BorderRadius.circular(10.0)
                              ),
                              clipBehavior: Clip.antiAlias,
                              child: Image.asset(
                                image,
                                fit: BoxFit.cover,
                              ),
                            )
                        ) ,
                      );
          
                    }
          

          【讨论】:

            【解决方案6】:

            你可以使用这个flutter包https://pub.dev/packages/carousel_slider。 它也有一个非常有用的描述和几个样本来看看它的外观。而且它也兼容 dart 2.0。

            【讨论】:

            猜你喜欢
            • 2021-02-09
            • 2021-06-08
            • 2018-10-26
            • 2020-04-28
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-09-26
            • 2012-07-28
            相关资源
            最近更新 更多