Flutter 如何构建具有不可滚动部分的 CustomScrollView

Pho*_*mer 5 flutter

我想要一个视图,顶部有一个不可滚动的部分,例如图像,例如底部有一个选项卡栏,我可以滚动到顶部以显示项目列表,并能够在项目列表内滚动。

为此,我使用了 CustomScrollView,用一个条子网格暂时代替了图像,一个条子应用程序栏用于选项卡栏,一个条子固定范围列表用于列表。

  Widget build(BuildContext context) {
return new Scaffold(
    body: new CustomScrollView(
      slivers: <Widget>[
        new SliverGrid(
          gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(
            childAspectRatio: 0.58,
            crossAxisCount: 1,

          ),
          delegate: new SliverChildBuilderDelegate(
                (BuildContext context, int index) {
              return new Container(

                  color: Colors.red,
                  child: new Container(
                    color: Colors.green,
                    child: new Text('IMG HERE'),
                  )
              );
            },
            childCount: 1,

          ),
        ),

        new SliverAppBar(
          title: new Text("title"),
          floating: false,
          pinned: true,
          primary: true,
          actions: <Widget>[
            new IconButton(
              icon: const Icon(Icons.arrow_upward),
              onPressed: () {
              },
            ),

          ],
          bottom: new TabBar(
            controller: _tabController,
            isScrollable: true,
            tabs: _bars,
          ),
        ),

        new SliverFixedExtentList(
          itemExtent: 100.0,
          delegate: new SliverChildBuilderDelegate(
                (BuildContext context, int index) {
              return new Container(
                alignment: Alignment.center,
                color: Colors.lightGreen[100 * (index % 9)],
                child: new Text('list item $index'),
              );
            },
          ),
        ),
      ],
    )
);
Run Code Online (Sandbox Code Playgroud)

}

但我有 3 个问题:

  1. 我不知道如何使这里的 slivergrid 的 sliver 不可滚动。
  2. 我不知道如何使 appBar 在启动时准确放置在屏幕底部。
  3. 当应用栏到达顶部时,列表会跳转一些项目,我的列表有问题,它似乎代表了 sliverGrid 元素的大小。

谢谢

Mαπ*_*π.0 1

我已经尝试过你的代码,似乎缺少一些重要部分。我看不到_tabControllerand后面的代码是什么_bars,所以我只是制作了自己的_tabControllerand _bars。我已经运行了它,这就是我到目前为止所得到的:

启动时: 在此输入图像描述

浏览直至AppBar到达顶部。 在此输入图像描述

因此,出于演示目的,我对您的代码进行了一些更改:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage>
    with SingleTickerProviderStateMixin {
  TabController _tabController;
  List<Widget> _bars = [
    Tab(icon: Icon(Icons.image)),
    Tab(icon: Icon(Icons.image)),
  ];
  int _selectedIndex = 0;

  @override
  void initState() {
    super.initState();
    _tabController = TabController(length: _bars.length, vsync: this);
    _tabController.addListener(() {
      setState(() {
        _selectedIndex = _tabController.index;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
        body: new CustomScrollView(
      slivers: <Widget>[
        new SliverGrid(
          gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(
            childAspectRatio: .69,
            crossAxisCount: 1,
          ),
          delegate: new SliverChildBuilderDelegate(
            (BuildContext context, int index) {
              return SafeArea(
                child: new Container(
                  color: Colors.green,
                  child: new Text('IMG HERE'),
                ),
              );
            },
            childCount: 1,
          ),
        ),
        new SliverAppBar(
          title: new Text("title"),
          floating: false,
          pinned: true,
          primary: true,
          actions: <Widget>[
            new IconButton(
              icon: const Icon(Icons.arrow_upward),
              onPressed: () {},
            ),
          ],
          bottom: new TabBar(
            controller: _tabController,
            isScrollable: true,
            tabs: _bars,
          ),
        ),
        new SliverFixedExtentList(
          itemExtent: 100.0,
          delegate: new SliverChildBuilderDelegate(
            (BuildContext context, int index) {
              return new Container(
                alignment: Alignment.center,
                color: Colors.lightGreen[100 * (index % 9)],
                child: new Text('list item $index'),
              );
            },
          ),
        ),
      ],
    ));
  }
}
Run Code Online (Sandbox Code Playgroud)

这是输出:

在此输入图像描述

正如你所看到的,我已经尝试了 的值,childAspectRatio以便你可以默认设置屏幕底部的 AppBar`,这就是我理解你的问题 2 的方式。

对于问题 3,您的代码似乎运行良好。我能够正确地看到从 0 开始的升序列表项已正确排序。

对于第一个问题,我很困惑你希望它如何发生。您不希望SliverGrid可以滚动,但您希望AppBar滚动后 位于屏幕顶部。我想在这一部分提供更多背景信息可以让每个人都清楚。