Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create sticky shop button animation in Flutter?

Tags:

flutter

dart

How can I create this sticky buy button animation of Adidas app in Flutter. I have tried to use a scroll controller to listen for the position of user and then use an animated container but it is of no use since I have to define my scroll controller in my initstate while the height of my containers are relative to my device's height. here is the link of video for the animation: https://drive.google.com/file/d/1TzIUBr6abRQI87xAVu4NOPG67aftzceK/view?usp=sharing

this is what the widget tree looks like:

 Scaffold(appbar,FAB,_body),
_body= SingleChildSrollView child:Column[Container(child:Listview)
,Container(child:PageView(children:[GridView])
,Container
,Container(this is where the shop button should be, the one that replaces the FAB)
,GridView,])
like image 716
geekymano Avatar asked Jun 22 '19 00:06

geekymano


1 Answers

Another answer (variable height boxes)

enter image description here

void main() => runApp(MaterialApp(home: Scaffold(body: HomePage(), appBar: AppBar())));

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> with WidgetsBindingObserver {
  ScrollController _controller = ScrollController();
  double _screenHeight, _hRatings = 350, _hSize = 120, _hWidth = 130, _hComfort = 140, _hQuality = 150, _hBuy = 130, _hQuestions = 400;
  bool _itemVisibility = true;

  @override
  void initState() {
    super.initState();

    double offsetEnd;
    WidgetsBinding.instance.addPostFrameCallback((_) {
      RenderBox box = context.findRenderObject();
      _screenHeight = box.globalToLocal(Offset(0, MediaQuery.of(context).size.height)).dy;
      offsetEnd = (_hRatings + _hSize + _hWidth + _hComfort + _hQuality + _hBuy) - _screenHeight;
    });

    _controller.addListener(() {
      if (_controller.position.pixels >= offsetEnd) {
        if (_itemVisibility) setState(() => _itemVisibility = false);
      } else {
        if (!_itemVisibility) setState(() => _itemVisibility = true);
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget>[
        ListView(
          controller: _controller,
          children: <Widget>[
            _buildBox(_hRatings, "Ratings box", Colors.blue[200]),
            _buildBox(_hSize, "Size box", Colors.blue[300]),
            _buildBox(_hWidth, "Width box", Colors.blue[400]),
            _buildBox(_hComfort, "Comfort box", Colors.blue[500]),
            _buildBox(_hQuality, "Quality box", Colors.blue[600]),
            _buildBox(_hBuy, "Buy box", Colors.orange[700]),
            _buildBox(_hQuestions, "Questions part", Colors.blue[800]),
          ],
        ),
        Positioned(
          bottom: 0,
          right: 0,
          left: 0,
          child: Visibility(
            visible: _itemVisibility,
            child: _buildBox(_hBuy, "Buy box", Colors.orange[700]),
          ),
        ),
      ],
    );
  }

  Widget _buildBox(double height, String text, Color color) {
    return Container(
      height: height,
      color: color,
      alignment: Alignment.center,
      child: Text(
        text,
        style: TextStyle(
          fontSize: 32,
          color: Colors.black,
          fontWeight: FontWeight.bold,
        ),
      ),
    );
  }
}
like image 102
CopsOnRoad Avatar answered Nov 06 '22 17:11

CopsOnRoad