Flutter : How to disable drag down to close showModalBottomSheet - flutter

I want to disable drag down to close the showModalBottomSheet
I have already tried using enableDrag:false,
When i'm using enableDrag:false, is showing me below error
Below is my code
modal(BuildContext context) {
showModalBottomSheet(
context: context,
enableDrag:false,
isDismissible: false,
backgroundColor: Colors.transparent,
builder: (context) {
return Container(
width: MediaQuery.of(context).size.width,
child: Stack(
alignment: Alignment.topCenter,
children: <Widget>[
Container(
width: MediaQuery.of(context).size.width,
padding: EdgeInsets.only(top: 30),
child: Stack(
alignment: Alignment.topCenter,
children: <Widget>[
ClipPath(
clipper: OvalTopBorderClipper(),
child: Container(
width: MediaQuery.of(context).size.width,
padding: EdgeInsets.only(top: 80),
color: Colors.white,
height: 440,
child: Text("This is a modal bottom sheet !"),
),
),
],
),
),
Positioned(
top: 5,
child: Container(
width: 50.0,
height: 53.0,
child: Center(
child: Text(
"K",
style: TextStyle(
color: AppColors.textColor, fontSize: 20.0),
),
),
padding:
EdgeInsets.symmetric(horizontal: 10.0, vertical: 10.0),
decoration: BoxDecoration(
border:
Border.all(color: AppColors.textColor, width: 2)),
),
),
],
),
);
});
}
I have already check this post
Disable drag down to close showModalBottomSheet
If need more information please do let me know. Thanks in advance. Your efforts will be appreciated.

enableDrag is not available in showModalBottomSheet. I don't think it was ever available in stable channel. According to comments from the link at that time it was available in Master channel. But second answer from that link works well
builder: (context) => GestureDetector(
onVerticalDragDown: (_) {},
child: ...,
here is documentation to showModalBottomSheet . You can always tap into the showModalBottomSheet and customise it.. According to doc
BottomSheet, which becomes the parent of the widget returned by the function passed as the builder argument to showModalBottomSheet.
and BottomSheet has enableDrag parameter.

As of 2020-05-06 and flutter v1.17.1 enableDrag is available on showModalBottomSheet

Related

Screen is reloading every element/api inside when keyboard opens/closes inside a show dialog

I have a screen, which contains a button, when tapping on that button, a showDialog function is been called, which displays a popup with a textfield, whenever the keyboard appears or disappears, the whole screen reloads, even the api calls, as if I'm calling setState ,
the class is a StatefulWidget
Button trigger:
CustomButton(buttonName: defaultLanguage == "en" ? "Settings" : "Ajustes", backgroundColor:
appVioletColor, onPress: () {
PopupScreen().displayDialog(context, isLargeScreen);
}, isLanguage: true, style: Styles.generateWeightFont(Colors.white, isLargeScreen ? 18 : 9, FontWeight.w400),
image: new AssetImage('assets/Settings/setting.png'), isLargeScreen: isLargeScreen ,),
PopupScreen code:
class PopupScreen {
final pinCodeReader = TextEditingController();
Future displayDialog(BuildContext context, bool isLargeScreen) {
return
showDialog(
barrierDismissible: true,
useSafeArea: false,
context: context,
builder: (BuildContext context) =>
Material(
type: MaterialType.transparency,
child: Center(
child:
Padding(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom),
child:
Container(
color: Colors.white,
height: MediaQuery.of(context).size.height / 2,
width: MediaQuery.of(context).size.width / 1.5,
child:
ListView(
children:[
Column(
children: [
Container(
alignment: Alignment.topCenter,
height: 12,
width: 411,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/WelcomeScreen/purple-top-rec.png"),
)
),
),
const SizedBox(height: 24,),
Container(
width: 200,
height: 100,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/WelcomeScreen/pin_icon.png"),
)
),
),
const SizedBox(height: 17,),
Container(
padding: EdgeInsets.only(left: 25),
alignment: Alignment.topLeft,
child: Text("Please enter security pin", style:
Styles.generateWeightFont(Colors.black, 24, FontWeight.w400),),
),
const SizedBox(height: 15,),
Container(
padding: EdgeInsets.only(left: 25, right: 25),
child: buildCommonTextField("", pinCodeReader, whiteGrey, TextInputType.number),
),
const SizedBox(height: 12,),
Container(
alignment: Alignment.center,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
width: 100,
height: 50,
alignment: Alignment.center,
decoration: BoxDecoration(
border: Border.all(color: greyColor, width: 1)
),
child: Text("Cancel", style: Styles.generateWeightFont(greyColor, 18, FontWeight.w700),),
),
const SizedBox(width: 10,),
Container(
width: 114,
height: 48,
alignment: Alignment.center,
decoration: BoxDecoration(
color: appVioletColor,
border: Border.all(color: greyColor, width: 1)
),
child: Text("Done", style: Styles.generateWeightFont(Colors.white, 18, FontWeight.w700),),
),
],
),
)
],
),
],
),
),
)
)
)
);
}
}
Anyone has an idea what's going on?
thanks
When the keyboard appears or disappears, it is an animation that can last for a little while. During this, the available screen area for your app is constantly changing: on opening the keyboard it shrinks, on closing the keyboard it grows.
Whenever you use MediaQuery.of(context) in your code, Flutter engine will keep notifying your widget about media changes, causing rebuilds. So in your case the widget is rebuilt on every animation frame caused by opening or closing the keyboard.
This is an intended behaviour, for example if the user rotates the screen, the available MediaQuery.of(context).size will change, and it should result in a rebuild. If you'd like to avoid this, organize you code in a way that it calls MediaQuery.of(context) only in those parts where you want to get updates about media parameters constantly.

