Flutter Ui 实验室(三)Baidu App 悬浮菜单
2019-06-08 本文已影响38人
funpig
Baidu App 有一个悬浮菜单的效果,今天就用Flutter来实现一下
![](https://img.haomeiwen.com/i209371/d6069d955e7de4c8.png)
具体效果:点击分类,弹出菜单,再次点击,收起菜单。
Flutter里面要实现这种悬浮菜单的效果,需要用到 Overlay 控件
我们实现的效果如下
![](https://img.haomeiwen.com/i209371/fd7411dc9777ee39.png)
重点如下:
- 使用 Overlay 控件来实现悬浮菜单
- 使用 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: ...
- 点击‘分类’widget后,设置是否显示悬浮菜单
setState((){
_isMenuShow = !_isMenuShow;
}),
- 利用Column和Row的组合,来实现具体菜单的显示
未实现
- 点击悬浮菜单的其他位置,隐藏悬浮菜单
- 没有响应点击悬浮菜单的具体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)
],
),
),
),
],
),
)
],
),
),
);
}
}