Flutter圈子Flutter中文社区Flutter

Flutter Ui 实验室(三)Baidu App 悬浮菜单

2019-06-08  本文已影响38人  funpig

Baidu App 有一个悬浮菜单的效果,今天就用Flutter来实现一下


image.png

具体效果:点击分类,弹出菜单,再次点击,收起菜单。

Flutter里面要实现这种悬浮菜单的效果,需要用到 Overlay 控件

我们实现的效果如下


image.png

重点如下:

  1. 使用 Overlay 控件来实现悬浮菜单
  2. 使用 BuildContext findRenderObject 方法找到对应Widget的position和size,然后算出悬浮菜单的位置
    //使用全局context得到屏幕宽度
    RenderBox renderBox = context.findRenderObject();
    var size = renderBox.size;
    //利用GlobalKey找到 ‘分类’widget的position
    renderBox = _appMenuKey.currentContext.findRenderObject();
    var menusize = renderBox.size;
    var menupositon = renderBox.localToGlobal(Offset.zero);
    return OverlayEntry(
      builder: (context) => Positioned(
        //确定悬浮菜单的 offset_y
        top: menupositon.dy + menusize.height,
        width: size.width,
        child: ...
  1. 点击‘分类’widget后,设置是否显示悬浮菜单
setState((){
   _isMenuShow = !_isMenuShow;
}),
  1. 利用Column和Row的组合,来实现具体菜单的显示

未实现

  1. 点击悬浮菜单的其他位置,隐藏悬浮菜单
  2. 没有响应点击悬浮菜单的具体Item

代码如下

import 'package:flutter/material.dart';

class BaiduAppMenueOverlay extends StatefulWidget {
  @override
  _BaiduAppMenueOverlayState createState() => _BaiduAppMenueOverlayState();
}

class _BaiduAppMenueOverlayState extends State<BaiduAppMenueOverlay> {
  bool _isMenuShow = false;

  OverlayEntry _overlayEntry;
  GlobalKey _appMenuKey = GlobalKey();

  OverlayEntry _createOverlayEntry(BuildContext context) {
    RenderBox renderBox = context.findRenderObject();
    var size = renderBox.size;
    renderBox = _appMenuKey.currentContext.findRenderObject();
    var menusize = renderBox.size;
    var menupositon = renderBox.localToGlobal(Offset.zero);
    return OverlayEntry(
      builder: (context) => Positioned(
        top: menupositon.dy + menusize.height,
        width: size.width,
        child: Container(
          color: Colors.yellow,
          child: Column(
            children: <Widget>[
              Container(height: 5),
              Row(
                children: <Widget>[
                  Expanded(
                    child: Column(
                      children: <Widget>[
                        Icon(Icons.bookmark),
                        Text(
                          '图一',
                          textAlign: TextAlign.center,
                          style: TextStyle(
                            inherit: false,
                            fontSize: 16.0,
                            color: Colors.grey
                          ),
                        )
                      ],
                    ),
                  ),
                  Expanded(
                    child: Column(
                      children: <Widget>[
                        Icon(Icons.bookmark),
                        Text(
                          '图二',
                          textAlign: TextAlign.center,
                          style: TextStyle(
                            inherit: false,
                            fontSize: 16.0,
                            color: Colors.grey
                          ),)
                      ],
                    ),
                  ),
                  Expanded(
                    child: Column(
                      children: <Widget>[
                        Icon(Icons.bookmark),
                        Text(
                          '图三',
                          textAlign: TextAlign.center,
                          style: TextStyle(
                            inherit: false,
                            fontSize: 16.0,
                            color: Colors.grey
                          ),
                        )
                      ],
                    ),
                  ),Expanded(
                    child: Column(
                      children: <Widget>[
                        Icon(Icons.bookmark),
                        Text(
                          '图四',
                          textAlign: TextAlign.center,
                          style: TextStyle(
                            inherit: false,
                            fontSize: 16.0,
                            color: Colors.grey
                          ),
                          )
                      ],
                    ),
                  ),
                ],
              ),
              Container(height: 5),
              Row(
                children: <Widget>[
                  Expanded(
                    child: Column(
                      children: <Widget>[
                        Icon(Icons.bookmark),
                        Text(
                          '图五',
                          textAlign: TextAlign.center,
                          style: TextStyle(
                            inherit: false,
                            fontSize: 16.0,
                            color: Colors.grey
                          ),
                        )
                      ],
                    ),
                  ),
                  Expanded(
                    child: Column(
                      children: <Widget>[
                        Icon(Icons.bookmark),
                        Text(
                          '图六',
                          textAlign: TextAlign.center,
                          style: TextStyle(
                            inherit: false,
                            fontSize: 16.0,
                            color: Colors.grey
                          ),)
                      ],
                    ),
                  ),
                  Expanded(
                    child: Column(
                      children: <Widget>[
                        Icon(Icons.bookmark),
                        Text(
                          '图七',
                          textAlign: TextAlign.center,
                          style: TextStyle(
                            inherit: false,
                            fontSize: 16.0,
                            color: Colors.grey
                          ),
                        )
                      ],
                    ),
                  ),Expanded(
                    child: Column(
                      children: <Widget>[
                        Icon(Icons.bookmark),
                        Text(
                          '图八',
                          textAlign: TextAlign.center,
                          style: TextStyle(
                            inherit: false,
                            fontSize: 16.0,
                            color: Colors.grey
                          ),
                          )
                      ],
                    ),
                  ),
                ],
              ),
            ],
          ),
        ),
      )
    );
  }

  _showBaiduOverlayMenu(isMenuShow) {
    if (isMenuShow) {
      this._overlayEntry = this._createOverlayEntry(context);
      Overlay.of(context).insert(this._overlayEntry);
    } else {
      this._overlayEntry.remove();
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Baidu App 浮动菜单'),
      ),
      body: Container(
        child: Column(
          children: <Widget>[
            Container(
              height: 40,
              color: Colors.white,
              child: Row(
                children: <Widget>[
                  Container(
                    width: 10,
                  ),
                  GestureDetector(
                    key: _appMenuKey,
                    onTap: () => {
                      setState((){
                        _isMenuShow = !_isMenuShow;
                      }),
                      _showBaiduOverlayMenu(_isMenuShow)
                    },
                    child: Container(
                      child: Row(
                        children: <Widget>[
                          Text('分类'),
                          Container(width: 4),
                          Icon(_isMenuShow ? Icons.arrow_drop_up: Icons.arrow_drop_down)
                        ],
                      ),
                    ),
                  ),
                ],
              ),
            )
          ],
        ),
      ),
    );
  }
}

上一篇 下一篇

猜你喜欢

热点阅读