flutter - 值更改后小部件宽度不更新
问题描述
我正在尝试构建一个侧面菜单,当按下下面屏幕截图中显示的垂直应用栏底部的箭头图标时,该菜单将打开和关闭。我目前正在通过使用名为 isleftWidgetCollapsed 的全局布尔值来执行此操作,如果 isleftWidgetCollapsed 设置为 true,它会将侧边菜单的宽度更改为 0。
它似乎工作正常,但只有当我调整应用程序窗口的大小时,如下面的屏幕截图所示。我怎样才能让它在按下 IconButton 时工作,而不必每次都调整应用程序窗口的大小?
buildLeftMenu.dart 中的代码部分:
Widget buildLeft(context, HomeViewModel model) {
final _scrollbar = ScrollController();
return Material(
textStyle: TextStyle(
color: Colors.white70,
fontFamily: 'Lato',
),
child: Row(
children: [
Container(
width: (gb.isleftWidgetCollapsed==true)
? 0
: MediaQuery.of(context).size.width * .20, //21.width,
height: 100.height,
decoration: BoxDecoration(
color: MainTheme.primary[50], //Colors.blueAccent[400],
),
mainHomeView.dart 中的代码部分:
body: Container(
child: Row(
children: [
VerticalAppBar(),
buildLeft(context, HomeViewModel()),
...
VerticalAppBar.dart 中的 onPressed 部分:
leading: RotatedBox(
quarterTurns: 1,
child: IconButton(
icon: Icon(gb.isleftWidgetCollapsed
? Icons.arrow_right
: Icons.arrow_left),
onPressed: () {
setState(() {
gb.isleftWidgetCollapsed = !gb.isleftWidgetCollapsed;
buildLeft(context, HomeViewModel());
});
},
)),
),
);
}
}
globals.dart:
library my_prj.globals;
bool isLoggedIn = false;
bool isleftWidgetCollapsed = false;
解决方案
buildLeft
对inside的调用onPressed
什么也不做:
onPressed: () {
setState(() {
gb.isleftWidgetCollapsed = !gb.isleftWidgetCollapsed;
buildLeft(context, HomeViewModel());
});
},
这是使用hooks_riverpod包的解决方案。你可以在这里找到关于这个包的所有信息:http ://riverpod.dev/
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
void main() {
runApp(
ProviderScope(
child: MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
home: HomePage(),
),
),
);
}
class HomePage extends HookWidget {
@override
Widget build(BuildContext context) {
final menuOpened = useProvider(menuOpenedProvider).state;
return Scaffold(
body: Stack(
children: [
AnimatedPositioned(
duration: Duration(milliseconds: 300),
top: 0,
right: 0,
bottom: 0,
left: menuOpened
? kVerticalBarWidth + kLeftMenuWidth
: kVerticalBarWidth,
child: Content(),
),
AnimatedPositioned(
duration: Duration(milliseconds: 300),
top: 0,
bottom: 0,
left: menuOpened
? kVerticalBarWidth
: kVerticalBarWidth - kLeftMenuWidth,
child: LeftMenu(),
),
Align(alignment: Alignment.centerLeft, child: VerticalAppBar()),
],
),
);
}
}
class VerticalAppBar extends HookWidget {
@override
Widget build(BuildContext context) {
final menuOpened = useProvider(menuOpenedProvider).state;
return Container(
width: kVerticalBarWidth,
color: kVerticalBarColor,
child: Align(
alignment: Alignment.bottomCenter,
child: IconButton(
onPressed: () =>
context.read(menuOpenedProvider).state = !menuOpened,
icon: Icon(menuOpened ? Icons.arrow_left : Icons.arrow_right)),
),
);
}
}
class LeftMenu extends HookWidget {
@override
Widget build(BuildContext context) {
return Container(
color: kLeftMenuColor,
width: 200.0,
padding: EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
...List.generate(20, (index) => Text('Menu Item $index')),
],
),
);
}
}
class Content extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
color: kContentColor,
child: Center(
child: Text('CONTENT'),
),
);
}
}
// Provider for the Menu State
final menuOpenedProvider = StateProvider((ref) => true);
// Some constants
const double kVerticalBarWidth = 48.0;
const double kLeftMenuWidth = 200.0;
const Color kVerticalBarColor = Color(0xffc19277);
const Color kLeftMenuColor = Color(0xffe1bc91);
const Color kContentColor = Color(0xff62959c);
推荐阅读
- android - 带有“cordova-plugin-local-notifications”插件的本地通知
- security - 基于 NTAG213 与 Ultralight C 的支付应用程序(使用 Android NFC)
- c# - 有没有办法获得指向泛型类型“in”参数的指针?
- javascript - 为什么 JS Map 函数返回未定义?
- swift - 如何在 Swift 中解开任意深度嵌套的选项?
- design-patterns - 带有单例的工厂模式
- asp.net-mvc - 如何在 MVC 中使用 Razor View 获取去年(如“00/2017”)?
- c - 用逗号将宏参数传递给函数
- javascript - 无垂直移动的 PunchJs 编辑
- orange - 在脚本而不是 GUI 中重现 RandomForestLearner 的困难