How to reposition a fixed widget in flutter

I'm building an AR app with Flutter and using the ar_flutter_plugin.
The position of the AR widget seems to be fixed to the top left and it doesn't move anywhere else. Whatever the other widgets in the tree, doesn't change anything. It's always at top left corner (see image).
It works with a dummy widget just fine (compare second img).
Child Ar widget
Widget build(BuildContext context) {
return SizedBox(
width: widget.width,
height: widget.height,
child: Column(
children: [
Expanded(
child: Column(children: [
Expanded(
child: ARView(
onARViewCreated: onARViewCreated,
planeDetectionConfig:
PlaneDetectionConfig.horizontalAndVertical,
),
),
Align(
alignment: Alignment(1, 1),
child: FloatingActionButton(onPressed: takePicture))
]),
),
],
));
}
Parent Widget
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Title'),
),
key: scaffoldKey,
backgroundColor: FlutterFlowTheme.of(context).primaryBackground,
body: SafeArea(
child: GestureDetector(
onTap: () => FocusScope.of(context).unfocus(),
child: Stack(
children: [
Container(
width: 350,
height: 350,
child: ObjectsOnPlanesWidget(
// child: custom_widgets.ArPlaceholder(
width: double.infinity,
height: double.infinity,
modelUrl: widget.modelUrl,
),
),
Align(
alignment: AlignmentDirectional(-0.23, -0.92),
child: Padding(
padding: EdgeInsetsDirectional.fromSTEB(8, 24, 8, 24),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
width: 30,
height: 30,
decoration: BoxDecoration(
color:
FlutterFlowTheme.of(context).secondaryBackground,
borderRadius: BorderRadius.circular(12),
),
child: InkWell(
onTap: () async {
Navigator.pop(context);
},
child: Icon(
Icons.chevron_left,
color: Colors.black,
size: 24,
),
),
),
Text(
'Try On',
style: FlutterFlowTheme.of(context).bodyText1,
),
Container(
width: 30,
height: 30,
decoration: BoxDecoration(
color:
FlutterFlowTheme.of(context).secondaryBackground,
borderRadius: BorderRadius.circular(12),
),
child: Icon(
Icons.share_outlined,
color: Colors.black,
size: 24,
),
),
],
),
),
),
Align(
alignment: AlignmentDirectional(0, 0.95),
child: Container(
width: 50,
height: 50,
decoration: BoxDecoration(
color: FlutterFlowTheme.of(context).secondaryBackground,
borderRadius: BorderRadius.circular(12),
),
child: Icon(
Icons.photo_camera,
color: Colors.black,
size: 24,
),
),
),
],
),
),
),
);
}
I want to put the camera in the background and put other widgets (such as photo-taking-button) on top of it.
How do I reposition it into a container? At least under the App Bar?
Logically this should have worked, what i would suggest you try would be to first have a SafeArea widget.
SafeArea(
child: build(buildContext),
),
I had a similar issue in the past and using this solved it.
Also, there seems to be an open issue which seems related to this with the following possible solution :
With Flutter 2.10.5. it works without problems. This seems to be a Flutter 3 problem.
The way platforms views are rendered was changed in the 3.0 release.
probably same issue:
flutter/flutter#106246
explained here:
flutter/flutter#103630
I hope this will be fixed in new Flutter 3 releases soon.
And also this
I try the master channel Flutter v3.1.0-0.0.pre.1372 and the issue is fixed there.
Fixed will come to a stable channel soon with Flutter v3.1.0.
Also, I am not sure why are you using SizedBox as your parent widget.
Why not try a basic Container instead?
Good luck, Let me know if I can help with anything else

