Search code examples
flutterflutter-sliver

Scroll background container in Flutter


I am trying to build scrollable screen, where brown background Container must scroll with List of elements when black container near this container. How can I do it? I thought about Positioned, but I can't build items above SliverAppbar even if I build it in different Stack.

May I build body above SliverAppbar or how can I realise this?

return Scaffold(
  body: Stack(
    children: [
      Container(
        height: MediaQuery.of(context).size.height * 0.45,
        decoration: const BoxDecoration(
          color: AppColors.mainBrown,
          borderRadius: BorderRadius.vertical(bottom: Radius.circular(30)),
        ),
      ),
      CustomScrollView(
        slivers: [
          const SliverAppBar(
            expandedHeight: 70,
            backgroundColor: Colors.transparent,
            elevation: 0,
            shadowColor: Colors.transparent,
            titleSpacing: 22,
            title: Text('AppBar'),
          ),
          SliverPadding(
            padding: const EdgeInsets.symmetric(horizontal: 30),
            sliver: SliverList(
              delegate: SliverChildListDelegate([
                Card(
                  child: Container(
                    color: Colors.brown,
                    height: 200,
                  ),
                ),
                Card(
                  child: Container(
                    color: Colors.yellow,
                    height: 250,
                  ),
                ),
                Card(
                  child: Container(
                    color: Colors.black,
                    height: 300,
                  ),
                ),
                Card(
                  child: Container(
                    color: Colors.red,
                    height: 50,
                  ),
                ),
                Card(
                  child: Container(
                    color: Colors.green,
                    height: 100,
                  ),
                ),
                Card(
                  child: Container(
                    color: Colors.blue,
                    height: 150,
                  ),
                ),
              ]),
            ),
          )
        ],
      ),
    ],
  ),
);

Solution

  • It looks like solution in my case, but I am not sure, this is right way

      late ScrollController _frontController, _backController;
    
      @override
      void initState() {
        super.initState();
        _frontController = ScrollController();
        _backController = ScrollController();
        _frontController.addListener(test);
      }
    
      @override
      void dispose() {
        _frontController.dispose();
        _backController.dispose();
        super.dispose();
      }
    
      test() {
        if (_frontController.position.pixels >= 215) {
          _backController.jumpTo(_frontController.offset - 215);
        }
      }
    
     return Scaffold(
          body: Stack(
            children: [
              SingleChildScrollView(
                controller: _backController,
                child: Column(
                  children: [
                    Container(
                      height: MediaQuery.of(context).size.height * 0.45,
                      decoration: const BoxDecoration(
                        color: AppColors.mainBrown,
                        borderRadius:
                            BorderRadius.vertical(bottom: Radius.circular(30)),
                      ),
                    ),
                    const SizedBox(
                      height: 1000,
                    )
                  ],
                ),
              ),
              CustomScrollView(
                controller: _frontController,
                slivers: [
                  const SliverAppBar(
                    expandedHeight: 70,
                    backgroundColor: Colors.transparent,
                    elevation: 0,
                    shadowColor: Colors.transparent,
                    titleSpacing: 22,
                    title: Text('AppBar'),
                  ),
                  SliverPadding(
                    padding: const EdgeInsets.symmetric(horizontal: 30),
                    sliver: SliverList(
                      delegate: SliverChildListDelegate([
                        Card(
                          child: Container(
                            color: Colors.brown,
                            height: 200,
                          ),
                        ),
                        Card(
                          child: Container(
                            color: Colors.yellow,
                            height: 250,
                          ),
                        ),
                        Card(
                          child: Container(
                            color: Colors.black,
                            height: 300,
                          ),
                        ),
                        Card(
                          child: Container(
                            color: Colors.red,
                            height: 50,
                          ),
                        ),
                        Card(
                          child: Container(
                            color: Colors.green,
                            height: 100,
                          ),
                        ),
                        Card(
                          child: Container(
                            color: Colors.blue,
                            height: 150,
                          ),
                        ),
                      ]),
                    ),
                  )
                ],
              ),
            ],
          ),
        );