Output:

Probably this will help. 
void main() => runApp(MaterialApp(home: HomePage()));
class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
  var _controller = ScrollController();
  static final double _height = 120;
  double _top = 0, _topList = _height;
  double _offsetA = 0, _offsetB = 0, _savedA = 0, _savedB = 0;
  var _tookA = false, _tookB = false, _fadeContainer = true;
  @override
  void initState() {
    super.initState();
    _controller.addListener(listener);
  }
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("ListView")),
      body: Stack(
        children: <Widget>[
          Positioned(
            top: _topList,
            left: 0,
            right: 0,
            bottom: 0,
            child: _buildListView(),
          ),
          Positioned(
            top: _top,
            left: 0,
            right: 0,
            child: Opacity(
              opacity: _fadeContainer ? 1 + (_top / _height) : 1,
              child: _buildContainer(title: "ContainerA", color: Colors.red),
            ),
          ),
          Positioned(
            bottom: -_height - _top,
            left: 0,
            right: 0,
            child: Opacity(
              opacity: _fadeContainer ? (-_top / _height) : 1,
              child: _buildContainer(title: "ContainerB", color: Colors.teal),
            ),
          ),
        ],
      ),
    );
  }
  void listener() {
    double offset = _controller.offset;
    _topList = _height - offset;
    if (_topList < 0) _topList = 0;
    if (_controller.position.userScrollDirection == ScrollDirection.reverse) {
      _tookB = false;
      if (!_tookA) {
        _tookA = true;
        _offsetA = offset;
      }
      var difference = offset - _offsetA;
      _top = _savedB - difference;
      if (_top <= -_height) _top = -_height;
      _savedA = _top;
    } else if (_controller.position.userScrollDirection == ScrollDirection.forward) {
      _tookA = false;
      if (!_tookB) {
        _tookB = true;
        _offsetB = offset;
      }
      var difference = offset - _offsetB;
      _top = _savedA - difference;
      if (_top >= 0) _top = 0;
      _savedB = _top;
    }
    setState(() {});
  }
  Widget _buildListView() {
    return ListView.builder(
      controller: _controller,
      padding: EdgeInsets.only(bottom: _height + 16),
      itemCount: 16,
      itemBuilder: (_, i) => ListTile(title: Text("Item $i")),
    );
  }
  Widget _buildContainer({String title, Color color}) {
    return Container(
      height: _height,
      color: color,
      alignment: Alignment.center,
      child: Text(
        title,
        style: TextStyle(fontSize: 32, color: Colors.white),
      ),
    );
  }
}