Prevent scrolled Hero from jumping on top of the app bar - dart

I have a Hero that can be scrolled so that part of it is offscreen. When I trigger a transition, it appears to abruptly jump on top of the AppBar and then jumps back under it when the transition is reversed. How do I force the AppBar to stay on top of the Hero?
import 'package:flutter/material.dart';
void main() {
runApp(new MaterialApp(
home: new Example(),
theme: new ThemeData(primaryColor: Colors.orange),
debugShowCheckedModeBanner: false,
));
}
Widget positionHeroOverlay(BuildContext context, Widget overlay, Rect rect, Size size) {
final RelativeRect offsets = new RelativeRect.fromSize(rect, size);
return new Positioned(
top: offsets.top,
right: offsets.right,
bottom: offsets.bottom,
left: offsets.left,
child: overlay,
);
}
class LogoPageRoute extends MaterialPageRoute<Null> {
LogoPageRoute(this.colors) : super(
builder: (BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('Flutter Logo'),
),
body: new ConstrainedBox(
constraints: new BoxConstraints.expand(),
child: new Hero(
tag: colors,
child: new FlutterLogo(colors: colors),
),
),
);
},
);
/// The color of logo to display
final MaterialColor colors;
#override
final Duration transitionDuration = const Duration(seconds: 1);
}
final List<MaterialColor> swatches = [
Colors.blue,
Colors.orange,
Colors.green,
];
class Example extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('All Logos'),
),
body: new ListView(
children: swatches.map((MaterialColor colors) {
return new InkWell(
onTap: () {
Navigator.push(context, new LogoPageRoute(colors));
},
child: new Hero(
tag: colors,
child: new FlutterLogo(size: 360.0, colors: colors),
),
);
}).toList(),
),
);
}
}

Wrap your AppBar in a Hero to force it to stay on top.
appBar: new PreferredSize(
child: new Hero(
tag: AppBar,
child: new AppBar(
title: new Text('All Logos'),
),
),
preferredSize: new AppBar().preferredSize,
),
For the AppBar of the detail page, I would recommend forcing the back button to be displayed so that it appears at the same time that the page title changes.
appBar: new PreferredSize(
child: new Hero(
tag: AppBar,
child: new AppBar(
leading: const BackButton(),
title: new Text('Flutter Logo'),
),
),
preferredSize: new AppBar().preferredSize,
),
Here's what it looks like:

i've fixed it here https://github.com/zombie6888/scrolled_hero by providing bottom and top offset to hero animation builder

Related

How to keep hamburger icon without visible appBar flutter

