Allow GridView to overlap SliverAppBar

后端 未结 2 927
无人共我
无人共我 2021-01-05 11:40

I am trying to reproduce the following example from the earlier Material design specifications (open for animated demo):

Until now I was able to produce the

相关标签:
2条回答
  • 2021-01-05 12:04

    I had the same problem and could not solve it with slivers. This example from another stackoverflow question solved my problem.

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

    Change the list to a grid and its what you want

    0 讨论(0)
  • 2021-01-05 12:26

    I managed to get this functionality, using the ScrollController and a couple of tricks:

    Here's the code:

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

    To make the Feed() not overlap the blue container, I simply made the first child of it a SizedBox with the required height property.

    Note that I am using a modified Stack class. That is in order to let the first Widget in the stack (the blue container) to detect presses, so it will fit my uses; unfortunately at this point the default Stack widget has an issue with that, you can read more about it over https://github.com/flutter/flutter/issues/18450.

    The StackWithAllChildrenReceiveEvents code can be found over https://github.com/flutter/flutter/issues/18450#issuecomment-575447316.

    0 讨论(0)
提交回复
热议问题