How to make two containers within one column scrollable? - flutter

I am building an app using Flutter, and I encountered this mistake:
I am making a column, that has two Containers inside it. The top Container has a fixed height, 40% of screen. The bottom Container's height is changed. Its height is dependent on the amount of containers it has inside. If the amount of inner containers is more than 6, then I have an overflow. Yet, I want a scrollable behavior (only on second widget). This is the minimal reproducible code:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Stateful Clicker Counter',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Clicker Counter Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
final String title;
const MyHomePage({Key? key, required this.title}) : super(key: key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
width: size.width,
height: size.height * 0.4,
color: Colors.black,
),
Container(
width: size.width,
color: Colors.red,
child: Column(
children: [
Text("Hello"),
GridView.count(
crossAxisCount: 3,
children: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map((el) => Text(el.toString())).toList() as List<Widget>,
shrinkWrap: true,
),
],
)),
],
),
));
}
}
As you may see, I use GridView.count in the second container to create this inner containers. It has by default scrollable behaviour. But it still gives overflow. How do I fix this?

GridView has scroll behavior but when using shrinkWarp scrolling doesn't work.
as on https://youtu.be/LUqDNnv_dh0?t=117 when defination shrinkWarp:
to completely evaluate itself and figure out its full size up front and then proceed by your top-level viewport behaving as if they're all just one widget
that means when using shrinkWarp gridview will take a full size.
you can solve your code by doing like:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Stateful Clicker Counter',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Clicker Counter Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
final String title;
const MyHomePage({Key? key, required this.title}) : super(key: key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
width: size.width,
height: size.height * 0.4,
color: Colors.black,
),
Expanded( // Added
child: Container(
width: size.width,
color: Colors.red,
child: Column(
children: [
Text("Hello"),
Expanded( // Added
child: GridView.count(
crossAxisCount: 3,
children: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map((el) => Text(el.toString())).toList() as List<Widget>,
// shrinkWrap: true, // changed
),
),
],
)),
),
],
),
));
}
}

You should wrap your main column in an expanded or flexible format so that it uses the available screen space. Then add a SingleChildScrollView on your child column to get a simple scroll.
Example:
Expanded(
child:
Container(
width: size.width,
color: Colors.red,
child: SingleChildScrollView(
child: Column(
children: [
Text("Hello"),
GridView.count(
crossAxisCount: 3,
children: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map((el) => Text(el.toString())).toList() as List<Widget>,
shrinkWrap: true,
),
],
)
),
)
)

wrap your second Container & column with expanded and remove shrinkwrap from GridView.count:
Expanded(
// Added
child: Container(
width: size.width,
color: Colors.red,
child: Column(
children: [
Text("Hello"),
Expanded(
// Added
child: GridView.count(
crossAxisCount: 3,
children: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
.map((el) => Text(el.toString()))
.toList() as List<Widget>,
// shrinkWrap: true, // changed
),
),
],
)),
),

Related

Flutter - How to setup a custom height and width of Scaffold

I'm aware that MediaQuery solutions exist to problems, however, I want to limit the size of my Scaffold so that it can be used for web-based apps as well. Similar to what Instagram has, can anyone help me with it?
Have you tried wrapping your Scaffold in SafeArea with a minimum property of EdgeInsets.all(32.0)?
For me, this recreates your mockup on any screen
Example code:
//...
return SafeArea(
minimum: const EdgeInsets.all(32.0),
child: Scaffold(
//...
),
);
//...
I used sizedboxes to create layers for a single page look. The gridview does not shrink to the size of the window. Instead it activates scrolling. My solution works for chrome web.
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.purple,
buttonTheme: const ButtonThemeData(
textTheme:ButtonTextTheme.primary,
buttonColor:Colors.yellow,
)
),
home: Test_SinglePage(),
);
}
}
class DataRecord{
String name;
String number;
DataRecord(this.name,this.number);
}
class Test_SinglePage extends StatefulWidget {
Test_SinglePage({Key? key}) : super(key: key);
#override
State<Test_SinglePage> createState() => _Test_SinglePageState();
}
class _Test_SinglePageState extends State<Test_SinglePage> {
List<DataRecord> lstData=[
DataRecord("A","1"), DataRecord("B","2"), DataRecord("C","3"), DataRecord("D","4"),
DataRecord("E","5"), DataRecord("F","6"), DataRecord("G","7"), DataRecord("H","8"),
DataRecord("I","9"), DataRecord("J","10"), DataRecord("K","11"), DataRecord("L","12"),
DataRecord("M","13"), DataRecord("N","14"), DataRecord("O","15"), DataRecord("P","16"),
DataRecord("Q","17"), DataRecord("R","18"), DataRecord("S","19"), DataRecord("T","20"),
DataRecord("V","21"), DataRecord("X","22"), DataRecord("Y","23"), DataRecord("Z","24"),
];
Widget _dialogBuilder(BuildContext context, String name)
{
return SimpleDialog(
contentPadding:EdgeInsets.zero,
children:[
Container(width:80,height:80,child:
Column(children:[
Text(name),
SizedBox(height:20),
Expanded(child:Row(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end,
children: [ElevatedButton(onPressed:(){ Navigator.of(context).pop();}, child:
Text("Close"))
],))
])
)]);
}
Widget _itemBuilder(BuildContext context,int index)
{
return
GestureDetector(
onTap:()=>showDialog(context:context,builder:(context)=>_dialogBuilder(context,lstData[index].name)),
child:Container(color:Colors.grey,child:GridTile(child: Center(child:
Column(children:[
Text(lstData[index].name,style:Theme.of(context).textTheme.headline2),
Text(lstData[index].number,style:Theme.of(context).textTheme.headline4)
])
))));
}
#override
Widget build(BuildContext context) {
return Scaffold(appBar: AppBar(title:Text("Single Page")),body:
Container(
margin: const EdgeInsets.only(top:20.0, left: 20.0, right: 20.0, bottom:10.0),
child:
Flex(
direction: Axis.vertical,
mainAxisAlignment: MainAxisAlignment.start,
children: [
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child:Row(
mainAxisAlignment: MainAxisAlignment.start,
children:[
FittedBox(
fit:BoxFit.fitHeight,
child:SizedBox(
width:200,
height:200,
child: Image.asset("assets/images/apple.jpg"),
)),
Column(
mainAxisAlignment:MainAxisAlignment.start,
children:[
Row(
children: [
SizedBox(height:100,width:200,child:Container(color:Colors.red,child:Text("reached"))),
SizedBox(height:100,width:200,child:Container(color:Colors.blue,child:Text("reached2"))),
SizedBox(height:100,width:200,child:Container(color:Colors.green,child:Text("reached3")))
],),
Row(children: [
SizedBox(width:600, child:ElevatedButton(
onPressed:(){
},child:Text("Press Me")))],)
])
])),
Expanded(child:SizedBox(
height:400,
width:MediaQuery.of(context).size.width,child:
GridView.builder(
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 300,
childAspectRatio: 3 / 2,
crossAxisSpacing: 20,
mainAxisSpacing: 20),
itemCount: lstData.length,
itemBuilder: _itemBuilder
)))],)
,));
}
}