How to disable Inkwell image button in flutter

I would like to make the inkwell image button to be disabled. I can disable onTap event, but can't make gray like disabled button. I tried with adding this code
decoration: new BoxDecoration(color:Colors.grey.withOpacity(0.6)),
But it doesn't work as I want.
My code:
child: Container(
decoration:
new BoxDecoration(color: Colors.grey.withOpacity(0.6)),
child: Material(
//elevation: 4.0,
clipBehavior: Clip.none,
color: Colors.black,
child: Stack(
alignment: Alignment.center,
fit: StackFit.passthrough,
children: [
Ink.image(
image: AssetImage(ihaveheard_imagepath),
fit: BoxFit.cover,
width: MediaQuery.of(context).size.width / 4 * 3,
height: MediaQuery.of(context).size.width / 6,
child: InkWell(onTap: () {}),
),
Align(
alignment: Alignment.center,
child: Padding(
padding: EdgeInsets.all(8.0),
child: InkWell(
child: Text(
LocaleKeys.ihaveheard,
style: TextStyle(
fontSize:
MediaQuery.of(context).size.width / 30,
color: Colors.white),
).tr(),
onTap: () {
ihaveheard_imagepath =
"assets/images/greenbutton.png";
setState(() {});
},
),
),
)
],
),
),
),
child:
IgnorePointer(
ignoring: disableBtn, //true or false
child: Container(
foregroundDecoration: disableBtn
? BoxDecoration( //this can make disabled effect
color: Colors.grey,
backgroundBlendMode: BlendMode.lighten)
: null,
child: ...
You can use IgnorePointer as parent widget to prevent tab event.
IgnorePointer(
ignoring: disableBtn, //true, false
child: yourWidget()
You can pass null to decoration to show default based on tappable state
Container(
decoration: disableBtn? BoxDecoration(...): null,
.....
)

How to overlap button on BottomSheet in Flutter?

In my design, there is a close button in the BottomSheet. I have tried Stack. But it didn't work. Does anyone know how to achieve the result? Thanks :)
modalBottomSheet(context) {
return showModalBottomSheet(
context: context,
builder: (context) {
return Stack(
children: [
Container(
child: Text('Sample Text'),
),
Container(
height: 50,
width: 50,
decoration: BoxDecoration(
color: Colors.red,
shape: BoxShape.circle,
),
),
],
);
}
);
}
So I've been trying around for a bit, and this seems to work as you explained.
modalBottomSheet(context) {
return showModalBottomSheet(
context: context,
builder: (context) {
// using a scaffold helps to more easily position the FAB
return Scaffold(
body: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(
width: double.maxFinite,
),
Padding(
padding: EdgeInsets.all(30.0),
child: Text("Text in the sheet"),
),
],
),
// translate the FAB up by 30
floatingActionButton: Container(
transform: Matrix4.translationValues(0.0, -30, 0.0), // translate up by 30
child: FloatingActionButton(
onPressed: () {
// do stuff
print('doing stuff');
},
child: Icon(Icons.add),
),
),
// dock it to the center top (from which it is translated)
floatingActionButtonLocation: FloatingActionButtonLocation.centerTop,
);
});
}
The meat of the solution here is to transform the Container which contains the FAB. I got this idea from this older SO answer to a somewhat related question.
The result looks like this:
You'll probably have to make some more edits to achieve the exact result you desire, but I hope this sets you on the right path.
Edit
When, in the above solution, you want to press the FAB, and you tap the top half, the onPressed handler fires, but the modal also closes. You should probably use a WillPopScope that only pops when the actual button is pressed (and not the area around/above it). If you think it's fine pressing anywhere above it as well, you can just leave it as-is.
showModalBottomSheet(
backgroundColor: Colors.transparent,
context: context,
builder: (BuildContext context) {
return Stack(clipBehavior: Clip.none, children: [
Container(
decoration: const BoxDecoration(
color: Colors.white,
borderRadius:
BorderRadius.vertical(top: Radius.circular(20))),
height: 220.h,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 10.0, vertical: 16),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
ElevatedButton(
color: Colors.green,
onPressed: () {},
child: const Center(child: Text('Remove')))
],
),
),
),
),
Positioned(
top: -30.h,
right: 12.w,
child: FloatingActionButton(
onPressed: () {},
child: const Icon(Icons.close),
)),
]);
},
)

