As the title says, when using Stacks in flutter, only the "last" rendered children can be interacted with if that child overlaps all other children. In my application i have a ListWheelScrollView which is contained in a Stack, and afterwards "styled" with gradients that lie on top of the ScrollView.
This makes more sense when given an example.
There is an existing issue on almost this exact situation here: Flutter- GestureDetector not working with containers in stack
However, it assumes you are working with a gesture detector.
Stack(children: <Widget>[
Container(
height: 250,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
width: _style.fontSize * 1.5,
child: ListWheelScrollView.useDelegate(
controller: fixedExtentScrollController,
physics: FixedExtentScrollPhysics(),
itemExtent: _style.fontSize * 1.5,
childDelegate: ListWheelChildLoopingListDelegate(
children: hours
.map((hour) => hour < 10
? Text(
"0$hour",
style: _style,
)
: Text(
"$hour",
style: _style,
))
.toList())),
),
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
":",
style: _style,
),
SizedBox(
height: 25,
)
],
),
Container(
width: _style.fontSize * 1.5,
child: ListWheelScrollView.useDelegate(
physics: FixedExtentScrollPhysics(),
itemExtent: _style.fontSize * 1.5,
childDelegate: ListWheelChildLoopingListDelegate(
children: minutes
.map((minute) => minute < 10
? Text(
"0$minute",
style: _style,
)
: Text(
"$minute",
style: _style,
))
.toList())),
),
],
),
),
Container(
height: 250,
child: Column(
children: <Widget>[
Container(
height: 75.3,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
colors: [
Colors.white.withOpacity(0.1),
Theme.of(context).scaffoldBackgroundColor
])),
),
Center(
child: Container(
height: 83.3,
width: 220,
decoration: BoxDecoration(
border: Border.all(
color: Color(0xFFc0ccd4), width: 5),
))),
],
),
)
]),
The design works perfectly as expected, however i am no longer able of scrolling since the containers are on top of the scroll widget.
Any workarounds?
You only need to wrap all of your widgets that are not supposed to receive tap events in IgnorePointer widgets.
In the comments it was said that you should use AbsorbPointer, however, you do not want to catch tap events on the ignoring widgets.
In your case, you want to wrap your upper, upper as in top of the stack, Container in an IgnorePointer widget:
Stack(
children: <Widget>[
Container(...),
IgnorePointer(
child: Container(...),
),
],
)
Learn more.
Related
I wanted to get same dynamic height of right widget to left widget in Row Widget.Below I was attaching screenshot of my expected design. Could you help how can do that.
We can see right side date widget is expanding , So I wanted to get the height of left side widget(blue and purple) same as right side widget.
If left side image widget is not possible to expand the height then is any there any possible to create custom widget, Any solution is welcome.
Thanks in advance.
Row(
children: [
Align(
alignment: Alignment.topCenter,
child: Container(
constraints: BoxConstraints(
minHeight: 40.0,
maxHeight: 50.0,
/*maxWidth: 10,
minWidth: 10,*/
),
padding: EdgeInsets.only(top: 0.0),
//height: 98,
width: 20,
child: ShaderMask(
shaderCallback: (bounds) {
return LinearGradient(
colors: [Color(0xff12229F), Color(0xff615FDF)],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
).createShader(bounds);
},
child: ImageIcon(
AssetImage('assets/images/reservations/small_timeline.png'),
color: Colors.white,
size: 40,
),
),
),
),
Expanded(
child: Column(
children: [
pickup(data),
dropoff(data),
],
),
),
],
),
After Using IntrinsicHeight
I was unable to remove default padding around the icons
IntrinsicHeight(
child: Padding(
padding: const EdgeInsets.only(top: 0,bottom: 0),
child: Row(
children: [
Column(
children: [
Padding(
padding: const EdgeInsets.only(top: 4),
child: Icon(
Icons.fiber_manual_record,
size: 18,
color: Color(0xff11219E),),
),
Flexible(
child: Container(
decoration: BoxDecoration(
gradient:
LinearGradient(colors: [Color(0xff11219E), Color(0xff6F6AEB)]),
),
width: 4,
),
),
Padding(
padding: const EdgeInsets.only(bottom: 4),
child: Icon(
Icons.fiber_manual_record,
size: 18,
color: Color(0xff6F6AEB),),
),
],
),
Expanded(
child: Column(
children: [
pickup(data),
dropoff(data),
],
),
),
],
),
),
),
It seems to me that Expanded could be used to expand your widget to full availabe height.
Keep in mind that the Row width will distribution will also expand, since no flex parameter is provided.
You already have an Expanded on the right widget so just add the other one and provide a flex value for both of them.
Some thing like 10 for left and 90 for right should work for you :)
I'm using columns to display 2 texts. 1st text represents the title and 2nd text displays the quotation. I'm trying to split the quotation text into multi-lines using the max line's property, but the text is overlapping with other items. I try to use Expanded and flexible property to overcome this issue but still, I didn't get desired output. This is what I'm trying to do:
Container(
color: Color(0xff1D1D1D),
width: double.maxFinite,
height: responsivness.safeBlockVertical! * 54.55,
// Stories Title
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Text("Stories",
style: Theme.of(context).textTheme.headline1!),
),
// list of Stories
Expanded(
child: ListView.builder(
itemCount: 5,
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) {
return Stack(
clipBehavior: Clip.none,
children: [
Padding(
padding: EdgeInsets.all(h * .014),
child: Container(
width:
responsivness.safeBlockHorizontal! *
47,
height:
responsivness.safeBlockVertical! *
17,
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(10),
color: Colors.amber,
),
),
),
Positioned(
top: h * .19,
left: h * .016,
child: Column(
mainAxisAlignment:
MainAxisAlignment.start,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
"Steve H.",
style: Theme.of(context)
.textTheme
.headline1!,
),
Text(
"I bet away my house and all the money i got",
style: Theme.of(context)
.textTheme
.bodyText2!,
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
],
),
),
],
);
},
),
),
],
),
),
Try below code hope its helpful to you. I think the problem comes from Stack widget so remove your Stack and Positioned Widget, and used Column() widget instead.
Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Text("Stories",
style: Theme.of(context).textTheme.headline1!),
),
// list of Stories
Expanded(
child: ListView.builder(
itemCount: 5,
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) {
return Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: 200,
height: 100,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.amber,
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Steve H.",
),
Text(
"I bet away my house and all the money i got",
style: Theme.of(context).textTheme.bodyText2!,
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
],
),
),
],
);
},
),
),
],
),
),
Your result screen->
Your text is overlapping because of the Stack widget. You can either wrap your text inside a sized box to give a fix width or you can remove Stack widget and use Column instead. I dont find any particular use of stack here, so probably you can remove it without any issues.
Try wrapping with container and specify any width
Container(
width: 100,
child: Text(
"I bet away my house and all the money i got",
style: Theme.of(context).textTheme.subtitle1,
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
),
Try wrapping your overlapping Text with a fixed width SizedBox, and see if it fixes your issue.
Have you tried wrapping the Text in a FittedBox()
I have a problem with the Stack Widget.
I have a Stack that contains two children: an Image wrapped with GestureDetector and a Container
. When i click anywhere on the Container, whoever is last on the Stack children list his onTap
I am extremely new to flutter.
Screenshot of the screen
this code
sonItem(dynamic icon ,String text,Color color){
return GestureDetector(
onTap: () {
print("dddddddddddddddd");
},
child: Container(
width: 70,
height: 100,
margin: EdgeInsets.all(2),
padding: EdgeInsets.all(2),
child: Column(
children: [
Icon(icon ,color: color,),
Text(text)
],
),
),
);
}
I Have a problem with the Stack Widget.
I have a Stack that contains two children: an Image wrapped with GestureDetector and an Container
. When i click anywhere on the Container , whoever is last on the Stack children list his onTap
body: Container(
color: Colors.white,
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
color: Color(0xffF0F0F0),
height: 200,
child: Stack(
overflow: Overflow.visible,
alignment: Alignment.center,
children: [
Positioned(
bottom: -170.0,
child: Container(
padding: EdgeInsets.only(top: 40 , right: 10, left: 10),
height: 250,
decoration: BoxDecoration(
color: Color(0xffFFFFFF),
borderRadius: BorderRadius.circular(30),
border: Border.all(
width: 1,
color: Colors.black,
style: BorderStyle.solid,
),
),
child: Column(
children: [
Text('company',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 24,
color: Colors.black,
),
),
Text("The number 2000"),
RatingBar(
rating: 3,
icon:Icon(Icons.star,size:20,color: Colors.grey,),
starCount: 5,
spacing: 5.0,
size: 20,
isIndicator: false,
allowHalfRating: true,
onRatingCallback: (double value,ValueNotifier<bool> isIndicator){
print('Number of stars--> $value');
//change the isIndicator from false to true ,the RatingBar cannot support touch event;
isIndicator.value=true;
},
color: Colors.amber,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
sonItem(Icons.phone,"call us",Colors.green),
sonItem(Icons.location_on_outlined,"location",Colors.red),
sonItem(Icons.facebook,"FaceBook",Colors.blue),
sonItem(Icons.add_ic_call_outlined,"whatsapp",Colors.green)
],
)
],),
)),
Try below code hope its help to you
Stack(
children: <Widget>[
//your InkWell or GestureDetector Widget
InkWell(
child: Container(
// your child Widget
),
onTap: () {},
),
Positioned(),
]
),
The problem is solved when I delete bottom: -170.0,
But I need it in the design
I'm trying to make this drawing but I'm struggling.
I don't understand how to make the white block of information dynamic. That is to say that it automatically adapts to the size in height of the elements it contains.
I am for the moment obliged to give a defined height (here 200), I would like the size to be automatic. Moreover if I do not give a defined size my gray line on the left side disappears.
The design :
ListTile(
title : Column(
children: [
Container(
width: double.infinity,
child: Row(
children: [
Container(
width: 50,
alignment: Alignment.center,
child: Container(
width: 20,
height: 20,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(40),
border: Border.all(
width: 5,
color: Colors.blue,
style: BorderStyle.solid
)
),
),
),
Text('9:00 am - 9:15 am')
],
)
),
Container(
child: IntrinsicHeight(
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
width : 50,
alignment: Alignment.center,
child: IntrinsicHeight(
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
color: Colors.grey,
width: 3,
height : 200 // if I remove the size it desappear
),
],
),
),
),
Expanded(
child: Container(
margin: EdgeInsets.symmetric(vertical :10),
padding: EdgeInsets.symmetric(vertical: 20, horizontal: 10),
color: Colors.white,
child: Column(
children: [
Text('Titre'),
Text('Info 1'),
Text('Info 2')
],
),
),
)
],
),
),
)
],
),
),
You can try this package for timelines https://pub.dev/packages/timeline_tile.
This package also automatically Sizes your widget height and width.
And for Automatically Sizing your widgets next time, You could use Expanded widget at most places in your code.
Note: An Expanded widget must be a descendant of a Row, Column, or Flex, So Use it carefully.
I think it's much easier with this package, timelines.
TimelineTileBuilder.connected(
connectionDirection: ConnectionDirection.before,
itemCount: processes.length,
contentsBuilder: (_, index) {
//your Container/Card Content
},
indicatorBuilder: (_, index) {
if (processes[index].isCompleted) {
return DotIndicator(
color: Color(0xff66c97f),
child: Icon(
Icons.check,
color: Colors.white,
size: 12.0,
),
);
} else {
return OutlinedDotIndicator(
borderWidth: 2.5,
);
}
},
connectorBuilder: (_, index, ___) => SolidLineConnector(
color: processes[index].isCompleted ? Color(0xff66c97f) : null,
),
),
),
whenever I tap on any of the options of the given 4 buttons, my new data loads in the text and in the 4 option fields.
but the scroll view doesn't come back to its normal position, instead, it remains down, at what position I had left it, previously.
so how to get singlechildscrollview back to its original form after every refresh?
Expanded(
child: Container(
width: MediaQuery.of(context).size.width,
margin:EdgeInsets.only(top: 50.0,bottom: 50) ,
decoration: BoxDecoration(
color: Color(0xFFf2f2f2),
borderRadius: BorderRadius.only(topRight: Radius.circular(40),topLeft:Radius.circular(40) ),
),
child: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Container(
height: 800,
child: (
Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.only(top: 50,left: 20,right: 20),
child: Text(question.replaceAll("\\n", "\n"),style: TextStyle(fontWeight: FontWeight.bold,fontSize: 18),),
),
SizedBox(height: 20),
optionButton(text: option1),
SizedBox(height: 30),
optionButton(text: option2),
SizedBox(height: 30),
optionButton(text: option1),
SizedBox(height: 30),
optionButton(text: option2),
SizedBox(height: 30),
Spacer(),
Column(
children: [
Text("TOTAL"),
Container(
width: MediaQuery. of(context). size. width,
color: Colors.blue,
child:
Center(child: Text(score.toString(),)),),
SizedBox(height: 20)
],),
],
)
),
),
),
),
),
Since I'm not sure what optionButton looks like, you'll probably need this first above your build method:
ScrollController scrollController = new ScrollController();
Then if your optionButton is within the same class, call this within your button function onTap(){} or onPressed(){} :
scrollController.jumpTo(0.0);
Make sure to add the controller to SingleChildScrollView
If optionButton is from a different class, then I'll have to change my answer.
Let me know if this helps!