How to stack two bottom sheet in flutter? - flutter

I want to stack two bottom sheet each other in flutter as show in photo. The upper one is shown when in error state. In photo, it build with alert dialog. I want is with bottom sheet. How can I get it?
Edit:
Here is my code that I want to do. Lower bottom sheet is with pin field, autoComplete. autoComplete trigger StreamController, and then streamBuilder watch Error state and show dialog.
confirmPasswordModalBottomSheet(
BiometricAuthRegisterBloc biometricAuthRegBloc) {
showMaterialModalBottomSheet(
context: context,
builder: (BuildContext context) {
return StreamBuilder(
stream: biometricAuthRegBloc.biometricAuthRegisterStream,
builder: (context,AsyncSnapshot<ResponseObject>biometricAuthRegSnapShot) {
if (biometricAuthRegSnapShot.hasData) {
if (biometricAuthRegSnapShot.data!.messageState ==
MessageState.requestError) {
showModalBottomSheet(context: context, builder:
(BuildContext context){
return Container(
width: 200,height: 200,
child: Center(child: Text('Helllllllllo'),),);
});
}
}
return SizedBox(
width: 100,
height: 300,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(
height: margin30,
),
Text(CURRENT_PIN_TITLE),
SizedBox(
height: margin30,
),
Padding(
padding: const EdgeInsets.only(
left: margin60, right: margin60),
child: PinCodeField(
pinLength: 6,
onChange: () {},
onComplete: (value) {
biometricAuthRegBloc.biometricAuthRegister(
biometricType:_biometricAuthTypeForApi,
password: value);
},
),
),
SizedBox(
height: margin30,
),
Padding(
padding: const EdgeInsets.symmetric(horizontal:
margin80),
child: AppButton(
onClick: () {},
label: CANCEL_BTN_LABEL,
),
),
Container(
padding: const EdgeInsets.all(8.0),
margin:
EdgeInsets.symmetric(vertical: 8.0,
horizontal: 30),
decoration: BoxDecoration(
color: Colors.grey,
border: Border.all(color: Colors.black),
),
child: const Text(
FINGER_PRINT_DIALOG,
textAlign: TextAlign.center,
),
)
],
),
);
});
},
);
}
When I do like that above, I get setState() or markNeedsBuild() called during build. Error and why? Sorry for my previous incomplete question.

I am bit confused with your question but stacking two bottomsheet is just easy. You just need to call the showModalBottomSheet whenever you want it shown to user. You can check out the following implementation:
class HomeScreen extends StatelessWidget {
const HomeScreen({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: ElevatedButton(
onPressed: () {
showModalBottomSheet<void>(
context: context,
builder: (BuildContext context) {
return Container(
height: 500,
color: Colors.amber,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const Text('Modal BottomSheet 1'),
ElevatedButton(
child: const Text('Show second modal 2'),
onPressed: () {
showModalBottomSheet<void>(
context: context,
builder: (BuildContext context) {
return Container(
height: 200,
color: Colors.redAccent,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const Text('Modal BottomSheet 2'),
ElevatedButton(
child: const Text('Close BottomSheet'),
onPressed: () => Navigator.pop(context),
),
],
),
),
);
},
);
},
),
],
),
),
);
},
);
},
child: Text('Show bottom sheet 1'),
),
);
}
}

I have solution. All I need to do is, need to add WidgetBinding.insatance.addPostFrameCallback((timeStamp){showModalBottomSheet()}); in the StreamBuilder return.

Related

List view childs get out of container

