将覆盖设置为 false 后锚定覆盖不隐藏?扑
Anchored Overlay not hiding after turning overlay to false? Flutter
我不知道为什么即使将 bool 值更改为 false 后它仍然不运行。
这是覆盖的代码。
int bools =1;
@override
Widget build(BuildContext context) {
return AnchoredOverlay(
showOverlay: bools==1?true:false,
child: Center(),
overlayBuilder: (BuildContext context, Rect anchorBounds, Offset anchor) {
return CenterAbout(
position: anchor,
child: Stack(
children: [
Transform(
transform:
Matrix4.translationValues(cardOffset.dx, cardOffset.dy, 0.0)
..rotateZ(_rotation(anchorBounds)),
origin: _rotationOrigin(anchorBounds),
child:Container(
key: profileCardKey,
width: anchorBounds.width,
height: anchorBounds.height,
padding: EdgeInsets.only(top: 16,right: 16,left: 16,bottom: 60),
child: GestureDetector(
onPanStart: _onPanStart,
onPanUpdate: _onPanUpdate,
onPanEnd: _onPanEnd,
child: widget.card,
),
),
),
Positioned(
bottom: 0,
child: Arc(
arcType: ArcType.CONVEX,
edge: Edge.TOP,
height: 60.0,
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 30, sigmaY: 30),
child: Container(
child: RawMaterialButton(
onPressed: () {
bools =0;
Navigator.pushNamed(context, ProfileView.profileView);
},
),
height: 140,
width: MediaQuery.of(context).size.width,
color: Colors.white70.withOpacity(0),
),
),
),
),
Positioned(
left: 50,
bottom: 60,
child: RawMaterialButton(
shape: CircleBorder(),
elevation: 100.0,
child: IconButton(
iconSize: 90,
onPressed: (){bools =0;},
icon: Image.asset('images/deselect.png'),
),
onPressed: (){bools =0;print(bools);},
),
),
Positioned(
right: 50,
bottom: 60,
child: RawMaterialButton(
shape: CircleBorder(),
elevation: 100.0,
child: IconButton(
iconSize: 90,
onPressed: null,
icon: Image.asset('images/select.png'),
),
onPressed: () {
bools=1;
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ProfileView()),
);
},
),
),
],),
);
},
);
}
}
这里是AnchoredOverlay的代码,供参考。
class CenterAbout extends StatelessWidget {
final Offset position;
final Widget child;
CenterAbout({
key,
this.position,
this.child,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Positioned(
left: position.dx,
top: position.dy,
child: FractionalTranslation(
translation: Offset(-0.5, -0.5),
child: child,
),
);
}
}
class AnchoredOverlay extends StatelessWidget {
final bool showOverlay;
final Widget Function(BuildContext, Rect anchorBounds, Offset anchor)
overlayBuilder;
final Widget child;
AnchoredOverlay({
key,
this.showOverlay = false,
this.overlayBuilder,
this.child,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
// This LayoutBuilder gives us the opportunity to measure the above
// Container to calculate the "anchor" point at its center.
child: LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
return OverlayBuilder(
showOverlay: showOverlay,
overlayBuilder: (BuildContext overlayContext) {
// To calculate the "anchor" point we grab the render box of
// our parent Container and then we find the center of that box.
RenderBox box = context.findRenderObject() as RenderBox;
final topLeft =
box.size.topLeft(box.localToGlobal(const Offset(0.0, 0.0)));
final bottomRight = box.size
.bottomRight(box.localToGlobal(const Offset(0.0, 0.0)));
final Rect anchorBounds = Rect.fromLTRB(
topLeft.dx,
topLeft.dy,
bottomRight.dx,
bottomRight.dy,
);
final anchorCenter = box.size.center(topLeft);
return overlayBuilder(overlayContext, anchorBounds, anchorCenter);
},
child: child,
);
},
),
);
}
}
class OverlayBuilder extends StatefulWidget {
final bool showOverlay;
final Widget Function(BuildContext) overlayBuilder;
final Widget child;
OverlayBuilder({
key,
this.showOverlay = false,
this.overlayBuilder,
this.child,
}) : super(key: key);
@override
_OverlayBuilderState createState() => new _OverlayBuilderState();
}
class _OverlayBuilderState extends State<OverlayBuilder> {
OverlayEntry overlayEntry;
@override
void initState() {
super.initState();
if (widget.showOverlay) {
WidgetsBinding.instance.addPostFrameCallback((_) => showOverlay());
}
}
@override
void didUpdateWidget(OverlayBuilder oldWidget) {
super.didUpdateWidget(oldWidget);
WidgetsBinding.instance.addPostFrameCallback((_) => syncWidgetAndOverlay());
}
@override
void reassemble() {
super.reassemble();
WidgetsBinding.instance.addPostFrameCallback((_) => syncWidgetAndOverlay());
}
@override
void dispose() {
if (isShowingOverlay()) {
hideOverlay();
print("Hidden");
}
super.dispose();
}
bool isShowingOverlay() => overlayEntry != null;
void showOverlay() {
if (overlayEntry == null) {
// Create the overlay.
overlayEntry = OverlayEntry(
builder: widget.overlayBuilder,
);
addToOverlay(overlayEntry);
} else {
// Rebuild overlay.
buildOverlay();
}
}
void addToOverlay(OverlayEntry entry) async {
Overlay.of(context).insert(entry);
}
void hideOverlay() {
if (overlayEntry != null) {
overlayEntry.remove();
overlayEntry = null;
}
}
void syncWidgetAndOverlay() {
if (isShowingOverlay() && !widget.showOverlay) {
hideOverlay();
} else if (!isShowingOverlay() && widget.showOverlay) {
showOverlay();
}
}
void buildOverlay() async {
overlayEntry?.markNeedsBuild();
}
@override
Widget build(BuildContext context) {
WidgetsBinding.instance.addPostFrameCallback((_) => buildOverlay());
return widget.child;
}
}
当我改变 bool 值的值时,只有卡片隐藏而不是按钮,如下所示。
这是将 showoverlay 值更改为 false 后的图片。
如您所见,按钮容器仍然没有隐藏,我该如何解决这个问题。
如果我缺少问题中的任何信息,请帮助并告诉我。
您必须将 'deselect' 按钮包装在 setState 函数中,这将触发 OverlayBuilder 重建。
在取消选择图像的调用中执行以下操作:
void deselect() {
// ... do somethings
setState() {
bools == 0;
print(bool);
}
// do some other things
}
我不知道为什么即使将 bool 值更改为 false 后它仍然不运行。
这是覆盖的代码。
int bools =1;
@override
Widget build(BuildContext context) {
return AnchoredOverlay(
showOverlay: bools==1?true:false,
child: Center(),
overlayBuilder: (BuildContext context, Rect anchorBounds, Offset anchor) {
return CenterAbout(
position: anchor,
child: Stack(
children: [
Transform(
transform:
Matrix4.translationValues(cardOffset.dx, cardOffset.dy, 0.0)
..rotateZ(_rotation(anchorBounds)),
origin: _rotationOrigin(anchorBounds),
child:Container(
key: profileCardKey,
width: anchorBounds.width,
height: anchorBounds.height,
padding: EdgeInsets.only(top: 16,right: 16,left: 16,bottom: 60),
child: GestureDetector(
onPanStart: _onPanStart,
onPanUpdate: _onPanUpdate,
onPanEnd: _onPanEnd,
child: widget.card,
),
),
),
Positioned(
bottom: 0,
child: Arc(
arcType: ArcType.CONVEX,
edge: Edge.TOP,
height: 60.0,
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 30, sigmaY: 30),
child: Container(
child: RawMaterialButton(
onPressed: () {
bools =0;
Navigator.pushNamed(context, ProfileView.profileView);
},
),
height: 140,
width: MediaQuery.of(context).size.width,
color: Colors.white70.withOpacity(0),
),
),
),
),
Positioned(
left: 50,
bottom: 60,
child: RawMaterialButton(
shape: CircleBorder(),
elevation: 100.0,
child: IconButton(
iconSize: 90,
onPressed: (){bools =0;},
icon: Image.asset('images/deselect.png'),
),
onPressed: (){bools =0;print(bools);},
),
),
Positioned(
right: 50,
bottom: 60,
child: RawMaterialButton(
shape: CircleBorder(),
elevation: 100.0,
child: IconButton(
iconSize: 90,
onPressed: null,
icon: Image.asset('images/select.png'),
),
onPressed: () {
bools=1;
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ProfileView()),
);
},
),
),
],),
);
},
);
}
}
这里是AnchoredOverlay的代码,供参考。
class CenterAbout extends StatelessWidget {
final Offset position;
final Widget child;
CenterAbout({
key,
this.position,
this.child,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Positioned(
left: position.dx,
top: position.dy,
child: FractionalTranslation(
translation: Offset(-0.5, -0.5),
child: child,
),
);
}
}
class AnchoredOverlay extends StatelessWidget {
final bool showOverlay;
final Widget Function(BuildContext, Rect anchorBounds, Offset anchor)
overlayBuilder;
final Widget child;
AnchoredOverlay({
key,
this.showOverlay = false,
this.overlayBuilder,
this.child,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
// This LayoutBuilder gives us the opportunity to measure the above
// Container to calculate the "anchor" point at its center.
child: LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
return OverlayBuilder(
showOverlay: showOverlay,
overlayBuilder: (BuildContext overlayContext) {
// To calculate the "anchor" point we grab the render box of
// our parent Container and then we find the center of that box.
RenderBox box = context.findRenderObject() as RenderBox;
final topLeft =
box.size.topLeft(box.localToGlobal(const Offset(0.0, 0.0)));
final bottomRight = box.size
.bottomRight(box.localToGlobal(const Offset(0.0, 0.0)));
final Rect anchorBounds = Rect.fromLTRB(
topLeft.dx,
topLeft.dy,
bottomRight.dx,
bottomRight.dy,
);
final anchorCenter = box.size.center(topLeft);
return overlayBuilder(overlayContext, anchorBounds, anchorCenter);
},
child: child,
);
},
),
);
}
}
class OverlayBuilder extends StatefulWidget {
final bool showOverlay;
final Widget Function(BuildContext) overlayBuilder;
final Widget child;
OverlayBuilder({
key,
this.showOverlay = false,
this.overlayBuilder,
this.child,
}) : super(key: key);
@override
_OverlayBuilderState createState() => new _OverlayBuilderState();
}
class _OverlayBuilderState extends State<OverlayBuilder> {
OverlayEntry overlayEntry;
@override
void initState() {
super.initState();
if (widget.showOverlay) {
WidgetsBinding.instance.addPostFrameCallback((_) => showOverlay());
}
}
@override
void didUpdateWidget(OverlayBuilder oldWidget) {
super.didUpdateWidget(oldWidget);
WidgetsBinding.instance.addPostFrameCallback((_) => syncWidgetAndOverlay());
}
@override
void reassemble() {
super.reassemble();
WidgetsBinding.instance.addPostFrameCallback((_) => syncWidgetAndOverlay());
}
@override
void dispose() {
if (isShowingOverlay()) {
hideOverlay();
print("Hidden");
}
super.dispose();
}
bool isShowingOverlay() => overlayEntry != null;
void showOverlay() {
if (overlayEntry == null) {
// Create the overlay.
overlayEntry = OverlayEntry(
builder: widget.overlayBuilder,
);
addToOverlay(overlayEntry);
} else {
// Rebuild overlay.
buildOverlay();
}
}
void addToOverlay(OverlayEntry entry) async {
Overlay.of(context).insert(entry);
}
void hideOverlay() {
if (overlayEntry != null) {
overlayEntry.remove();
overlayEntry = null;
}
}
void syncWidgetAndOverlay() {
if (isShowingOverlay() && !widget.showOverlay) {
hideOverlay();
} else if (!isShowingOverlay() && widget.showOverlay) {
showOverlay();
}
}
void buildOverlay() async {
overlayEntry?.markNeedsBuild();
}
@override
Widget build(BuildContext context) {
WidgetsBinding.instance.addPostFrameCallback((_) => buildOverlay());
return widget.child;
}
}
当我改变 bool 值的值时,只有卡片隐藏而不是按钮,如下所示。
这是将 showoverlay 值更改为 false 后的图片。
如您所见,按钮容器仍然没有隐藏,我该如何解决这个问题。
如果我缺少问题中的任何信息,请帮助并告诉我。
您必须将 'deselect' 按钮包装在 setState 函数中,这将触发 OverlayBuilder 重建。
在取消选择图像的调用中执行以下操作:
void deselect() {
// ... do somethings
setState() {
bools == 0;
print(bool);
}
// do some other things
}