6

我试图从早期的材料设计规范(打开动画演示)中重现以下示例:

谷歌笔记

到目前为止,我能够产生滚动效果,但内容的重叠仍然缺失。我不知道如何正确地做到这一点。

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')
            ),
          ),
        ],
      ),
    );
  }
}
4

2 回答 2

2

我设法获得了这个功能,使用ScrollController和几个技巧:

演示 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()蓝色容器不重叠,我只是将它的第一个子元素设置为SizedBox具有所需的高度属性。

请注意,我使用的是修改后的Stack类。那是为了让堆栈中的第一个小部件(蓝色容器)检测压力,所以它适合我的用途;不幸的是,此时默认小部件存在问题,您可以通过https://github.com/flutter/flutter/issues/18450Stack阅读有关它的更多信息。

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

于 2020-07-16T01:43:19.687 回答
1

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

flutter - 在灵活空间中使用重叠内容滚动应用栏

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);
  }
}

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

于 2019-05-27T12:20:53.690 回答