How can i hide specific child inside Stack widget. I tried Visibility widget to hide child but this effects whole stack widget to hidden.
My code
Visibility(
visible: visibleControl == ScreenControls.RECORDING ? true:false,
child: Stack(
alignment: AlignmentDirectional.center,
children: <Widget>[
Visibility(
visible: false,
child: SpinKitRipple(
color: kConvertLoadingDotsColor,
size: 100,
),
),
Positioned(
bottom:6,
child:Text("Hello Mongolia"),),
],
)
UPDATE:
There is a param in Visibility called maintainSize that will keep the size of the widget and therefore the Stack size too
OLD:
Visibility doesn't hide the widget, it replaces it with a zero-sized box. So if the `Stack size is inherited from their child and the only child that give it size has visibility false the stack will have 0 size.
There are several solutions to this
Use fit: StackFit.expand to expand Stack size to parent
1.1 Add a SizedBox above Stack with a fixed height if you want a fixed height
Replace Visibility widget with Opacity widget, this will hide the widget but won't be remove it. This to consider here is
opacity performance
For values of opacity other than 0.0 and 1.0, this class is relatively expensive because it requires painting the child into an intermediate buffer.
Touch inputs will still work. You can add an IgnorePointer with the param ignore that changes along the opacity one
This is just an example ! Modify as your requirement... !
List<bool> visibilityValues = [];
#override
void initState() {
super.initState();
visibilityValues = List.generate(5, (ind) => true).toList();
//change 5 with your num of widgets
}
#override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(15),
child: Stack(children: [
Positioned(
top: 1,
left: 1,
child: Visibility(
visible: visibilityValues[0],
child:
InkWell(
//similarly wrap all widgets with inkwell or any othe listener and change widget visibility value
onTap:(){
setState((){
visibilityValues[0] = false;
});
},
child: Container(width: 100, height: 100, color: Colors.greenAccent)),
),
),
Positioned(
top: 1,
right: 1,
child: Visibility(
visible: visibilityValues[1],
child:
Container(width: 100, height: 100, color: Colors.blueAccent),
),
),
Positioned(
bottom: 1,
left: 1,
child: Visibility(
visible: visibilityValues[2],
child:
Container(width: 100, height: 100, color: Colors.redAccent),
),
),
Positioned(
bottom: 1,
right: 1,
child: Visibility(
visible: visibilityValues[3],
child:
Container(width: 100, height: 100, color: Colors.yellowAccent),
),
),
Align(
alignment: Alignment.center,
child: Visibility(
visible: visibilityValues[4],
child:
Container(width: 100, height: 100, color: Colors.tealAccent),
),
)
]));
}
Related
I'm trying to create a custom widget and it makes use of the Stack widget. When I wrap the Stack's children using the Positined widget, the stack hugs the children that are not positioned. When I try to use the Align widget for more precise placement the stack expands to fill all the available space.
I'm trying to avoid using any widget with a fixed size, i.e. Container or SizedBox, as the parent for the Stack widget.
Is there a way to prevent the stack from filling all the available space or work around this that archives the same result?
I'm trying to position a child to the top center of the Stack as an example and this is where I am right now:
Using the Positined widget (I have to try multiple time to get the center position and sometimes its still off):
Positioned(
top: 0,
left: 80,
child: child,
);
Using the Align widget:
Align(
alignment: Alignment.topCenter,
child: child,
);
This should be the result using the Align widget:
Align(
alignment: Alignment.topCenter,
child: child,
);
You can set Stack's alignment to topCenter, Try this:
Stack(
alignment: Alignment.topCenter, // <=== add this
children: [
Container(
color: Colors.grey,
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisSize: MainAxisSize.min, // <=== add this
children: [
Container(
color: Colors.amber,
height: 30,
width: 30,
),
Container(
color: Colors.green,
height: 30,
width: 30,
),
Container(
color: Colors.blue,
height: 30,
width: 30,
),
Container(
color: Colors.yellow,
height: 30,
width: 30,
),
],
),
),
Container(
color: Colors.red,
height: 30,
width: 30,
)
],
)
Note: make sure you set Row's mainAxisSize to min.
I need to increase the tap area for gesture detector. I tried wrapping it in a stack and added gesture detector to the top widget which is basically an empty container
Widget build(BuildContext context) {
return Stack(
alignment: Alignment.center,
children: [
_button(),
GestureDetector(
behavior: HitTestBehavior.translucent,
child: Container(
height: 80,
width: 80,
color: Colors.redAccent.withOpacity(0.5), // remove this
),
onTap: () {
print('tapped');
},
onPanUpdate: (details) => ....,
onPanEnd: (details) => ....,
)
],
);
}
Screenshot
As you can see in the screenshot I have a text which can be scaled in height. In order to do so I have added a button:
Widget _button() {
return Material(
color: Colors.grey[500],
child: Container(
alignment: Alignment.center,
child: SizedBox(
height: widget.size / 4,
width: widget.size,
),
),
);
}
But I need to increase the tap area and so the stack solution. But it's not working unless I tap in the center(right on top of the _button()). Why is that happening even when I wrapped the empty container with gesture detector?
The top button in the screenshot attached is positioned on the dash lines:
return Stack(
clipBehavior: Clip.none,
fit: StackFit.passthrough,
children: <Widget>[
child,
Positioned(
top: -25,
right: widget.item!.width / 2,
child: TopScaleButton(
widget.item!,
size: buttonSize,
canvasKey: canvasKey,
),
),
],
);
}
AFAIK, in a stack, the widget are stacked on to of each other, so you might need to switch the order of your two widgets in the stack.
What's the right way to animate a change in size of a Stack widget?
The first idea was to wrap the Stack with a SizeTransition:
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
SizeTransition(
sizeFactor: _height, // Just a Tween<double>(begin: 200, end: 400)
axis: Axis.vertical,
axisAlignment: -1,
child: Stack(
children: [
Positioned(
bottom: 10,
left: 10,
child: Container(width: 50, height: 50, color: Colors.blue),
),
Positioned(
top: 10,
right: 10,
child: Container(width: 50, height: 50, color: Colors.green),
),
],
),
),
],
);
}
But running the snippet causes the following error:
'package:flutter/src/rendering/stack.dart': Failed assertion: line 588 pos 12: 'size.isFinite': is not true.
So, apparently, that's not the right way to do it. Questions now is: How do you animate resizing of a Stack?
Wrapping the Stack with a SizedBox would fix the error message, but then, how do you get the size from SizedTransition to set the proper size of a SizedBox?
You can use AnimatedContainer as parent of Stack widget by providing height or width one you like to change over time.
AnimatedContainer(
color: Colors.purple,
duration: const Duration(milliseconds: 200),
height: height,
child: Stack(
children: [
Positioned(
bottom: 10,
left: 10,
child: Container(width: 50, height: 50, color: Colors.blue),
),
Positioned(
top: 10,
right: 10,
child: Container(width: 50, height: 50, color: Colors.green),
),
],
),
),
I'm using a Stack to Positioned one widget on top of an Image.asset widget, but the problem I have is that my whole Stack widget is not scrollable to see the whole content. I wrapped the Stack widget with a SingleChildScrollView but the problem still persists. If I wrap the Stack widget with a Containter and give the height: MediaQuery.of(context).size.height, it's scrollable but I can't still see the whole content of the page. Where is my mistake, that's what I'm wondering? With what widget should I wrap Stack or is there a better way for my problem? In short, I'm stacking a Column on top of an Image and I need the whole Stack widget to be scrollable so I can see the whole content of the Stack widget. Here is the code:
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey,
body: SafeArea(
child: SingleChildScrollView(
child: Stack(
overflow: Overflow.visible,
children: [
Image.asset(
'lib/modules/common/images/logo.png',
width: double.infinity,
height: 196.0,
),
Positioned(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
top: 136.0,
child: Column(
children: [
Container(), // some content inside the container
Container(), // // some content inside the container
],
),
),
],
),
),
),
);
}
Thanks in advance for the help!
if you mean to have a image on back and scrollable content at fron check this answer, if not let me know and share a prototype/image that you want.
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey,
body: SafeArea(
child: SingleChildScrollView(
child: SizedBox(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height * 3,
child: Stack(
fit: StackFit.loose,
children: [
Align(
alignment: Alignment.topCenter,
child: Image.asset(
'assets/image.jpg',
width: double.infinity,
height: 196.0,
),
),
Positioned(
top: 136.0,
child: SizedBox(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: Column(
mainAxisSize: MainAxisSize.min,
children: List.generate(
2,
(index) => Container(
height: 100,
width: double.infinity,
color: index % 2 == 0
? Colors.amberAccent
: Colors.cyanAccent,
), // some content inside the container
// some content inside the container
),
),
),
),
],
),
),
),
),
);
}
CODE:
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
backgroundColor: Colors.blue,
body: SafeArea(
child: SingleChildScrollView(
physics: ClampingScrollPhysics(),
child: Align(
alignment: Alignment.center,
child: Container(
width: Get.width,
height: Get.width * 16 / 9,
child: Stack(
children: [
Positioned(top: 16, left: 16, child: BackButton()),
Positioned(
left: 0,
bottom: 0,
child: IconButton(
padding: EdgeInsets.symmetric(vertical: 0, horizontal: 0),
icon: Icon(
Icons.delete_forever,
color: Colors.greenAccent,
size: 32,
),
onPressed: () {
},
),
),
],
),
),
),
),
),
);
}
There is some margin on IconButton.
I think IconButton should be tight on bottom left.
How to remove margin IconButton and screen side?
Actually it's the default padding of the Icon Button only...
That is, the stack is placing the button at bottom left but icon in the button is padded by default.
You can try using Gesture detector with that icon as a child...
You will get different result...
Please correct me if i am wrong..