I am trying to make a list view only occupy part of the screen, but it keeps growing till the end not respecting the contianer constraints. I tried to use a sizedbox too but it didn' work. List tiles outside the container are shown without any widget inside, but the background is shown anyways
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: pedidos,
builder: (context, AsyncSnapshot<List<Pedido>> snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SizedBox(
height: MediaQuery.of(context).size.height * 0.6,
child: ListView.builder(
itemCount: snapshot.data!.length,
shrinkWrap: true,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Hero(
tag:
"pedidos_card${snapshot.data![index].idPedido}",
child: ListTile(
tileColor: Colors.white,
leading: Container(
width: 50,
height: 50,
decoration: BoxDecoration(
color: Colors.blue,
shape: BoxShape.circle),
child: Center(
child: Text(
style: Theme.of(context)
.textTheme
.headlineSmall,
"${snapshot.data![index].idPedido}"),
),
),
title: Text(
'Pedido: ${snapshot.data![index].idPedido}'),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 10),
Text(
'Estado: ${snapshot.data![index].estadoPedido.last.tipoEstadoPedido.name}'),
SizedBox(height: 10),
Text(
"Cliente: ${snapshot.data![index].cliente.nombre}")
],
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
trailing: Checkbox(
value: pedidosSeleccion
.contains(snapshot.data![index]),
onChanged: (bool? value) {
// value = checkboxList[index];
// setState(() {});
},
),
onTap: () {
bool isSelected = pedidosSeleccion
.contains(snapshot.data![index]);
if (isSelected) {
pedidosSeleccion
.remove(snapshot.data![index]);
} else {
pedidosSeleccion.add(snapshot.data![index]);
}
setState(() {});
},
),
));
}),
),
ElevatedButton(
onPressed: () {}, child: Text('Ver ultima milla')),
],
);
} else {
return Center(
child: CircularProgressIndicator(),
);
}
});
}
}
example
you can use Expanded instead of Sizedbox
eg:-
Column(
children:[
Expanded(flex:9,
child: ListView(
padding: const EdgeInsets.only(top: 10.0),
children: snapshot.map((data) => _buildListItem(context, data)).toList(),
),
),
Expanded(flex:1,
child:
ElevatedButton(
// fill in required params
),
)
])

Lock Sliding Up Flutter

I have a sliding up with two buttons and I want to freeze the widget (sliding up) and unlock after the user taps on a button.
My sliding up code is here.
#override
Widget build(BuildContext context) {
return Container(
color: Colors.white,
child: _body(context),
);
}
Widget _body(BuildContext context) {
return Column(
children: [
Container(
padding: EdgeInsets.symmetric(horizontal: w(30)),
child: Column(
children: [
SizedBox(
height: w(15),
),
Lottie.asset('assets/lottie/privacy_policy.json', width: w(150)),
SizedBox(
height: w(20),
),
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
AboutDetailsPage.show(
context, FlutterI18n.translate(context, "about.privacyPolicy"), PrivacyDetailsBody(), true);
},
child: Align(
alignment: Alignment.centerLeft,
child: Text(
FlutterI18n.translate(context, "about.privacyPolicyUpdateDescription"),
style: textStyle17().copyWith(color: TecnoColors.theme().grey1, height: 1.5),
),
),
),
],
),
),
SizedBox(
height: w(35),
),
Container(
padding: EdgeInsets.symmetric(horizontal: w(15)),
child: Column(
children: [
Container(
child: TecnoButton(FlutterI18n.translate(context, "about.privacyPolicyUpdateAllow"),
backgroundColor: TecnoColors.theme().blue2),
),
SizedBox(
height: w(15),
),
Container(
child: GestureDetector(
onTap: () {
getUserBLoC(context).logout();
Navigator.pushReplacement(
context,
new CupertinoPageRoute<Null>(
settings: RouteSettings(name: 'LoginPage'),
builder: (BuildContext context) => new BoxLoginPage(loginPageMode.LOGIN),
));
},
child: Text(
FlutterI18n.translate(context, "about.privacyPolicyUpdateDeny"),
style: textStyle16().copyWith(color: TecnoColors.theme().blue2),
),
),
)
],
),
)
],
);
}
Basically if the user open this widget, the user can not close it, just after he taps on a button.
After the sliding up appears, the sliding up can not close, even if the user click out of. The sliding up can close just if user taps on one of widgets button
You can wrap you sliding up will WillPopScope and on will pop you can check if user has pressed the button the make
Navigator.pop(context);
else, show some message

How to show custom dialog at the top center of the screen in flutter?

I am going to show a custom dialog at the top center of the screen.
I've attached a screenshot .
How can I accomplish this? Default position of Dialog is center of the screen.
showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
);
You can use Align and Material widget. (Alignment.topCenter) i.e
void showCustomDialog(BuildContext context, String message) {
showDialog(
barrierDismissible: false,
context: context,
builder: (BuildContext cxt) {
return Align(
alignment: Alignment.topCenter,
child: Padding(
padding: EdgeInsets.all(16),
child: Material(
color: Colors.green,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15)),
child: Padding(
padding: EdgeInsets.all(16),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(
children: [
InkWell(
onTap: () {
Navigator.of(context).pop();
},
child: Image.asset("assets/close.png")),
SizedBox(width: 16),
Expanded(
child: Text(
message,
style: TextStyle(
color: Colors.white,
),
),
),
],
),
],
),
),
),
),
);
},
);
}

