Keyboard dismiss taking space in Flutter - flutter

Whenever i dismiss the keyboard sometimes it is taking space at half of the screen whether in iOS or Android. Below is the screenshot why i'm facing this issue. This picture is when after i dismiss the keyboard.
TestPage.dart
class TestPage extends StatefulWidget {
const TestPage({Key? key}) : super(key: key);
#override
State<TestPage> createState() => _TestPageState();
}
class _TestPageState extends State<TestPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: ListView(
children: [
SizedBox(height: 50.0,),
TextField(),
SizedBox(height: 50.0,),
TextField()
],
),
);
}
}

Hey did you try to set background color to your scaffold like below
class TestPage extends StatefulWidget {
const TestPage({Key? key}) : super(key: key);
#override
State<TestPage> createState() => _TestPageState();
}
class _TestPageState extends State<TestPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.teal,
body: ListView(
children: const [
SizedBox(height: 50.0,),
TextField(),
SizedBox(height: 50.0,),
TextField()
],
),
);
}
}

Related

Colors not showing up in Flutter

I was trying to give my Container a Color but but it's saying, for example: red is not defined for the type 'Color'.
Does anyone know how to fix this?
import 'package:flutter/material.dart';
import 'package:color/color.dart';
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
#override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
Container(
color: Color.red,
)
],
),
);
}
}
It's Colors, not Color.
You can look up the Color Class on the official documentation.
Container(
color: Colors.red,
)
import 'package:flutter/material.dart';
import 'package:color/color.dart';
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
#override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
Container(
color: Colors.red,
)
],
),
);
}
}

How to create method without effecting each others?

I created a method that named "Button". This method changes container's color and I want to use this method two times but I don't want "Button" method to not effect other methods. I don't know how to do it. Finally i want to create a method and use it several times but i don't want them to effect each others.
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: HomeScreen(),
);
}
}
class HomeScreen extends StatefulWidget {
const HomeScreen({Key? key}) : super(key: key);
#override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: Column(
children: [
Button(color1!),
SizedBox(height: 20,),
Button(color1!),
],
),
),
);
}
Color? color1 = Colors.green;
FlatButton Button(Color color) {
return FlatButton(
onPressed: () {
setState(() {
color1 = Colors.blue;
});
},
child: Container(
height: 200,
width: 200,
color: color1,
),
);
}
}

Flutter - The const widget still rebuild when its parent rebuild

I have a question about when and how a const widget will rebuild.
For example, I have a demo project like this:
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
static const String _title = 'Flutter Code Sample';
#override
Widget build(BuildContext context) {
return MaterialApp(
title: _title,
home: Scaffold(
appBar: AppBar(title: const Text(_title)),
body: const Center(
child: MyStatefulWidget(),
),
),
);
}
}
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({Key? key}) : super(key: key);
#override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
bool isChecked = false;
#override
Widget build(BuildContext context) {
const child = ChildWidget();
return OrientationBuilder(
builder: (context, orientation) {
debugPrint('$orientation');
final isPortrait = orientation == Orientation.portrait;
return Container(
alignment: Alignment.topCenter,
child: isPortrait
? Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: const [
SizedBox(height: 200, child: child),
Text('Bellow text'),
])
: child,
);
},
);
}
}
class ChildWidget extends StatefulWidget {
const ChildWidget({Key? key}) : super(key: key);
#override
State<ChildWidget> createState() => _ChildWidgetState();
}
class _ChildWidgetState extends State<ChildWidget> {
int _counter = 0;
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
setState(() {
_counter += 1;
});
},
child: Container(
color: Colors.blue, child: Center(child: Text('$_counter'))),
);
}
}
As you see, I have a const ChildWidget.
const child = ChildWidget();
When I rotate the device, it will trigger the builder function of the OrientationBuilder and return a new Container. But my question is why the child widget is rebuilt again while it is a const.
The reason why I want the child widget is not rebuilt is that I don't want the counter Text to reset to 0 each time I rotate the device.
Please advice.
Thanks a lot.
While the variable and object assigned are constant, the framework will still call the build method on the child widgets. So the actual ChildWidget class is not recreated, but the build will be called.
This is not really a problem. Flutter is really optimized for rebuilding Widgets. If the data has not changed, the actual cost of rebuilding is negligible.

How can I place a container laid out above a Scaffold?