DataTable that expands to window with, and also scroll horizontally if it overflows

I'm trying to create a DataTable that will expand to the available width of its parent as DataTables do normally, but also if there isn't enough horizontal space on the screen it should allow horizontal scrolling. As it stands I'm only able to do one or the other. The problem is when I allow the table to scroll horizontally, the cells no longer expand. And when I allow the cells to expand horizontally, the table will be cut off of the page if it doesn't fit.
Sample code below is of the table version where the cells won't expand, but scrolling works.
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 MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
ScrollController verticalController = ScrollController();
ScrollController horizontalController = ScrollController();
bool maximized = false;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Scrollbar(
controller: verticalController,
isAlwaysShown: true,
child: SingleChildScrollView(
controller: verticalController,
child: Padding(
padding: const EdgeInsets.all(15.0),
child: Column(
children: [
Text('Table Name'),
Container(
width: double.infinity,
child: Scrollbar(
isAlwaysShown: true,
controller: horizontalController,
child: SingleChildScrollView(
controller: horizontalController,
scrollDirection: Axis.horizontal,
child: DataTable(
dataRowHeight: 50,
columnSpacing: 20,
horizontalMargin: 0,
columns: List<DataColumn>.generate(
10,
(index) => DataColumn(
label: Text("Column" + index.toString()))),
rows: List<DataRow>.generate(10, (rowIndex) {
if (maximized) {
return DataRow(
cells: List<DataCell>.generate(
10,
(cellIndex) => DataCell(
Container(
width: 100,
child: Column(
children: [
Text("row" + rowIndex.toString()),
Text("Cell" + cellIndex.toString()),
],
),
),
),
),
);
} else {
return DataRow(
cells: List<DataCell>.generate(
10,
(cellIndex) => DataCell(
Container(
child: Column(
children: [
Text("row" + rowIndex.toString()),
Text("Cell" + cellIndex.toString()),
],
),
),
),
),
);
}
})),
),
),
),
],
),
),
),
));
}
}
Can You try to give the upper SingleChildScrollView property of:
shrinkWrap: true,
Hope I understand what is the problem
You can give it a try hope it helps
I was able to fix this issue by using a constrained box around my table and setting the minimum width to the available width on the screen. This still allows the table to expand horizontally while keeping the width at least as large as the available screen width.

Expanded with max width / height?

