【问题标题】:How to make Column scrollable when overflowed but use expanded otherwise如何在溢出时使列可滚动,但在其他情况下使用扩展
【发布时间】:2021-11-14 13:38:50
【问题描述】:

我正在尝试实现这样一种效果,即在侧边栏的顶端有可展开的内容,而在侧边栏的底部有其他链接。当顶部的内容扩展到需要滚动的点时,底部的链接应该在同一个视图中滚动。

这是我想要做的一个例子,除了它不滚动。如果我在列周围包裹一个可滚动的视图,那将不适用于将底部链接保持在底部所需的间隔或扩展:

import 'package:flutter/material.dart';

const Color darkBlue = Color.fromARGB(255, 18, 32, 47);

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark().copyWith(
        scaffoldBackgroundColor: darkBlue,
      ),
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: Center(
          child: MyWidget(),
        ),
      ),
    );
  }
}

class MyWidget extends StatefulWidget {
  @override
  State<MyWidget> createState() {
    return MyWidgetState();
  }
}

class MyWidgetState extends State<MyWidget> {
  List<int> items = [1];

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            IconButton(
              icon: const Icon(Icons.add),
              onPressed: () {
                setState(() {
                  items.add(items.last + 1);
                });
              },
            ),
            IconButton(
              icon: const Icon(Icons.delete),
              onPressed: () {
                setState(() {
                  if (items.length != 1) items.removeLast();
                });
              },
            ),
          ],
        ),
        for (final item in items)
          MyAnimatedWidget(
            child: SizedBox(
              height: 200,
              child: Center(
                child: Text('Top content item $item'),
              ),
            ),
          ),
        Spacer(),
        Container(
          alignment: Alignment.center,
          decoration: BoxDecoration(border: Border.all()),
          height: 200,
          child: Text('Bottom content'),
        )
      ],
    );
  }
}

class MyAnimatedWidget extends StatefulWidget {
  final Widget? child;

  const MyAnimatedWidget({this.child, Key? key}) : super(key: key);

  @override
  State<MyAnimatedWidget> createState() {
    return MyAnimatedWidgetState();
  }
}

class MyAnimatedWidgetState extends State<MyAnimatedWidget>
    with SingleTickerProviderStateMixin {
  late AnimationController controller;

  @override
  initState() {
    controller = AnimationController(
        value: 0, duration: const Duration(seconds: 1), vsync: this);
    controller.animateTo(1, curve: Curves.linear);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
        animation: controller,
        builder: (context, child) {
          return SizedBox(height: 200 * controller.value, child: widget.child);
        });
  }
}

我尝试使用全局键来获取垫片的大小,并在重建后检测垫片的大小是否为 0,如果是,则将整个小部件重新构建为列表视图(不带垫片)的一列。在这种情况下,您还需要监听大小是否缩小并且需要再次成为列,这似乎使性能明显变差,在列/列表视图之间切换时保存状态很棘手,而且似乎不是解决问题的最佳方法。

有什么想法吗?

【问题讨论】:

  • 你可能想看看SliverAppBar
  • SliverAppBar 很有趣,感谢您的提示 - 但是我无法找到 Sliver 的组合以添加到 CustomScrollView 中,这将为视图底部的小部件实现类似的效果。

标签: flutter listview flutter-layout flutter-animation


【解决方案1】:

尝试在没有动画的情况下实现我刚刚创建的这个解决方案。是顶部的可滚动区域和持久的页脚。

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark().copyWith(
        scaffoldBackgroundColor: darkBlue,
      ),
      home: SafeArea(
        child: Scaffold(
          appBar: AppBar(
            title: Text("My AppBar"),
          ),
          body: Column(
            children: [
              Expanded(
                child: SingleChildScrollView(
                  child: Column(
                    children: [

                      // Your scrollable widgets here

                      Container(
                        height: 100,
                        color: Colors.green,
                      ),
                      Container(
                        height: 100,
                        color: Colors.blue,
                      ),
                      Container(
                        height: 100,
                        color: Colors.red,
                      ),
                    ],
                  ),
                ),
              ),
              Container(
                child: Text(
                  'Your footer',
                ),
                color: Colors.blueGrey,
                height: 200,
                width: double.infinity,
              )
            ],
          ),
        ),
      ),
    );
  }
}

【讨论】:

  • 您好,感谢您的回答,不幸的是,我正在专门寻找一种方法来避免这种情况,因为页脚将占据移动设备屏幕的很大一部分,并且使用如果需要,请休息。
猜你喜欢
  • 2011-09-29
  • 1970-01-01
  • 2020-09-07
  • 2018-03-21
  • 1970-01-01
  • 2021-09-24
  • 1970-01-01
  • 1970-01-01
  • 2023-02-05
相关资源
最近更新 更多