I want to get an image like the one below with Flutter. How should I provide this? I can provide this with container border, but I want to put a wigdet instead of border. For example, I want to wrap a circle widget with a Circleprogress bar. progress should grow as widget grows
Stack(
children: [
Container(
padding: EdgeInsets.all(20),
decoration: BoxDecoration(
color: context.themeCopyExtensions.backgroundColor,
shape: BoxShape.circle,
border: Border.all(width: 5),
boxShadow: [
BoxShadow(
color: context.themeCopyExtensions.backgroundColor,
blurRadius: 10)
]),
child: ImagesHelper.imagesHelper.getAssetImage(imageName: "logo"),
),
],
);
I implemented using 'Stack' widget and 'CircularProgressIndicator'.
(Need to adjust each widget size)
/// Flutter code sample for CircularProgressIndicator
// This example shows a [CircularProgressIndicator] with a changing value.
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
/// This is the main application widget.
class MyApp extends StatelessWidget {
const MyApp({Key key}) : super(key: key);
static const String _title = 'Flutter Code Sample';
#override
Widget build(BuildContext context) {
return const MaterialApp(
title: _title,
home: MyStatefulWidget(),
);
}
}
/// This is the stateful widget that the main application instantiates.
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({Key key}) : super(key: key);
#override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}
/// This is the private State class that goes with MyStatefulWidget.
/// AnimationControllers can be created with `vsync: this` because of TickerProviderStateMixin.
class _MyStatefulWidgetState extends State<MyStatefulWidget>
with TickerProviderStateMixin {
AnimationController controller;
#override
void initState() {
controller = AnimationController(
vsync: this,
duration: const Duration(seconds: 5),
)..addListener(() {
setState(() {});
});
controller.repeat(reverse: true);
super.initState();
}
#override
void dispose() {
controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Container(
width: 300,
child: Stack(
alignment: Alignment.center,
children: <Widget>[
CircularProgressIndicator(
value: controller.value,
strokeWidth: 5,
semanticsLabel: 'Linear progress indicator',
),
Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Color(0xFF431CEE),
),
child: Icon(
Icons.audiotrack,
color: Colors.white,
size: 35,
),
),
],
),
),
],
),
),
);
}
}
I think I would use the FloatingActionButton to do this. You can put it anywhere in the widget tree and achieve your intended goal with much less effort than creating custom painter. It will always sit on top of your whole stack of pages using its built in overlay functionality. If you also don't want it to be clickable, you can always set the onPressed to null. One possible example is:
FloatingActionButton(
onPressed: () {},
child: Container(
padding: EdgeInsets.all(20),
decoration: BoxDecoration(
color: context.themeCopyExtensions.backgroundColor,
shape: BoxShape.circle,
border: Border.all(width: 5),
boxShadow: [
BoxShadow(
color: context.themeCopyExtensions.backgroundColor,
blurRadius: 10,
)
],
image: DecorationImage(
image: ImagesHelper.imagesHelper.getAssetImage(imageName: "logo"),
fit: BoxFit.cover,
)),
),
)
Related
How to change the current index tabbar.
I have three tabbar with images when I click index 0 the height will
change to big like focus.
I have tried several ways but it didn't work.
when I select it will work only one index
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(home: MyApp()));
}
class MyApp extends StatefulWidget {
MyApp({Key? key}) : super(key: key);
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: DefaultTabController(
length: 3,
child: Scaffold(
appBar: AppBar(
backgroundColor: Colors.transparent,
toolbarHeight: 100,
bottom: TabBar(
indicator: BoxDecoration(
border: Border.all(width: 1, color: Colors.deepOrange),
borderRadius: BorderRadius.circular(10),
color: Colors.transparent),
tabs: [
Card(
child: Image(
image: AssetImage("assets/box.png"),
),
),
Card(
child: Image(image: AssetImage("assets/box.png")),
),
Card(
child: Image(image: AssetImage("assets/box.png")),
),
]),
),
body: TabBarView(
children: [
AmazonBox(),
AmazonGift(),
AmazonSave(),
],
)),
));
}
}
If you want to give the active tab icon a bigger size than the other icons, you have to create your own TabController first. Then add a listener to that TabController to update your Widget with setState() every time the tab index changes. Compare the tab icon index with the current index of the TabController to decide whether to display a big or small tab icon.
import 'package:flutter/material.dart';
void main() {
runApp(const MaterialApp(home: MyApp()));
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
late final _tabController = TabController(length: 3, vsync: this)
..animation?.addListener(() => setState(() {}));
#override
Widget build(BuildContext context) {
return MaterialApp(
home: DefaultTabController(
length: 3,
child: Scaffold(
appBar: AppBar(
backgroundColor: Colors.transparent,
toolbarHeight: 100,
bottom: TabBar(
controller: _tabController,
indicator: BoxDecoration(
border: Border.all(width: 1, color: Colors.deepOrange),
borderRadius: BorderRadius.circular(10),
color: Colors.transparent),
tabs: [
SizedBox(
width: _tabController.index == 0 ? 100 : 50,
height: _tabController.index == 0 ? 100 : 50,
child: const Image(
image: AssetImage("assets/box.png"),
),
),
SizedBox(
width: _tabController.index == 1 ? 100 : 50,
height: _tabController.index == 1 ? 100 : 50,
child: const Image(image: AssetImage("assets/box.png")),
),
SizedBox(
width: _tabController.index == 2 ? 100 : 50,
height: _tabController.index == 2 ? 100 : 50,
child: const Image(image: AssetImage("assets/box.png")),
),
]),
),
body: TabBarView(
children: const [
AmazonBox(),
AmazonGift(),
AmazonSave(),
],
)),
));
}
}
How to achieve this dual-curved layout on Flutter? double.infinity for height and width. Never mind about the Text and color, any color will do. Thank you :)
You can use a Column with two Flexible widgets, both of them containing a Stack as a child, and two Container widgets in each. This way the containers will be on top of each other, and one of them can have a decoration with rounded corners:
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return const MaterialApp(
home: Scaffold(body: MyWidget()),
);
}
}
class MyWidget extends StatelessWidget {
const MyWidget({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Column(children: [
Flexible(
flex: 1,
child: Stack(children: [
Container(
color: Colors.blue,
),
Container(
decoration: const BoxDecoration(
borderRadius:
BorderRadius.only(bottomRight: Radius.circular(100)),
color: Colors.yellow,
))
])),
Flexible(
flex: 3,
child: Stack(children: [
Container(
color: Colors.yellow,
),
Container(
decoration: const BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.only(topLeft: Radius.circular(100)),
))
]),
)
]);
}
}
The result will be like this:
Thank you for your answer #Peter Koltai you answered perfectly correct. Thank you
I have a variable inside a statefull widget which contains a string value. I called a widget from another dart file. I need to change the value of the variable in statefull widget from this widget. I have tries valuelistanablebuilder but it is only listen to value when function called inside that dart file. Please tell me a way and example code on how to do it.
import 'package:flutter/material.dart';
import 'package:messaging_service/components/app_bar.dart';
import 'package:messaging_service/components/home_pages/all_messages.dart';
import 'package:messaging_service/components/home_pages/stories.dart';
import 'package:messaging_service/components/search_bar.dart';
import 'package:messaging_service/components/strings.dart';
import 'package:messaging_service/components/style.dart';
class HomeMobile extends StatefulWidget {
const HomeMobile({Key? key}) : super(key: key);
#override
_HomeMobileState createState() => _HomeMobileState();
}
class _HomeMobileState extends State<HomeMobile> {
var currentPage = 'all';
TextEditingController searchChatController = TextEditingController();
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: lightColor,
appBar: AppBarHomeMobile(context),
body: SingleChildScrollView(
child: Column(
children: [
AppBarHomeExtend(),
const SizedBox(
height: 10,
),
//To Call a Widget
],
),
),
);
}
}
In this AppBarHomeExtend() has some buttons..
Widget AppBarHomeExtend() {
return Container(
height: 80,
decoration: BoxDecoration(
color: lightColor,
boxShadow: [
BoxShadow(color: darkColor, blurRadius: 5),
],
borderRadius: const BorderRadius.only(
bottomLeft: Radius.circular(35), bottomRight: Radius.circular(35))),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
HRButtons('All Messages', () {}),
HRButtons('Groups', () { }),
HRButtons('Stories', () {}),
HRButtons('Calls', () {}),
],
),
);
}
When called these buttons I need to change the value of variable currentPage from that statefull widget.
First, turn your AppBarHomeExtend into a proper widget which takes a callback function as argument:
import 'package:flutter/material.dart';
class ExtendedAppBar extends StatelessWidget {
final void Function(String) setPage;
const ExtendedAppBar({Key? key, required this.setPage}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
height: 80,
decoration: BoxDecoration(
color: Colors.blue.shade50,
boxShadow: [
BoxShadow(color: Colors.blue.shade900, blurRadius: 5),
],
borderRadius: const BorderRadius.only(bottomLeft: Radius.circular(35), bottomRight: Radius.circular(35))),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
HRButtons('All Messages', () => setPage('All Messages')),
HRButtons('Groups', () => setPage('Groups')),
HRButtons('Stories', () => setPage('Stories')),
HRButtons('Calls', () => setPage('Calls')),
],
),
);
}
}
Then in your _HomeMobileState class, use this:
ExtendedAppBar(
setPage: (String value) {
setState(() {
currentPage = value;
});
},
),
you better need to use a state management to get a better solution . check this package
floatingActionButton: FloatingActionButton(
key: const Key('increment_floatingActionButton'),
/// Calls `context.read` instead of `context.watch` so that it does not rebuild
/// when [Counter] changes.
onPressed: () => context.read<Counter>().increment(),
tooltip: 'Increment',
child: const Icon(Icons.add),
),
class Count extends StatelessWidget {
const Count({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Text(
/// Calls `context.watch` to make [Count] rebuild when [Counter] changes.
'${context.watch<Counter>().count}',
key: const Key('counterState'),
style: Theme.of(context).textTheme.headline4);
}
}
when I load the builder for the first time , all of my cards are the same size for a second before jumping to the correct sizes and proportions ,does anyone know how I can adjust this so that they are in the right sizes from the get go?
Strangely enough when I replace my Padding & Card widget with just a container full of the images, it seems to spawn in the correct sizes , however I need them to be cards for my later layout.
(I also plan on throwing it all into a widget class instead of putting all this code in my main and rather just returning a CustomScroller.)
Please check the following Gifs:
Gif Of Animation Glitch
Gif of Animation working fine when just container is used
Any help fixing the initial loading would be wildly appreciated! :)
import 'package:flutter/material.dart';
import 'package:blink/widget/customScroller.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
PageController pageController;
List<String> images = [
"https://iso.500px.com/wp-content/uploads/2014/07/big-one.jpg",
"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRXRfe-GzBFRQzv8udHMCshqQGAj2JD5SGsR7CoyWP_HqFapJCYSA&s",
"https://ichef.bbci.co.uk/wwfeatures/live/976_549/images/live/p0/7w/b9/p07wb9xk.jpg",
"https://images.unsplash.com/photo-1501785888041-af3ef285b470?ixlib=rb-1.2.1&w=1000&q=80"
];
#override
void initState() {
// TODO: implement initState
pageController = PageController(initialPage: 1, viewportFraction: 0.77);
}
#override
Widget build(BuildContext context) {
return new Scaffold(
body: PageView.builder(
controller: pageController,
itemCount: images.length,
itemBuilder: (context,position){
return customScroller(position);
}),);
}
customScroller(int index) {
return AnimatedBuilder(
animation: pageController,
builder: (context, widget) {
double val = 1;
if(pageController.position.haveDimensions){
val = pageController.page - index;
val = 1 - (val.abs()*0.3).clamp(0.0,1.0);}
return Center(
child: SizedBox(
height: Curves.easeInOut.transform(val) *300,
width: Curves.easeInOut.transform(val) *400,
child: widget,
),
);
},
// child: Container(
// margin: EdgeInsets.all(10),
// child: Image.network(images[index],fit:BoxFit.cover),
// ),
// When I use the above code as the child instead of the padding with the card in it seems to spawn correctly
child: Padding(
padding: EdgeInsets.fromLTRB(0, 15, 0, 15),
child: Container(
child: Card(
color: Colors.white70,
elevation: 9,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0),
),
clipBehavior: Clip.antiAlias,
child: Container(
color: Colors.white,
padding: EdgeInsets.all(5),
child: Row(
children: <Widget>[
Expanded(
flex: 2,
child: Container(
height: double.infinity,
child: ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20.0),
topRight: Radius.circular(0.0),
bottomRight: Radius.circular(0.0),
bottomLeft: Radius.circular(20.0)),
child: new Image.network(
images[index],
fit: BoxFit.cover,
),
),
),
),
],
),
),
),
),
)
);
}
}
What you are missing is that the AnimatedBuilder build method runs only if there is some animation. Not at the very beginning. So this is why the size changes if you are scrolling and not before.
Your child widget is not wrapped with a transformer widget (or sized box) so it stays the same for all indexes (at the beginnen - the builder has not run yet). In my example I wrapped the child also with a SizedBox and i gave val some initial value.
Working example:
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
PageController pageController;
List<String> images = [
"https://iso.500px.com/wp-content/uploads/2014/07/big-one.jpg",
"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRXRfe-GzBFRQzv8udHMCshqQGAj2JD5SGsR7CoyWP_HqFapJCYSA&s",
"https://ichef.bbci.co.uk/wwfeatures/live/976_549/images/live/p0/7w/b9/p07wb9xk.jpg",
"https://images.unsplash.com/photo-1501785888041-af3ef285b470?ixlib=rb-1.2.1&w=1000&q=80"
];
#override
void initState() {
// TODO: implement initState
pageController = PageController(initialPage: 1, viewportFraction: 0.77);
}
#override
Widget build(BuildContext context) {
return new Scaffold(
body: PageView.builder(
controller: pageController,
itemCount: images.length,
itemBuilder: (context, position) {
return customScroller(position);
}),
);
}
customScroller(int index) {
Widget child = Padding(
padding: EdgeInsets.fromLTRB(0, 15, 0, 15),
child: Container(
child: Card(
color: Colors.white70,
elevation: 9,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0),
),
clipBehavior: Clip.antiAlias,
child: Container(
color: Colors.white,
padding: EdgeInsets.all(5),
child: Row(
children: <Widget>[
Expanded(
flex: 2,
child: Container(
height: double.infinity,
child: ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20.0),
topRight: Radius.circular(0.0),
bottomRight: Radius.circular(0.0),
bottomLeft: Radius.circular(20.0)),
child: new Image.network(
images[index],
fit: BoxFit.cover,
),
),
),
),
],
),
),
),
),
);
double val = (index == 1)?1:0.7;
return AnimatedBuilder(
animation: pageController,
builder: (context, widget) {
if (pageController.position.haveDimensions) {
val = pageController.page - index;
val = 1 - (val.abs() * 0.3).clamp(0.0, 1.0);
}
print("val: $val; index: $index");
return _getTransformedSizedBox(val, widget);
},
// child: Container(
// margin: EdgeInsets.all(10),
// child: Image.network(images[index],fit:BoxFit.cover),
// ),
// When I use the above code as the child instead of the padding with the card in it seems to spawn correctly
child: _getTransformedSizedBox(val, child));
}
_getTransformedSizedBox(double val, Widget widget) {
return Center(
child: SizedBox(
height: Curves.easeInOut.transform(val) * 300,
width: Curves.easeInOut.transform(val) * 400,
child: widget,
),
);
}
}
I want to display a "Close keyboard" button above the keyboard when it is visible.
I know that the resizeToAvoidBottomInset can impact how the keyboard interact with the rest of the application, however it doesn't do exactly what I want.
I have a background image and others widgets (not shown in the sample below) which should not be resized and not moved when the keyboards is shown. This is an ok behavior when the resizeToAvoidBottomInset attribute is set to false.
However, I would like to add a button which should appear above the keyboard.
How can I do that? I only want one widget floating above the keyboard, not all the app.
Here is a sample code :
import 'dart:async';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
var home = MyHomePage(title: 'Flutter Demo Home Page');
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: home,
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar(
title: Text(widget.title),
),
body: _getBody(),
floatingActionButton: FloatingActionButton(
onPressed: () {},
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
Widget _getBody() {
return Stack(children: <Widget>[
Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/sample.jpg"), fit: BoxFit.fitWidth)),
// color: Color.fromARGB(50, 200, 50, 20),
child: Column(
children: <Widget>[TextField()],
),
),
Positioned(
bottom: 0,
left: 0,
right: 0,
child: Container(
height: 50,
child: Text("Aboveeeeee"),
decoration: BoxDecoration(color: Colors.pink),
),
),
]);
}
}
Your Positioned widget has a bottom of 0, replacing with an appropriate value should do the job.
MediaQuery.of(context).viewInsets.bottom will give you the value of the height covered by the system UI(in this case the keyboard).
import 'dart:async';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
var home = MyHomePage(title: 'Flutter Demo Home Page');
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: home,
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar(
title: Text(widget.title),
),
body: _getBody(),
floatingActionButton: FloatingActionButton(
onPressed: () {},
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
Widget _getBody() {
return Stack(children: <Widget>[
Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/sample.jpg"), fit: BoxFit.fitWidth)),
// color: Color.fromARGB(50, 200, 50, 20),
child: Column(
children: <Widget>[TextField()],
),
),
Positioned(
bottom: MediaQuery.of(context).viewInsets.bottom,
left: 0,
right: 0,
child: Container(
height: 50,
child: Text("Aboveeeeee"),
decoration: BoxDecoration(color: Colors.pink),
),
),
]);
}
}
2022 Update
A PR was merged that provides platform-synchronized animations for closing/opening the keyboard. See the PR in effect here.
Detailed Answer
To achieve keyboard-visibility-based animated padding, here are a few modifications over #10101010's great answer:
If you want the bottom change when keyboard changes visibility to be animated AND you want extra padding under your floating child then:
1- Use keyboard_visibility flutter pub
To listen when keyboard is appearing/disappearing, like so:
bool isKeyboardVisible = false;
#override
void initState() {
super.initState();
KeyboardVisibilityNotification().addNewListener(
onChange: (bool visible) {
isKeyboardVisible = visible;
},
);
}
Optionally you can write your own native plugins, but it's already there you can check the pub's git repo.
2- Consume visibility flag in your AnimatedPostioned:
For fine-tuned animated padding, like so:
Widget _getBody() {
double bottomPadding = 0;
if (isKeyboardVisible) {
// when keyboard is shown, our floating widget is above the keyboard and its accessories by `16`
bottomPadding = MediaQuery.of(context).viewInsets.bottom + 16;
} else {
// when keyboard is hidden, we should have default spacing
bottomPadding = 48; // MediaQuery.of(context).size.height * 0.15;
}
return Stack(children: <Widget>[
Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/sample.jpg"), fit: BoxFit.fitWidth)),
// color: Color.fromARGB(50, 200, 50, 20),
child: Column(
children: <Widget>[TextField()],
),
),
AnimatedPositioned(
duration: Duration(milliseconds: 500),
bottom: bottomPadding,
left: 0,
right: 0,
child: Container(
height: 50,
child: Text("Aboveeeeee"),
decoration: BoxDecoration(color: Colors.pink),
),
),
]);
}
3- Keyboard-specific animation curve and duration for synchronized animation
For now this is still an known ongoing issue
You can use the bottomSheet of a Scaffold widget.
Example:
return Scaffold(
appBar: AppBar(
title: const Text("New Game"),
),
bottomSheet: Container(
padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 16),
color: Colors.blue,
child: const SizedBox(
width: double.infinity,
height: 20,
child: Text("Above Keyboard"),
))
...
)
You can use bottomSheet parameter of the Scaffold, which keep a persistent bottom sheet. See below code.
class InputScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Close')),
bottomSheet: Container(
padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 16),
color: Colors.black,
child: const SizedBox(width: double.infinity, height: 10)),
body: Column(
children: [
const TextField(
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: 'Enter your input here',
),
),
ElevatedButton(
onPressed: () {},
child: const Text('Submit'),
),
],
),
);
}
}
check this package, it can show a dismiss button above the keyboard.