I recently tried keeping a Hamburger icon for my menu slider without an AppBar or at least completely invisible. The first attempt was with a SafeArea but that emptied Scaffold. Then I tried setting the Opacity to 0.0 like shown on the code below. But it gives out the same result as SafeArea with nothing on Scaffold. Please can anyone help?
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
State<StatefulWidget> createState() => MyAppState();
}
class MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
return new MaterialApp(
theme: ThemeData(
// Define the default Brightness and Colors
brightness: Brightness.dark,
primaryColor: Colors.lightBlue[800],
accentColor: Colors.cyan[600],
),
home: Scaffold(
Opacity(
opacity: 0.0,
appBar: AppBar(),
),
drawer: new Drawer(
child: new ListView(),
),
body: new Center(
child: new Column(
children: <Widget>[],
))),
);
}
}
If I have understood you well, you want to display a menu button to show the Drawer without displaying any AppBar.
One option is to use a Stack for the body of the Scaffold.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
State<StatefulWidget> createState() => MyAppState();
}
class MyAppState extends State<MyApp> {
var scaffoldKey = GlobalKey<ScaffoldState>();
#override
Widget build(BuildContext context) {
return new MaterialApp(
theme: ThemeData(
// Define the default Brightness and Colors
brightness: Brightness.dark,
primaryColor: Colors.lightBlue[800],
accentColor: Colors.cyan[600],
),
home: Scaffold(
key: scaffoldKey,
drawer: new Drawer(
child: new ListView(),
),
body: Stack(
children: <Widget>[
new Center(
child: new Column(
children: <Widget>[],
)),
Positioned(
left: 10,
top: 20,
child: IconButton(
icon: Icon(Icons.menu),
onPressed: () => scaffoldKey.currentState.openDrawer(),
),
),
],
),
),
);
}
}
If I have understood your question well.
You have your own custom Menu button to open/close drawer.
You don't want to use AppBar as well.
In that case you can use GlobalKey<ScaffoldState>() object to open Drawer.
import 'package:flutter/material.dart';
GlobalKey<ScaffoldState> _scaffoldState = GlobalKey<ScaffoldState>();
return Scaffold(
key: _scaffoldState,
drawer: DrawerView(),
body: ThemeScreen(
header: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
IconButton(
icon: Icon(Icons.menu,
color: Colors.white,
size: 15),
onPressed: (){
_scaffoldState.currentState.openDrawer();
},
),
],
),
),
);
You can make AppBar completely invisible by setting the same color and elevation = 0
screenshot here
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color(0xFF198BAA),
appBar: AppBar(
backgroundColor: Color(0xFF198BAA),
elevation: 0.0,
),
drawer: Drawer(
child: SafeArea(
child: Padding(
padding: const EdgeInsets.all(18.0),
child: ListView(
children: <Widget>[
ListTile(
title: Text('Item1'),
)
],
),
),
),
),
);
}
}
This is similar to Ox.S's answer, but you can make the AppBar transparent and then change the icon to whatever color you want.
Scaffold(
appBar: AppBar(
backgroundColor: Colors.transparent,
elevation: 0.0,
iconTheme: IconThemeData(color: Colors.black),
),
drawer: Drawer(...

Flutter: Setting the height of the AppBar

How can I simply set the height of the AppBar in Flutter?
The title of the bar should be staying centered vertically (in that AppBar).
You can use PreferredSize:
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Example',
home: Scaffold(
appBar: PreferredSize(
preferredSize: Size.fromHeight(50.0), // here the desired height
child: AppBar(
// ...
)
),
body: // ...
)
);
}
}
Use toolbarHeight:
There's no longer a need to use PreferredSize. Use toolbarHeight with flexibleSpace.
AppBar(
toolbarHeight: 120, // Set this height
flexibleSpace: Container(
color: Colors.orange,
child: Column(
children: [
Text('1'),
Text('2'),
Text('3'),
Text('4'),
],
),
),
)
You can use PreferredSize and flexibleSpace for it:
appBar: PreferredSize(
preferredSize: Size.fromHeight(100.0),
child: AppBar(
automaticallyImplyLeading: false, // hides leading widget
flexibleSpace: SomeWidget(),
)
),
This way you can keep the elevation of AppBar for keeping its shadow visible and have custom height, which is what I was just looking for. You do have to set the spacing in SomeWidget, though.
The easiest way is to use toolbarHeight property in your AppBar
Example :
AppBar(
title: Text('Flutter is great'),
toolbarHeight: 100,
),
You can add flexibleSpace property in your appBar for more flexibility
Output:
For more controls , Use the PreferedSize widget to create your own appBar
Example :
appBar: PreferredSize(
preferredSize: Size(100, 80), //width and height
// The size the AppBar would prefer if there were no other constraints.
child: SafeArea(
child: Container(
height: 100,
color: Colors.red,
child: Center(child: Text('Fluter is great')),
),
),
),
Don't forget to use a SafeArea widget if you don't have a safeArea
Output :
At the time of writing this, I was not aware of PreferredSize. Cinn's answer is better to achieve this.
You can create your own custom widget with a custom height:
import "package:flutter/material.dart";
class Page extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new Column(children : <Widget>[new CustomAppBar("Custom App Bar"), new Container()],);
}
}
class CustomAppBar extends StatelessWidget {
final String title;
final double barHeight = 50.0; // change this for different heights
CustomAppBar(this.title);
#override
Widget build(BuildContext context) {
final double statusbarHeight = MediaQuery
.of(context)
.padding
.top;
return new Container(
padding: new EdgeInsets.only(top: statusbarHeight),
height: statusbarHeight + barHeight,
child: new Center(
child: new Text(
title,
style: new TextStyle(fontSize: 20.0, fontWeight: FontWeight.bold),
),
),
);
}
}
In addition to #Cinn's answer, you can define a class like this
class MyAppBar extends AppBar with PreferredSizeWidget {
#override
get preferredSize => Size.fromHeight(50);
MyAppBar({Key key, Widget title}) : super(
key: key,
title: title,
// maybe other AppBar properties
);
}
or this way
class MyAppBar extends PreferredSize {
MyAppBar({Key key, Widget title}) : super(
key: key,
preferredSize: Size.fromHeight(50),
child: AppBar(
title: title,
// maybe other AppBar properties
),
);
}
and then use it instead of standard one
You can simply use toolbarHeight, as follows:
appBar: AppBar(
toolbarHeight: 70.0, // add this line
centerTitle: true, // add this line
title: Text('your title'),
),
but if you have any actions the code above doesn't work as you want
you can use this code
AppBar(
centerTitle: true,
title: Padding(
padding: const EdgeInsets.all(16.0),
child: Stack(
alignment: Alignment.center,
children: [
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Chats', style: TextStyle(color:Colors.black),),
Icon(Icons.add, color: Colors.black,),
],
),
Align(
alignment: Alignment.centerRight,
child: Icon(Icons.add, color: Colors.black,),
),
],
),
),
)
Cinn's answer is great, but there's one thing wrong with it.
The PreferredSize widget will start immediately at the top of the screen, without accounting for the status bar, so some of its height will be shadowed by the status bar's height. This also accounts for the side notches.
The solution: Wrap the preferredSize's child with a SafeArea
appBar: PreferredSize(
//Here is the preferred height.
preferredSize: Size.fromHeight(50.0),
child: SafeArea(
child: AppBar(
flexibleSpace: ...
),
),
),
If you don't wanna use the flexibleSpace property, then there's no need for all that, because the other properties of the AppBar will account for the status bar automatically.
simply use toolbar height ...
AppBar(
title: Text("NASHIR'S APP"),
toolbarHeight: 100,
),
You can use the toolbarHeight property of Appbar, it does exactly what you want.
class AppBarWidget extends StatelessWidget with PreferredSizeWidget {
final String title;
const AppBarWidget({Key? key, required this.title}) : super(key: key);
#override`enter code here`
Widget build(BuildContext context) {
return AppBar(
title: Text(title),
centerTitle: true,
elevation: 0,
actions: [
Padding(
padding: const EdgeInsets.only(right: 10),
child: IconButton(
icon: const FaIcon(FontAwesomeIcons.language),
onPressed: () {},
),
),
],
);
}
#override
Size get preferredSize => const Size.fromHeight(40);// change
}
You can use PreferredSize, by this use can set multiple children widget inside their
appBar: PreferredSize(
preferredSize: Size(MediaQuery.of(context).size.width, 75),
child: Column(children: [
AppBar(
centerTitle: true,
toolbarHeight: 74,
backgroundColor: Colors.white,
elevation: 0,
title: Column(
children: [
Text(
viewModel.headingText,
style: sfDisplay16500Text,
),
SizedBox(
height: 8.0,
),
Text(
viewModel.url.toString(),
style: sfDisplay10400LightBlackText,
maxLines: 1,
overflow: TextOverflow.ellipsis,
)
],
),
),
]),
),
or just directly use toolbarHeight property for only increase hight of appBar.
appBar: AppBar(
title: Text('AppBar Texr'),
toolbarHeight: 200.0, // double
),
Extend AppBar class and override preferredSize
class AppBarCustom extends AppBar {
#override
Size get preferredSize => Size.fromHeight(100);
}
then use it as you would use AppBar class
class MyHomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBarCustom(),
body:
),
);
}
}
This is simplest and easiest way to change appbar height without changing original theme.
class AppBarSectionView extends StatefulWidget implements PreferredSizeWidget {
const AppBarSectionView({Key? key}) : super(key: key);
#override
_AppBarSectionViewState createState() => _AppBarSectionViewState();
#override
Size get preferredSize => const Size.fromHeight(kToolbarHeight + 20);
}
class _AppBarSectionViewState extends State<AppBarSectionView> {
#override
Widget build(BuildContext context) {
return AppBar(
toolbarHeight: widget.preferredSize.height ,
backgroundColor: Colors.red,
leading: const Icon(Icons.arrow_back_ios_rounded),
title: const Text("This Is Title"),
);
}
}
If you are in Visual Code, Ctrl + Click on AppBar function.
Widget demoPage() {
AppBar appBar = AppBar(
title: Text('Demo'),
);
return Scaffold(
appBar: appBar,
body: /*
page body
*/,
);
}
And edit this piece.
app_bar.dart will open and you can find
preferredSize = new Size.fromHeight(kToolbarHeight + (bottom?.preferredSize?.height ?? 0.0)),
Difference of height!