I would like to have a persistent container occupy the space about my material Scaffolds AppBar. I would like the Scaffold to resize to take up the available space.
When I try to do this, my Scaffold continues to be the height of the entire screen, and it is simply pushed lower, with a portion overflowing off the screen.
Is there a way I can have the Scaffold to resize to the available space?
Here is what I have coded so far...
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return PersistenTopBar(
child: Scaffold(
appBar: AppBar(
title: const Text("Test App"),
),
body: Container(),
),
);
}
}
class PersistenTopBar extends StatelessWidget {
final Widget child;
const PersistenTopBar({Key? key , required this.child }) : super(key: key);
#override
Widget build(BuildContext context) {
var mediaQuery = MediaQuery.of(context);
return Column(
children: [
Container(
width: double.infinity,
height: 200,
color: Colors.red,
),
SizedBox(
width: mediaQuery.size.width,
height: mediaQuery.size.height,
child: child,
),
],
);
}
}
You could also create a CustomAppBar that would take as children a topChild and an appBar.
class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
final double height;
final Widget topChild;
final AppBar appBar;
const CustomAppBar(
{Key? key,
this.height = 200.0,
required this.topChild,
required this.appBar})
: super(key: key);
#override
Widget build(BuildContext context) {
return Column(
children: [
Expanded(child: topChild),
appBar,
],
);
}
#override
Size get preferredSize => Size.fromHeight(height);
}
Full code sample
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(
theme: ThemeData.light(),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: CustomAppBar(
topChild: Container(color: Colors.red),
appBar: AppBar(title: const Text('My awesome Test App')),
),
body: const Center(
child: Text(
"Test App",
style: TextStyle(fontSize: 32.0),
),
),
);
}
}
class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
final double height;
final Widget topChild;
final AppBar appBar;
const CustomAppBar(
{Key? key,
this.height = 200.0,
required this.topChild,
required this.appBar})
: super(key: key);
#override
Widget build(BuildContext context) {
return Column(
children: [
Expanded(child: topChild),
appBar,
],
);
}
#override
Size get preferredSize => Size.fromHeight(height);
}
the available space = mediaQuery.size.height - the Height of the Container above the appBar so the SizedBox under the appBar wil be :
SizedBox(
width: mediaQuery.size.width,
height: mediaQuery.size.height - 200,
child: child,
),
the result:
or you can wrap your SizedBox with Expanded Widget :
Expanded(
child: SizedBox(
width: mediaQuery.size.width,
child: child,
),
),
the same result :

How to prevent rebuild StatelessWidget children of PageView

I've create simple PageView app to test multiple pages.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
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) {
final firstPage = FirstPage(key: Key("FirstPage"));
final secondPage = SecondPage(key: Key("SecondPage"));
debugPrint("_MyHomePageState.build");
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: PageView(
children: <Widget>[
firstPage,
secondPage,
],
),
);
}
}
class FirstPage extends StatelessWidget {
FirstPage({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
debugPrint("FirstPage.build");
return Container(
child: Center(
child: Text("First Page"),
),
);
}
}
class SecondPage extends StatelessWidget {
SecondPage({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
debugPrint("SecondPage.build");
return Container(
child: Center(
child: Text("Second Page"),
),
);
}
}
Even thought _MyHomePageState.build has been shown only once, FirstPage.build and SecondPage.build were printed on every page changes.
What I'd like to prevent unnecessary page draw, how can I accomplish this?
You can achieve so by using
1. const keyword
Make your widgets accept to be const:
class FirstPage extends StatelessWidget {
const FirstPage({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
debugPrint("FirstPage.build");
return Container(
child: Center(
child: Text("First Page"),
),
);
}
}
and call it with const keyword:
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: PageView(
children: <Widget>[
const firstPage(),
const secondPage(),
],
),
);
2. AutomaticKeepAliveClientMixin
Convert your StatelessWidget to StatefullWidget.
class FirstPage extends StatefulWidget {
FirstPage({Key key}) : super(key: key);
#override
_FirstPageState createState() => _FirstPageState();
}
class _FirstPageState extends State<FirstPage> {
#override
Widget build(BuildContext context) {
debugPrint("FirstPage.build");
return Container(
child: Center(
child: Text("First Page"),
),
);
}
}
Extends AutomaticKeepAliveClientMixin on StatefullWidget created State.
class _FirstPageState extends State<FirstPage> with AutomaticKeepAliveClientMixin {
Call super on the build method.
#override
Widget build(BuildContext context) {
super.build(context);
debugPrint("FirstPage.build");
return Container(
child: Center(
child: Text("First Page"),
),
);
}
Override wantKeepAlive getter with true returned value.
#override
bool get wantKeepAlive => true;
And then your widget tree won't dispose of this widget so it won't rebuild over and over.
Code Example:
class FirstPage extends StatefulWidget {
FirstPage({Key key}) : super(key: key);
#override
_FirstPageState createState() => _FirstPageState();
}
class _FirstPageState extends State<FirstPage>
with AutomaticKeepAliveClientMixin {
#override
Widget build(BuildContext context) {
super.build(context);
debugPrint("FirstPage.build");
return Container(
child: Center(
child: Text("First Page"),
),
);
}
#override
bool get wantKeepAlive => true;
}
3. MVVM Architecture with any State-management solution you like
It will save your state on ViewModel away from the View, so your UI can rebuild itself anytime it wants with no worries about your State because the ViewModel is still the same.
You should always imagine that your build() methods (for both StatefulWidget and StatelessWidget) are being called 60 times per second, so they should be simple and idempotent. Anything else should be moved into a StatefulWidget initState() and friends.
It's easy!
pageController can help you.
Just in your _MyHomePageState
Declare final pageController = PageController(keepPage: false);
And in your PageView
PageView(
controller: pageController,
children: <Widget>[
firstPage,
secondPage,
],
)
Good Luck.