Flutter Drawer функция hide/show
Пытаюсь сделать админку в WebApp flutter. Родной drawer при открытии покрывает полностью контент, я хочу сделать его всегда открытым и при нажатий на иконку закрывать. Как сделать функцию hide/show ? код:
class AdminPage extends StatefulWidget {
@override
_AdminPage createState() => _AdminPage();
}
bool isColapsed = true;
class _AdminPage extends State<AdminPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: Builder(
builder: (context) => IconButton(
icon: Icon(Icons.menu),
onPressed: () => Scaffold.of(context).openEndDrawer())),
backgroundColor: Colors.deepOrange,
actions: <Widget>[IconButton(icon: Icon(Icons.menu), onPressed: () {})],
),
body: Stack(
children: <Widget>[
Container(
color: Colors.amberAccent,
child: Center(
child: Text('content'),
),
),
],
),
);
}
}
Переделанный виджет
class SideMenu extends StatefulWidget {
@override
_SideMenuState createState() => _SideMenuState();
}
bool isSideBarOpened = true;
final _animationDuration = const Duration(milliseconds: 500);
class _SideMenuState extends State<SideMenu> {
Widget widgetForBody = FirstPage();
@override
Widget build(BuildContext context) {
final screenWidth = MediaQuery.of(context).size.width;
return AnimatedPositioned(
duration: _animationDuration,
top: 0,
bottom: 0,
left: isSideBarOpened ? 0 : -300,
right: isSideBarOpened ? 0 : screenWidth - 35,
child: Row(
children: <Widget>[
Flexible(
child: Container(
width: 300.0,
color: Colors.deepOrange,
child: Column(
children: <Widget>[
ListTile(
title: Text('First Page'),
onTap: () {
setState(() {
widgetForBody = FirstPage();
});
},
),
],
),
),
),
Align(
alignment: Alignment(0, -0.9),
child: Container(
width: 35,
height: 100,
color: Colors.deepOrange,
child: IconButton(
icon: Icon(Icons.menu),
onPressed: () {
setState(() {
isSideBarOpened = !isSideBarOpened;
});
},
),
),
),
],
),
);
}
}
Ответы (2 шт):
Автор решения: MiT
→ Ссылка
По сути это уже не Drawer, а своя реализация меню... Проверить можно в DartPad'е.
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(home: AdminPage()));
}
class AdminPage extends StatefulWidget {
@override
_AdminPage createState() => _AdminPage();
}
class _AdminPage extends State<AdminPage> {
bool _isMenuVisibility = true;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: Builder(
builder: (context) => IconButton(
icon: Icon(Icons.menu),
onPressed: () => setState(() => (_isMenuVisibility)
? _isMenuVisibility = false
: _isMenuVisibility = true),
),
),
backgroundColor: Colors.deepOrange,
actions: <Widget>[
IconButton(icon: Icon(Icons.menu), onPressed: () {}),
],
),
body: Stack(
children: <Widget>[
Container(
color: Colors.amberAccent,
child: Center(
child: Text('content'),
),
),
menu(),
],
),
);
}
Widget menu() {
return Visibility(
visible: _isMenuVisibility,
child: Drawer(
child: Padding(
padding: EdgeInsets.only(left: 0.0),
child: Align(
alignment: Alignment.centerLeft,
child: Container(
// width: 250.0,
color: Colors.blueGrey,
child: Column(
children: <Widget>[
Flexible(
child: ListView(
children: <Widget>[
ListTile(
title: Text('page1'),
),
],
),
)
],
),
),
),
),
),
);
}
}
Автор решения: Serge Shkurko
→ Ссылка
Реализация Drawer'a с анимацией появления и скрытия.
Код так же можно воспроизвести в dartpad
import 'package:flutter/material.dart';
/// Ширина Drawer'a
const double drawerWidth = 200;
/// Длительность анимации открытия и закрытия в миллисекундах
const Duration drawerAnimationDuration = Duration(milliseconds: 250);
void main() {
runApp(MaterialApp(home: AdminPage()));
}
class AdminPage extends StatefulWidget {
@override
_AdminPage createState() => _AdminPage();
}
class _AdminPage extends State<AdminPage> with SingleTickerProviderStateMixin {
AnimationController _animation;
@override
void initState() {
_animation = AnimationController(
// Значение, определяющее открыт ли Drawer
// при первом появлении страницы. 0 - закрыт, 1 - открыт
value: 1,
vsync: this,
duration: drawerAnimationDuration,
);
super.initState();
}
@override
void dispose() {
_animation.dispose();
super.dispose();
}
void _menuButtonPressed() {
if (_animation.isAnimating) return;
_animation.isCompleted ? _animation.reverse() : _animation.forward();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: <Widget>[
SlideTransition(
position: Tween<Offset>(
begin: Offset(-1, 0),
end: Offset.zero,
).animate(_animation),
child: _buildMenu(),
),
AnimatedBuilder(
animation: _animation,
builder: (_, widget) => Padding(
padding: EdgeInsets.only(left: drawerWidth * _animation.value),
child: widget,
),
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
AppBar(
title: Text('Admin panel'),
leading: IconButton(
icon: Icon(Icons.menu),
onPressed: _menuButtonPressed,
),
),
Expanded(
child: _buildContent(),
),
],
),
),
],
),
);
}
Widget _buildMenu() {
return Container(
width: drawerWidth,
decoration: BoxDecoration(
border: Border(right: BorderSide(color: Colors.grey[300])),
),
child: ListView(
children: <Widget>[
ListTile(title: Text("Menu A")),
ListTile(title: Text("Menu B")),
ListTile(title: Text("Menu C")),
ListTile(title: Text("Menu D")),
],
),
);
}
Widget _buildContent() {
return Container(
child: Center(child: Text('Content')),
color: Colors.grey[200],
);
}
}