Flutter TabBarView children: single instance for screens

I am experimenting with Flutter and I have created a simple TabBarView based app.
Widget build(BuildContext context) {
return new MaterialApp(
home: new DefaultTabController(
length: choices.length,
child: new Scaffold(
appBar: new AppBar(
title: const Text('My Cool App'),
bottom: new TabBar(
isScrollable: true,
tabs: choices.map((Choice choice) {
return new Tab(
text: choice.title,
);
}).toList(),
),
),
body: new TabBarView(
children: choices.map((Choice choice) {
return new Padding(
padding: const EdgeInsets.all(16.0),
child: myScreen,
);
}).toList(),
),
),
),
);
}
The problem is that every time I switch tab and return back, I get a new instance of myScreen.
I tried declaring myScreen as final outside the class, but it doesn't make a difference.
Any way I could achieve this?

Can FlutterLogo be made to stretch-to-fill?

I would like to display a large FlutterLogo in my app:
https://docs.flutter.io/flutter/material/FlutterLogo-class.html
In order to account for varying screen sizes I would like to make it stretch-to fill. Is that possible? Or do I need to use a MediaQuery to determine the parent's size and pass that into FlutterLogo(size:)?
My current code:
Widget build(BuildContext context) {
return new Center(
child: new FlutterLogo(size: 800.0, style: FlutterLogoStyle.horizontal, textColor: Colors.white),
);
}
You can accomplish this with a ConstrainedBox:
import 'package:flutter/material.dart';
void main() {
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
theme: new ThemeData.dark(),
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(title: new Text('Example App')),
body: new ConstrainedBox(
constraints: new BoxConstraints.expand(),
child: new FlutterLogo(
style: FlutterLogoStyle.horizontal,
textColor: Colors.white,
),
),
);
}
}
I believe I have answered a similar question
How to stretch an icon to fill parent?
https://docs.flutter.io/flutter/widgets/Expanded-class.html
https://groups.google.com/forum/#!msg/flutter-dev/lsgdU1yl7xc/0pYS2qrzBQAJ
https://docs.flutter.io/flutter/widgets/FittedBox-class.html
https://docs.flutter.io/flutter/painting/BoxFit-class.html
new Expanded(
child: new FittedBox(
fit: BoxFit.fill,
child: new FlutterLogo( style: FlutterLogoStyle.horizontal, textColor: Colors.white),
),
),
I feel kinda strange. Looking at the OP profile ID, I wonder if I answer the question correctly.
I hope this helps.
used this code to run it
import 'package:flutter/material.dart';
class MyAppBar extends StatelessWidget {
MyAppBar({this.title});
// Fields in a Widget subclass are always marked "final".
final Widget title;
#override
Widget build(BuildContext context) {
return new Container(
height: 56.0, // in logical pixels
padding: const EdgeInsets.symmetric(horizontal: 8.0),
decoration: new BoxDecoration(color: Colors.blue[500]),
// Row is a horizontal, linear layout.
child: new Row(
// <Widget> is the type of items in the list.
children: <Widget>[
new IconButton(
icon: new Icon(Icons.menu),
tooltip: 'Navigation menu',
onPressed: null, // null disables the button
),
// Expanded expands its child to fill the available space.
new Expanded(
child: title,
),
new IconButton(
icon: new Icon(Icons.search),
tooltip: 'Search',
onPressed: null,
),
],
),
);
}
}
class MyScaffold extends StatelessWidget {
#override
Widget build(BuildContext context) {
// Material is a conceptual piece of paper on which the UI appears.
return new Material(
// Column is a vertical, linear layout.
child: new Column(
children: <Widget>[
new MyAppBar(
title: new Text(
'Example title',
style: Theme.of(context).primaryTextTheme.title,
),
),
new Expanded(
child: new FittedBox(
fit: BoxFit.fill,
child: new FlutterLogo( style: FlutterLogoStyle.horizontal, textColor: Colors.white),
),
),
],
),
);
}
}
void main() {
runApp(new MaterialApp(
title: 'My app', // used by the OS task switcher
home: new MyScaffold(),
));
}
edit: I posted complete code just for darky, since I forgot to mention that expanded needs to be wrapped into row, column, or flex container to expand

