0

当嵌套的 CustomScrollView 的收缩包装设置为 true 时,我无法折叠子条。

如何滚动 customScrollViews 并使子 customScrollView 可折叠到最小高度。

这是现场演示

我的最终目标是制作带有滚动动画的堆栈卡列表视图

还有其他解决方案吗?或者有办法解决这个问题?

给我一些建议大师:)

class AnimationTest extends StatefulWidget {
  @override
  _AnimationTestState createState() => _AnimationTestState();
}

class _AnimationTestState extends State<AnimationTest>
    with WidgetsBindingObserver {
  @override
  void initState() {
    WidgetsBinding.instance.addObserver(this);
    super.initState();
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    print(state.toString());
  }

  @override
  Widget build(BuildContext context) {
    const double goldenRatio = 1.618;
    final Size displaySize = MediaQuery.of(context).size;
    final double minCardHeight = 24;
    final double maxCardHeight = 80;
    final List<Color> colors = Colors.primaries;
    List<Color> _colors = List();
    _colors.addAll(colors);
    _colors.addAll(colors);
    print(_colors.length);

    return Scaffold(
      body: Container(
        color: Colors.white,
        padding: EdgeInsets.only(top: 40),
        alignment: AlignmentDirectional.center,
        child: CustomScrollView(
          slivers: <Widget>[
            SliverList(
              delegate: SliverChildListDelegate([
                Column(
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: <Widget>[
                    CreditCard(),
                    Container(
                      width: displaySize.width * 0.85,
                      height: minCardHeight * _colors.length,
                      alignment: AlignmentDirectional.bottomCenter,
                      margin: EdgeInsets.all(0),
                      padding: EdgeInsets.all(0),
                      decoration: BoxDecoration(
                        borderRadius: BorderRadius.circular(8),
                        color: Colors.white,
                      ),
                      child: StackedList(
                        minCardHeight: minCardHeight,
                        maxCardHeight: maxCardHeight,
                        colors: _colors,
                      ),
                    )
                  ],
                ),
              ]),
            )
          ],
        ),
      ),
    );
  }
}

class StackedList extends StatefulWidget {
  final double minCardHeight;
  final double maxCardHeight;
  final List<Color> colors;
  StackedList({
    Key key,
    this.colors,
    this.maxCardHeight,
    this.minCardHeight,
  }) : super(key: key);
  @override
  _StackedListState createState() => _StackedListState();
}

class _StackedListState extends State<StackedList> {
  @override
  Widget build(BuildContext context) {
    return CustomScrollView(
      physics: AlwaysScrollableScrollPhysics(),
      shrinkWrap: true,
      slivers: <Widget>[
        ...widget.colors
            .map(
              (color) => StackedListChild(
                minHeight: widget.minCardHeight,
                maxHeight: widget.maxCardHeight,
                floating: false,
                pinned: true,
                child: getCard(
                  cardId: widget.colors.indexOf(color).toString(),
                  color: color,
                ),
              ),
            )
            .toList(),
        SliverToBoxAdapter(
            child: Container(
          height: MediaQuery.of(context).size.height,
          alignment: Alignment.center,
        ))
      ],
    );
  }

  Widget getCard({String cardId, Color color}) {
    const double cardWidth = 300;
    const double cardHeight = 370;
    return Hero(
      tag: cardId,
      child: Material(
        elevation: 3,
        color: Colors.white,
        child: InkWell(
          onTap: () => navigateToCardDetail(cardId: cardId, color: color),
          child: Container(
            width: cardWidth,
            height: cardHeight,
            color: color,
            // decoration: BoxDecoration(
            //   borderRadius: BorderRadius.only(
            //     topLeft: Radius.circular(8),
            //     topRight: Radius.circular(8),
            //   ),
            //   color: color,
            // ),
          ),
        ),
      ),
    );
  }

  navigateToCardDetail({String cardId, Color color}) {
    var route = PageRouteBuilder(
      pageBuilder: (context, animation, secondAnimation) =>
          SecondPage(cardId: cardId, color: color),
      barrierDismissible: true,
      transitionDuration: const Duration(milliseconds: 300),
      transitionsBuilder: (context, animation, secondaryAnimation, child) {
        // var begin = Offset(0.0, 1.0);
        // var end = Offset.zero;
        // var curve = Curves.fastOutSlowIn;

        // var tween =
        //     Tween(begin: begin, end: end).chain(CurveTween(curve: curve));

        return FadeTransition(
          //opacity: animation,
          //position: animation.drive(tween),
          opacity: animation,
          child: child,
        );
      },
    );
    Navigator.of(context).push(route);
  }
}

class StackedListChild extends StatelessWidget {
  final double minHeight;
  final double maxHeight;
  final bool pinned;
  final bool floating;
  final Widget child;

  SliverPersistentHeaderDelegate get _delegate => _StackedListDelegate(
      minHeight: minHeight, maxHeight: maxHeight, child: child);

  const StackedListChild({
    Key key,
    @required this.minHeight,
    @required this.maxHeight,
    @required this.child,
    this.pinned = false,
    this.floating = false,
  })  : assert(child != null),
        assert(minHeight != null),
        assert(maxHeight != null),
        assert(pinned != null),
        assert(floating != null),
        super(key: key);

  @override
  Widget build(BuildContext context) => SliverPersistentHeader(
      key: key, pinned: pinned, floating: floating, delegate: _delegate);
}

class _StackedListDelegate extends SliverPersistentHeaderDelegate {
  final double minHeight;
  final double maxHeight;
  final Widget child;

  _StackedListDelegate({
    @required this.minHeight,
    @required this.maxHeight,
    @required this.child,
  });

  @override
  double get minExtent => minHeight;

  @override
  double get maxExtent => math.max(maxHeight, minHeight);

  @override
  Widget build(
      BuildContext context, double shrinkOffset, bool overlapsContent) {
    return new SizedBox.expand(child: child);
  }

  @override
  bool shouldRebuild(_StackedListDelegate oldDelegate) {
    return maxHeight != oldDelegate.maxHeight ||
        minHeight != oldDelegate.minHeight ||
        child != oldDelegate.child;
  }
}
4

1 回答 1

0

将 CustomScrollView 放在另一个 CustomScrollView 中是一种反模式。

您可以使用NestedScrollView包装您的 CustomScrollView 以平滑滚动..

于 2020-02-12T06:33:38.057 回答