DolDurma
DolDurma

Reputation: 17279

Flutter show widgets on top of ListView which can slide on scrolling

I was able to solve this part, and now I want to put one more Container at the bottom of the screen say ContainerB.

Expectation:

When scrolling down the ListView (i.e. ScrollDirection.reverse) I want Top Container say ContainerA to slide up from top and at the same time Bottom Container say ContainerB to slide up from bottom and vice versa on sliding up the ListView with fade effect too.

Can anyone use the exiting code or something new to help me out on this?

Screenshot:

enter image description here

Upvotes: 2

Views: 1438

Answers (1)

CopsOnRoad
CopsOnRoad

Reputation: 267404

Output:

enter image description here


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

Upvotes: 3

Related Questions