How to arrange the items correctly in flutter

I try to make design of page of display comment. I need make page design is as follows: list at up and then Text Field at the bottom.So user will can see all comment and send new comment.
Something like photo:
but I have same problem with display.
This is my code:I make it like that now but now I can see list just without text field at the bottom
#override
Widget build(BuildContext context) {
return FutureBuilder<List<Flowerdata>>(
future: fetchFlowers(),
builder: (context, snapshot) {
if (!snapshot.hasData) return Center(
child: CircularProgressIndicator()
);
return ListView(
children: snapshot.data
.map((data) => Column(children: <Widget>[
GestureDetector(
onTap: ()=>{
getItemAndNavigate(data.id, context)
},
child: Row(
children: [
Container(
width: 100,
height: 100,
margin: EdgeInsets.fromLTRB(10, 0, 10, 0),
child: ClipRRect(
borderRadius: BorderRadius.circular(8.0),
child:
Image.network(data.flowerImageURL,
width: 200, height: 100, fit: BoxFit.cover,))),
Flexible(child:
Text(data.flowerName,
style: TextStyle(fontSize: 18))
),
]),),
Divider(color: Colors.black),
],))
.toList(),
);
Container(
width: 280,
padding: EdgeInsets.all(10.0),
child: TextField(
controller: naameController,
autocorrect: true,
decoration: InputDecoration(hintText: 'Enter Your Name Here'),
)
);
},
);
}
How can I arrange the items correctly?
First, your Container widget is unreachable, you should fix it then you can wrap your widgets with Column and wrap ListView with Expanded widget after giving height to Container. It will fix your problem.
But i have some suggestions about ListView. Why you did not use ListView.separated? If you use separated method you can delete map and your Divider.
Also when i looked your design, your list items looks like a card. You can use Card widget beside of GestureDetector.
I hope this will help you, if not i will glad to help you.
Edit: Here is sample code based on your question and my answer;
Column(
children: [
Expanded(
child: ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int i) {
InkWell(
onTap: () => getItemAndNavigate(snapshot.data[i].id, context),
child: Card(
child: Row(
children: <Widget>[
Container(
width: 100,
height: 100,
margin: EdgeInsets.fromLTRB(10, 0, 10, 0),
child: ClipRRect(
borderRadius: BorderRadius.circular(8.0),
child: Image.network(snapshot.data[i].flowerImageURL,
width: 200, height: 100, fit: BoxFit.cover,),
),
),
Flexible(
child: Text(
snapshot.data[i].flowerName,
style: TextStyle(fontSize: 18),
),
),
]
),
),
);
},
),
),
Container(
width: 280,
padding: EdgeInsets.all(10.0),
child: TextField(
autocorrect: true,
decoration: InputDecoration(hintText: 'Enter Your Name Here'),
),
),
],
),
You are placing the TextField in the position after returning ListView, which make it dead code. You can add it at the end of your ListView children list or place a Stack outside to place both the ListView and TextField inside.