允许GridView与SliverAppBar重叠

时间:2018-12-10 16:18:15

标签: flutter flutter-sliver

我正尝试从早期的Material Design规范(为动画演示开放)中复制以下示例:

Google Notes

直到现在我仍然可以产生滚动效果,但是内容的重叠仍然缺失。我找不到正确的方法。

import 'package:flutter/material.dart';

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CustomScrollView(
        slivers: <Widget>[
          SliverAppBar(
            title: Text('Title'),
            expandedHeight: 200.0,
            primary: true,
            pinned: true,
          ),
          SliverFixedExtentList(
            itemExtent: 30.0,
            delegate: SliverChildBuilderDelegate(
              (BuildContext context, int i) => Text('Item $i')
            ),
          ),
        ],
      ),
    );
  }
}

2 个答案:

答案 0 :(得分:1)

我使用ScrollController和一些技巧来获得此功能:

Demo GIF

这是代码:

  ScrollController _scrollController;
  static const kHeaderHeight = 235.0;

  double get _headerOffset {
    if (_scrollController.hasClients) if (_scrollController.offset > kHeaderHeight)
      return -1 * (kHeaderHeight + 50.0);
    else
      return -1 * (_scrollController.offset * 1.5);

    return 0.0;
  }

  @override
  void initState() {
    super.initState();

    _scrollController = ScrollController()..addListener(() => setState(() {}));
  }

  @override
  Widget build(BuildContext context) {
    super.build(context);
    return StackWithAllChildrenReceiveEvents(
      alignment: AlignmentDirectional.topCenter,
      children: [
        Positioned(
          top: _headerOffset,
          child: Container(
            height: kHeaderHeight,
            width: MediaQuery.of(context).size.width,
            color: Colors.blue,
          ),
        ),
        Padding(
          padding: EdgeInsets.only(left: 20.0, right: 20.0),
          child: Feed(controller: _scrollController, headerHeight: kHeaderHeight),
        ),
      ],
    );
  }

要使Feed()不与蓝色容器重叠,我只需将其第一个孩子作为具有所需height属性的SizedBox

请注意,我正在使用经过修改的Stack类。这是为了让堆栈中的第一个Widget(蓝色容器)能够检测印刷机,因此适合我的用途。不幸的是,此时默认的Stack小部件存在问题,您可以在https://github.com/flutter/flutter/issues/18450上阅读有关它的更多信息。

可以在https://github.com/flutter/flutter/issues/18450#issuecomment-575447316上找到StackWithAllChildrenReceiveEvents代码。

答案 1 :(得分:0)

我遇到了同样的问题,无法用条子解决。这个来自另一个stackoverflow问题的示例解决了我的问题。

flutter - App bar scrolling with overlapping content in Flexible space

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Scroll demo',
      home: new Scaffold(
        appBar: new AppBar(elevation: 0.0),
        body: new CustomScroll(),
      ),
    );
  }
}

class CustomScroll extends StatefulWidget {
  @override
  State createState() => new CustomScrollState();
}

class CustomScrollState extends State<CustomScroll> {
  ScrollController scrollController;
  double offset = 0.0;
  static const double kEffectHeight = 100.0;

  @override
  Widget build(BuildContext context) {
    return new Stack(
      alignment: AlignmentDirectional.topCenter,
      children: <Widget> [
        new Container(
          color: Colors.blue,
          height: (kEffectHeight - offset * 0.5).clamp(0.0, kEffectHeight),
        ),
        new Positioned(
          child: new Container(
            width: 200.0,
            child: new ListView.builder(
              itemCount: 100,
              itemBuilder: buildListItem,
              controller: scrollController,
            ),
          ),
        ),
      ],
    );
  }

  Widget buildListItem(BuildContext context, int index) {
    return new Container(
      color: Colors.white,
      child: new Text('Item $index')
    );
  }

  void updateOffset() {
    setState(() {
      offset = scrollController.offset;
    }); 
  }

  @override
  void initState() {
    super.initState();
    scrollController = new ScrollController();
    scrollController.addListener(updateOffset);
  }

  @override
  void dispose() {
    super.dispose();
    scrollController.removeListener(updateOffset);
  }
}

将列表更改为网格及其所需的内容