I am getting findAncestorStateOfType error in flutter . What should I do about this? I am stuck here

How to solve findAncestorStateOfType error in Flutter? I am not able to navigate to other page using these codes. What is wrong with this code?
The error which I am getting is this
The method 'findAncestorStateOfType' was called on null.
Receiver: null
Tried calling: findAncestorStateOfType()
My code is this:
// entry point for the app,
// the => operator is shorthand for {} when there is only one line of code
void main() {
runApp(MaterialApp(
home: HomeRoute(),
));
}
// the root widget of our application
class HomeRoute extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Color(0xFFFAAC98),
appBar: AppBar(
backgroundColor: Color(0xFFFAAC98),
),
body: myLayoutWidget(),
),
);
}
}
// replace this method with code in the examples below
Widget myLayoutWidget() {
return Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
width: 300,
height: 50,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30.0),
color: const Color(0xff89C5CC),
),
child: Center(
child: new Text(
'Gram Panchayat App',
style: TextStyle(
fontSize: 27,
fontWeight: FontWeight.bold,
color: Color(0xFF2F3676)),
),
),
),
),
Row(
children: [
Padding(
padding: const EdgeInsets.only(right: 18.0, top: 18.0),
child: Image.asset(
'assets/images/human1.png',
width: 150,
height: 150,
),
),
Padding(
padding: const EdgeInsets.only(left: 58.0),
child: elevatedButton(),
),
],
),
new Row(
children: [
Padding(
padding: const EdgeInsets.only(left: 28.0),
child: elevatedButton1(),
),
Padding(
padding: const EdgeInsets.only(top: 58.0, left: 68.0),
child: new Image.asset(
'assets/images/human2.png',
width: 200,
height: 170,
),
),
],
),
Padding(
padding: const EdgeInsets.only(left: 60.0),
child: Row(children: [
new Image.asset(
'assets/images/img3.png',
width: 180,
height: 80,
),
]),
)
],
),
);
}
ElevatedButton elevatedButton() => ElevatedButton(
onPressed: () {
BuildContext context;
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondRoute()),
);
},
child: Text('Citizen'),
);
ElevatedButton elevatedButton1() =>
ElevatedButton(onPressed: () {}, child: Text('Staff'));
class SecondRoute extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Second Route"),
),
body: Center(
child: ElevatedButton(
onPressed: () {
Navigator.pop(context);
},
child: Text('Go back!'),
),
),
);
}
}```
*Please help me I am stuck. I have gone through many sites but couldnt find what is wrong and the solution also.*
make myLayoutWidget() inside your HomeRoute class
and use
Navigator.of(context,rootNavigator:true).pop();
instead of
Navigator.pop(context);

Future builder not updating once i have resposne

I have a page where once i have response i need to display items
here is my code
It keeps on showing loader and futureBuilder never gets triggered
#override
void initState() {
super.initState();
helper.getString(TOKEN_ID).then((value) {
userResponseFuture = repos.getUserDetails(value);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
margin: EdgeInsets.all(10),
alignment: Alignment.center,
color: Colors.white,
child: FutureBuilder<UserResponse>(
future: userResponseFuture,
builder: (context, snapShot) {
if (snapShot.hasData) {
return Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
CircleAvatar(
radius: 50.0,
backgroundImage: NetworkImage(snapShot
.data.profilePictureURL ??
"https://cdn.mos.cms.futurecdn.net/5e7ehPZf5RT6Jt2H9cQP6k-1024-80.jpg.webp"),
backgroundColor: Colors.brown,
),
FlatButton(
child: Row(
children: [
Icon(Icons.edit),
Text("Edit profile Image"),
],
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
ProfilePicScreen()));
},
),
],
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
snapShot.data.firstName +
" " +
snapShot.data.lastName,
style: TextStyle(color: Colors.blue.shade900)),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(snapShot.data.email,
style: TextStyle(color: Colors.blue.shade900)),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(snapShot.data.phoneNo ?? "",
style: TextStyle(color: Colors.blue.shade900)),
)
],
);
} else {
return SizedBox(
height: 30.0,
width: 30.0,
child: CircularProgressIndicator(
strokeWidth: 2.0,
));
}
},
)),
);
}
}
You need to add setState after assign a value to userResponseFuture;
helper.getString(TOKEN_ID).then((value) {
userResponseFuture = repos.getUserDetails(value);
setState((){})
});
because it is being after build method and your widget can't call the right future function.