Flutter - FloatingActionButton in the center

Is it possible to make the FloatingActionButton in the centre instead of the right side?
import 'package:flutter/material.dart';
import 'number.dart';
import 'keyboard.dart';
class ContaPage extends StatelessWidget {
#override
Widget build(BuildContext context) => new Scaffold(
body: new Column(
children: <Widget>[
new Number(),
new Keyboard(),
],
),
floatingActionButton: new FloatingActionButton(
elevation: 0.0,
child: new Icon(Icons.check),
backgroundColor: new Color(0xFFE57373),
onPressed: (){}
)
);
}
I don't know if this was added since this question was first answered, but there's now floatingActionButtonLocation property on the Scaffold class.
It would work like this in your original question:
class ContaPage extends StatelessWidget {
#override
Widget build(BuildContext context) => new Scaffold(
// ...
floatingActionButton: new FloatingActionButton(
// ...FloatingActionButton properties...
),
// Here's the new attribute:
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
);
}
Also see the documentation:
Scaffold class (search floatingActionButtonLocation): https://docs.flutter.dev/flutter/material/Scaffold-class.html
...and the FloatingActionButtonLocation class: https://docs.flutter.dev/flutter/material/FloatingActionButtonLocation-class.html
With the new flutter API you do that very easily just change the floatingActionButtonLocation property in the Scaffold to
FloatingActionButtonLocation.centerFloat
Example :
return new Scaffold(
floatingActionButton: new FloatingActionButton(
child: const Icon(Icons.add),
),
floatingActionButtonLocation:
FloatingActionButtonLocation.centerFloat,
bottomNavigationBar: new BottomAppBar(
color: Colors.white,
child: new Row(...),
),
);
Use the Property floatingActionButtonLocation of scaffold class.
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
Full Example:
import 'package:flutter/material.dart';
final Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
debugShowCheckedModeBanner: false,
home: HomePage()
);
}
}
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Container(child: Center(child: Text('Hello World')),),
floatingActionButton: FloatingActionButton(
onPressed: () {},
child: Icon(Icons.camera, color: Colors.white, size: 29,),
backgroundColor: Colors.black,
tooltip: 'Capture Picture',
elevation: 5,
splashColor: Colors.grey,
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
);
}
}
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
Use this property with floatingActionButtonLocation property in Scaffold.
FloatingActionButton Flutter - More Details
Try wrapping it in a Center widget or use a crossAxisAlignment of CrossAxisAlignment.center on your Column.
You should pick one part of your Column to be wrapped in a Flexible that will collapse to avoid overflow, or replace some or all of it with a ListView so users can scroll to see the parts that are hidden.
You can use Container and Align widgets as below:
#override
Widget build(BuildContext context) {
return new Scaffold(
body: Center(
),
floatingActionButton: Container(
padding: EdgeInsets.only(bottom: 100.0),
child: Align(
alignment: Alignment.bottomCenter,
child: FloatingActionButton.extended(
onPressed: _getPhoneAuthResult,
icon: Icon(Icons.phone_android),
label: Text("Authenticate using Phone"),
),
),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
);
}
Align(
alignment: Alignment.center,
child: Container(
child: FloatingActionButton(
hoverColor: Colors.black,
elevation: 10,
onPressed: () {},
backgroundColor: Colors.pink,
child: Icon(Icons.add,),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(20.0))),
),
),
),
Here I used "Align" widget to make the FloatingActionButton center. You can see it here.
after end of the floating action button widget, you can Use floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
For Example
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
File _image;
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark(),
title: "Camera App",
home: Scaffold(
appBar: AppBar(
title: Text("Camera App"),
),
body: Center(
child: Center(
child: _image == null
? Text('No image selected.')
: Image.file(_image,
alignment: Alignment.topLeft,
),
),
),
floatingActionButton: FloatingActionButton(
elevation: 50,
hoverColor: Colors.red,
autofocus: true,
onPressed: () {
imagepicker();
},
child: Icon(Icons.camera_alt),
tooltip: 'Pick Image',
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
),
);
}
Future imagepicker() async {
var image = await ImagePicker.pickImage(source: ImageSource.gallery);
setState(() {
_image = image;
});
}
}
The above examples are great, but if you want to have full control over the exact location of the floating action button, you should wrap your FloatingActionButton widget with Align widget and use Alignment(x axis, y axis) to set the exact location.
Align(
alignment: Alignment(0.0, 0.8),
//control the location by changing the numbers here to anything between 1 and -1
child: FloatingActionButton()
)
By changing the logic to use crossAxisAlignment, the mainAxisAlignment and the Flexible the FloatingActionButton were centered at the bottom of the screen
import 'package:flutter/material.dart';
import 'number.dart';
import 'keyboard.dart';
class ContaPage extends StatelessWidget {
#override
Widget build(BuildContext context) => new Scaffold(
body: new Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
new Number(),
new Keyboard(),
new Flexible(
child: new Container(
padding: new EdgeInsets.only(bottom: 16.0),
child: new FloatingActionButton(
elevation: 0.0,
child: new Icon(Icons.check),
backgroundColor: new Color(0xFFE57373),
onPressed: (){}
)
)
)
],
),
);
}
For more freedom of alignment and more than 2 FAB use Stack
Stack(
children: <Widget>[
Center(
child: Center(
child: _image == null
? Text('No image selected.')
: Image.file(_image,
alignment: Alignment.topLeft,
),
),
),
Align(
alignment: Alignment.centerLeft,
child: new FloatingActionButton(
child: const Icon(Icons.skip_previous),
onPressed: () {
}),
),
Align(
alignment: Alignment.centerRight,
child: new FloatingActionButton(
child: const Icon(Icons.skip_next),
onPressed: () {
}),
),
],
)
I modified the code, now the button is in the bottom center but I do not know if it will always stay in the bottom, regardless of the size of the screen.
import 'package:flutter/material.dart';
import 'number.dart';
import 'keyboard.dart';
class ContaPage extends StatelessWidget {
#override
Widget build(BuildContext context) => new Scaffold(
body: new Column(
children: <Widget>[
new Number(),
new Keyboard(),
new Stack(
alignment: new FractionalOffset(0.5, 1.0),
children: <Widget>[
new FloatingActionButton(
elevation: 0.0,
child: new Icon(Icons.check),
backgroundColor: new Color(0xFFE57373),
onPressed: (){}
)
],
)
],
),
);
}
Since Scaffold.floatingActionButton just asks for a Widget, you can wrap your FloatingActionButton with the standard classes for more control if the Scaffold.floatingActionButtonLocation property isn't enough (which already gives you many standard placements, that can also play nicely with your appBar or bottomNavigationBar).
Container is a classic component, but a little overkill given that it combines a variety of widgets.
As others mentioned, Align is handy when you want to position relative to the Align widget itself (which if unconstrained fills to its parent). It can take a variety of preset Alignment constants, or use the Alignment constructor to specify your own relative position, e.g. Alignment(0.0, 0.0) represents the center of the rectangle, (1,1) the bottom right corner, and (-1,-1) the upper left. However, the parent of your FAB is influenced by the Scaffold's floatingActionButtonLocation:, so one way to help take it into account is by setting it to FloatingActionButtonLocation.centerDocked, which when used with Align lets you think about positioning relative to the screen's center.
But maybe you like the basic positioning provided by floatingActionButtonLocation, but just want to shift the FAB by a known number of logical pixels, e.g. to compensate for other widgets on the screen. In that case wrapping in a Padding with the appropriate EdgeInsets should work fine.
Depending on your design simply you can use persistentFooterButtons which accepts a list of widgets as children.
just like here for an example:
persistentFooterButtons: [
new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
child: Align(
alignment: Alignment.center,
child: FloatingActionButton(
onPressed: (){
Navigator.push(context, MaterialPageRoute(builder: (context) => InstallationPage()),);
},
child: new Icon(Icons.add, color: SysColors.ICON_COLOR, size: 34.w,),
),
),
],
)
],

Resources