getx
getx copied to clipboard
Bug Hiding all children when using Stack() with Visibility() or IF (visibility) for a child
Describe the bug Using a simple Stack() structure when it is necessary to hide a child widget results in hiding all the children. With other widgets this does not happen, for example Column. It works with StatefulWidget.
example:
VIEW
class HousePlanView extends GetView<HousePlanController> {
const HousePlanView({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: controller.obx(
(_) => Stack(
children: [
Positioned(
top: 10,
left: 10,
child: Container(
width: 100,
height: 100,
color: Colors.blue,
),
),
Obx(() {
if (controller.isKitchenSwitchedOn.value) {
return Positioned(
top: 50,
left: 50,
child: Container(
width: 120,
height: 120,
color: Colors.green,
),
);
}
return const SizedBox.shrink();
}),
Positioned(
top: 95,
left: 75,
child: OutlinedButton.icon(
onPressed: () => controller.switchLightBulb(LightBulb.kitchen),
icon: const Icon(Icons.lightbulb),
label: const Text(''),
iconAlignment: IconAlignment.end,
),
),
],
),
onLoading: const Center(
child: Text('LOADING...'),
),
onError: (error) => const Center(
child: Text('ERROR'),
),
onEmpty: const Center(
child: Text('EMPTY'),
),
),
);
}
}
CONTROLLER
enum LightBulb {
kitchen,
laundry,
}
class HousePlanController extends GetxController with StateMixin {
var isKitchenSwitchedOn = true.obs;
@override
void onInit() {
change(null, status: RxStatus.success());
super.onInit();
}
void switchLightBulb(LightBulb lightBulb) {
switch (lightBulb) {
case LightBulb.kitchen:
isKitchenSwitchedOn.toggle();
break;
default:
}
}
}
To Reproduce (bug) Steps to reproduce the behavior:
- Run the code
- Click on OutlinedButton
- All children will hide (expected only the green one)
Expected behavior Hide only the green widget using Stack()
- Change Stack() to Column() on HousePlanView
- Click on OutlinedButton
- Only one child is hidden (green one)
Screenshots
Bug with Stack()
Working with Column (or other widgets)
Flutter Version:
flutter doctor -v
[✓] Flutter (Channel stable, 3.22.3, on macOS 14.5 23F79 darwin-arm64, locale en-BR)
• Flutter version 3.22.3 on channel stable at /Users/thiagodelmotte/development/flutter
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision b0850beeb2 (2 weeks ago), 2024-07-16 21:43:41 -0700
• Engine revision 235db911ba
• Dart version 3.4.4
• DevTools version 2.34.3
[✓] Android toolchain - develop for Android devices (Android SDK version 35.0.0)
• Android SDK at /Users/thiagodelmotte/Library/Android/sdk
• Platform android-35, build-tools 35.0.0
• Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build 17.0.11+0-17.0.11b1207.24-11852314)
• All Android licenses accepted.
[✓] Xcode - develop for iOS and macOS (Xcode 15.4)
• Xcode at /Applications/Xcode.app/Contents/Developer
• Build 15F31d
• CocoaPods version 1.15.2
[✓] Chrome - develop for the web
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
[✓] Android Studio (version 2024.1)
• Android Studio at /Applications/Android Studio.app/Contents
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
• Java version OpenJDK Runtime Environment (build 17.0.11+0-17.0.11b1207.24-11852314)
[✓] VS Code (version 1.91.1)
• VS Code at /Applications/Visual Studio Code.app/Contents
• Flutter extension version 3.94.0
[✓] Connected device (7 available)
• sdk gphone arm64 (mobile) • emulator-5554 • android-arm64 • Android 11 (API 30) (emulator)
• iPhone SE (3rd generation) (mobile) • A5672C57-DA48-4749-88BD-29F5E639528E • ios • com.apple.CoreSimulator.SimRuntime.iOS-17-5
(simulator)
• iPhone 15 Pro Max (mobile) • F398281B-23A6-42A3-9FA4-ABC30B730E36 • ios • com.apple.CoreSimulator.SimRuntime.iOS-17-5
(simulator)
• iPad Pro 13-inch (M4) (mobile) • CC2569A5-800A-417F-A6D4-331FB8AEBF85 • ios • com.apple.CoreSimulator.SimRuntime.iOS-17-5
(simulator)
• macOS (desktop) • macos • darwin-arm64 • macOS 14.5 23F79 darwin-arm64
• Mac Designed for iPad (desktop) • mac-designed-for-ipad • darwin • macOS 14.5 23F79 darwin-arm64
• Chrome (web) • chrome • web-javascript • Google Chrome 127.0.6533.89
[✓] Network resources
• All expected network resources are available.
Getx Version:
get:
dependency: "direct main"
description:
name: get
sha256: e4e7335ede17452b391ed3b2ede016545706c01a02292a6c97619705e7d2a85e
url: "https://pub.dev"
source: hosted
version: "4.6.6"
Describe on which device you found the bug: All devices, but tested:
- iPhone 15 Pro Max
- Android Medium Phone API 30
- macOS
- Chrome
Thank you very much for opening this issue, I haven't had the opportunity to run your repro code yet, but just by taking a quick look, I can identify the cause of the problem.
You are using a
return const SizedBox.shrink(); inside a Stack (a widget that allows overlapping of its children). This is a problem that many don't realize, but there is a huge difference between doing this in a column, where this would be acceptable, or in a Stack (where this should NEVER be done).
How to solve this problem?
Well, there is a widget in Flutter that is universal, and aims to mitigate this type of problem, working with Column, or Stack, it is Visibility. If you change your code to something like this:
Obx(() {
return Visibility(
visible: controller.isKitchenSwitchedOn.value,
child: Positioned(
top: 50,
left: 50,
child: Container(
width: 120,
height: 120,
color: Colors.green,
),
),
);
}),
It should work.
I hope this helps, and let me know if this solved your problem.
Hi @jonataslaw ,
That's not the real problem, in fact I'm not using const SizedBox.shrink(); in my real code, it was just to illustrate here and it ended up going wrong.
Anyway, I had also tested Visibility() and with IF without SizedBox.shrink(); and even so all the Widgets on the screen disappeared.
I understand that this is a real bug, because I tried to simulate it separately in several simpler and more complex ways and in all of them I had the same result.
If you can't simulate it, even removing SizedBox.shrink();, let me know so I can help you show you the problem.
For now I've worked around the problem by using the opacity property to hide what I need on the screen, but it's not an ideal solution.
Thanks
Thank you for your response.
Can the issue be reproduced with the code provided in version 4?
I just tested the code provided in version 5, and I can reproduce the problem using SizedBox.shrink(); and I can't reproduce uit using Visibility.
Yes, I'm using 4.6.6. Using the code below, if I change Visible to False, everything disappears from Stack.
return Stack(
children: [
Positioned(
top: 0,
left: 0,
child: Image.asset(
asset,
),
),
Obx(() {
return const Visibility(
visible: true,
child: Positioned(
top: 100,
left: 100,
child: SizedBox(
width: 200,
height: 200,
child: Text('Test'),
),
),
);
}),
],
);