I want widgets that has certain size but shrink if available space is too small for them to fit.
Let's say available space is 100px, and each of child widgets are 10px in width.
Say parent's size got smaller to 90px due to resize.
By default, if there are 10 childs, the 10th child will not be rendered as it overflows.
In this case, I want these 10 childs to shrink in even manner so every childs become 9px in width to fit inside parent as whole.
And even if available size is bigger than 100px, they keep their size.
Wonder if there's any way I can achieve this.
return Expanded(
child: Row(
children: [
...List.generate(Navigation().state.length * 2, (index) => index % 2 == 0 ? Flexible(child: _Tab(index: index ~/ 2, refresh: refresh)) : _Seperator(index: index)),
Expanded(child: Container(color: ColorScheme.brightness_0))
]
)
);
...
_Tab({ required this.index, required this.refresh }) : super(
constraints: BoxConstraints(minWidth: 120, maxWidth: 200, minHeight: 35, maxHeight: 35),
...
you need to change Expanded to Flexible
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(appBar: AppBar(), body: Body()),
);
}
}
class Body extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
width: 80,
color: Colors.green,
child: Row(
children: List.generate(10, (i) {
return Flexible(
child: Container(
constraints: BoxConstraints(maxWidth: 10, maxHeight: 10),
foregroundDecoration: BoxDecoration(border: Border.all(color: Colors.yellow, width: 1)),
),
);
}),
),
);
}
}
two cases below
when the row > 100 and row < 100
optional you can add mainAxisAlignment property to Row e.g.
mainAxisAlignment: MainAxisAlignment.spaceBetween,
Try this
ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 10,maxHeigth:10),
child: ChildWidget(...),
)
The key lies in a combination of using Flexible around each child in the column, and setting the child's max size using BoxContraints.loose()
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Make them fit',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key}) : super(key: key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int theHeight = 100;
void _incrementCounter() {
setState(() {
theHeight += 10;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Playing with making it fit'),
),
body: Container(
color: Colors.blue,
child: Padding(
// Make the space we are working with have a visible outer border area
padding: const EdgeInsets.all(8.0),
child: Container(
height: 400, // Fix the area we work in for the sake of the example
child: Column(
children: [
Expanded(
child: Column(
children: [
Flexible(child: SomeBox('A')),
Flexible(child: SomeBox('A')),
Flexible(child: SomeBox('BB')),
Flexible(child: SomeBox('CCC')),
Flexible(
child: SomeBox('DDDD', maxHeight: 25),
// use a flex value to preserve ratios.
),
Flexible(child: SomeBox('EEEEE')),
],
),
),
Container(
height: theHeight.toDouble(), // This will change to take up more space
color: Colors.deepPurpleAccent, // Make it stand out
child: Center(
// Child column will get Cross axis alighnment and stretch.
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text('Press (+) to increase the size of this area'),
Text('$theHeight'),
],
),
),
)
],
),
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
class SomeBox extends StatelessWidget {
final String label;
final double
maxHeight; // Allow the parent to control the max size of each child
const SomeBox(
this.label, {
Key key,
this.maxHeight = 45,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return ConstrainedBox(
// Creates box constraints that forbid sizes larger than the given size.
constraints: BoxConstraints.loose(Size(double.infinity, maxHeight)),
child: Padding(
padding: const EdgeInsets.all(2.0),
child: Container(
decoration: BoxDecoration(
color: Colors.green,
border: Border.all(
// Make individual "child" widgets outlined
color: Colors.red,
width: 2,
),
),
key: Key(label),
child: Center(
child: Text(
label), // pass a child widget in stead to make this generic
),
),
),
);
}
}

App Bar height calculations with MediaQuery fail

I am building an app where I wanted to show 4 containers covering the whole available space of on the phone.
For that I am getting the full width and height of the screen using MediaQuery.of. I make the 4 containers fill the entire screen by giving each of them a height of 0.25 of the total height.
The initial code comes here and works fine:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(body: MyHomePage(title: 'Title')),
);
}
}
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 _buildMobileLayout(context);
}
Widget _buildMobileLayout(BuildContext context) {
AppBar appBar = AppBar(
title: Text("My App Title"),
);
// var newHeight =
// (MediaQuery.of(context).size.height - appBar.preferredSize.height) *
// 0.25;
var newHeight = (MediaQuery.of(context).size.height) * 0.25;
return Scaffold(
//appBar: appBar,
body: Column(
children: <Widget>[
Container(
width: MediaQuery.of(context).size.width,
height: newHeight,
child: Center(child: Text("Cont 1")),
),
Container(
width: MediaQuery.of(context).size.width,
height: newHeight,
child: Center(child: Text("Cont 2")),
),
Container(
width: MediaQuery.of(context).size.width,
height: newHeight,
child: Center(child: Text("Cont 3")),
),
Container(
width: MediaQuery.of(context).size.width,
height: newHeight,
child: Center(child: Text("Cont 4")),
),
],
),
);
}
}
As you can see on the code above, I am not including the appBar yet, since here is when the problem comes. All works ok without the appBar, but when I include the appBar, even though I am taking care of its height, getting a new total height and splitting it among the 4 containers, I get an error by pixel overflow on the last container.
Phone: Huawei P20 Pro.
Instead of using MediaQuery you can wrap each of your widgets in a Expanded and give them the same flex.
return Scaffold(
//appBar: appBar,
body: Column(
children: <Widget>[
Expanded(
flex: 1,
child: Center(child: Text("Cont 1")),
),
Expanded(
flex: 1,
child: Center(child: Text("Cont 2")),
),
Expanded(
flex: 1,
child: Center(child: Text("Cont 3")),
),
Expanded(
flex: 1,
child: Center(child: Text("Cont 4")),
),
],
),
);

Make only one widget float above the keyboard in Flutter

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.