I have my flutter app with 3 tabs. When the app loads, I want it to load all 3 pages and not only the one it will show.
My problem is, that when swiping to my other tab, it takes a second to load the content and then it animates.
What is the proper way to preload a tab for this case?
Or is it done by saving the widget into a variable?
I use it like this, it won't take any second to load the tab page.
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 3, //The number of tabs
child: Scaffold(
appBar: AppBar(
title: Text('Your tabs page title'),
bottom: TabBar(
tabs: <Widget>[
Tab(
icon: Icon(Icons.someIcone),
text: 'Page-1',
),
Tab(
icon: Icon(Icons.list),
text: 'Page-2',
),
Tab(
icon: Icon(Icons.list),
text: 'Page-3',
),
],
),
),
body: TabBarView(
children: <Widget>[
PageOne(),
PageTwo(),
PageThree(),
],
),
),
);
}
Related
When i set my tabs to scrollable, it will set all my tabs to the center. But i want to find a way that i can align all the tabs to the left. Is there a way for me align the tabs on the left instead of center? Here is my code. Thank you.
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: colorPrimary,
accentColor: colorAccent,
),
home: DefaultTabController(
length: 3,
child: Scaffold(
resizeToAvoidBottomPadding: false,
appBar: AppBar(
bottom: TabBar(
tabs: [
Tab(
child: Text(sign_in),
),
Tab(
child: Text(sign_up),
),
Tab(
child: Text(reset_password),
),
],
indicatorColor: colorWhite,
isScrollable: true,
),
),
body: TabBarView(
children: [
SignIn(),
SignUp(),
ResetPassword(),
],
),
),
),
);
}
}
For those who are interested, this is the answer that works form me
Flutter when I used ListTile ThreeLines, I don't know how to use ThreeLine
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(
appBar: AppBar(
title: Text('ddd'),
),
body:Container(
child: Column(
children: <Widget>[
ListTile(
isThreeLine: true,
leading: Icon(Icons.event_note),
title: Text('Title 1'),
// subtitle: Text('Title2'),
subtitle: Column(
children: <Widget>[
Text('Titile2'),
Text('Title 3'),
Text('Title 4'),
Text('and so on')
],
),
)
],
),
) ,
),
);
}
}
When i delete isThreeLines, the code is Ok
ListTile
Thanks
As from the docs:
The value of subtitle, which is optional, will occupy the space
allocated for an additional line of text, or two lines if isThreeLine
is true.
It basically means the subtitle of the ListTile is given more space to have text which is more than one line in length:
By default, the ListTile in flutter can display only 2 lines. The Title and the SubTitle. In case there is a third line of text to be displayed, the isThreeLine is set to true and can allow another line to be present. The subtitle will be taking care of giving the 3rd line of text. It is expected that, if the isThreeLine is set to true, the subtitle should be non-null. Anything after "\n" inside subtitle will come in next line
ListTile(
title: Text("First Line",
style: TextStyle(fontWeight: FontWeight.bold)),
subtitle: Text("Second One Text "\nThis is Line Third Text"),
isThreeLine: true,
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
GestureDetector(
child: Icon(Icons.delete,color: Colors.red,),
onTap: () {
},
),
],
),
onTap: (){},
)
By default, the ListTile in flutter can display only 2 lines. The Title and the SubTitle. In case there is a third line of text to be displayed, the isThreeLine is set to true and can allow another line to be present. The subtitle will be taking care of giving the 3rd line of text. It is expected that, if the isThreeLine is set to true, the subtitle should be non-null.
Using this simple design, how can I display the second image under the listview? In reality the list will be fetched from firebase where each item is an ExpansionTile, so the height of the listview can in no way be fixed.
The column should be scrollable so you can see the full image if you scroll down below the list.
import 'package:flutter/material.dart';
List<Widget> list = <Widget>[
ListTile(
title: Text('CineArts at the Empire',
style: TextStyle(fontWeight: FontWeight.w500, fontSize: 20.0)),
subtitle: Text('85 W Portal Ave'),
leading: Icon(
Icons.theaters,
color: Colors.blue[500],
),
),
ListTile(
title: Text('The Castro Theater',
style: TextStyle(fontWeight: FontWeight.w500, fontSize: 20.0)),
subtitle: Text('429 Castro St'),
leading: Icon(
Icons.theaters,
color: Colors.blue[500],
),
),
];
class CartWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return SafeArea(
child: Column(children: <Widget>[
Image.network("https://via.placeholder.com/350x150"),
Expanded(
child: ListView(
children: list,
),
),
Image.network("https://via.placeholder.com/350x500"), // error: hides above widget
]));
}
}
The way I understood your problem is that you want the bottom image to appear inside the list view instead of under it, as if it was just another item. Solution: Make it just another item!
More concrete, this is how your implementation for a helper function that enriches the list with the image may look like:
List<Widget> _buildListWithFooterImage(List<Widget> items) {
return items.followedBy([
Image.network("https://via.placeholder.com/350x500")
]);
}
Then, you could use that function during your build:
Widget build(BuildContext context) {
return SafeArea(
child: Column(
children: <Widget>[
Image.network("https://via.placeholder.com/350x150"),
Expanded(
child: ListView(
children: _buildListWithFooterImage(list)
)
),
]
)
);
}
Also, I believe your question is similar to this one.
I am trying to make a simple chat app, so I created a scaffold and my body, will be the messages and my bottomNavigationBar would be my typing field and sending icon.
I added a text field but when typing the navigation bar is hidden by the keyboard.
this is the code of my BottomNavigationBar :
bottomNavigationBar: new Container(
height: ScreenSize.height/12,
/*color: Colors.red,*/
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
new Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
new Container(
child: new Icon(Icons.send),
width:ScreenSize.width/6,
),
],
),
new Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Material(
child: new Container(
child: new TextField(
autofocus: false,
decoration: InputDecoration(
contentPadding: EdgeInsets.all(9.0),
border: InputBorder.none,
hintText: 'Please enter a search term',
),
),
width:ScreenSize.width*4/6,
),
elevation: 4.0,
/*borderRadius: new BorderRadius.all(new Radius.circular(45.0)),*/
clipBehavior: Clip.antiAlias,
type: MaterialType.card,
)
],
),
new Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
new Container(
child: Text('HELLO C1'),
color: Colors.green,
width:ScreenSize.width/6,
),
],
)
],
),
),
here is how it looks when focused :
if you use a Stack on your Scaffold's body, instead of bottomNavigationBar, your nav will push up above the keyboard. even if you fix to the bottom with a Positioned:
Positioned(
bottom: 0.0,
left: 0.0,
right: 0.0,
child: MyNav(),
),
simply wrap your bottom navigation bar with Padding and set it to MediaQuery.of(context).viewInsets,
bottomNavigationBar: Padding(
padding: MediaQuery.of(context).viewInsets,
child: ChatInputField(),
),
Literally just worked through the same issue. Given the code i was refactoring, this worked like a charm. Peep the github link, review his change and apply. Couldn't be much more straight forward: https://github.com/GitJournal/GitJournal/commit/f946fe487a18b2cb8cb1d488026af5c64a8f2f78..
Content of the link above in case the link goes down:
(-)BottomAppBar buildEditorBottonBar(
(+)Widget buildEditorBottonBar(
BuildContext context,
Editor editor,
EditorState editorState,
BottomAppBar buildEditorBottonBar(
folderName = "Root Folder";
}
*REPLACE* return BottomAppBar(
elevation: 0.0,
color: Theme.of(context).scaffoldBackgroundColor,
child: Row(
children: <Widget>[
FlatButton.icon(
icon: Icon(Icons.folder),
label: Text(folderName),
onPressed: () {
var note = editorState.getNote();
editor.moveNoteToFolderSelected(note);
},
)
],
mainAxisAlignment: MainAxisAlignment.center,
*WITH THE WRAPPER* return StickyBottomAppBar(
child: BottomAppBar(
elevation: 0.0,
color: Theme.of(context).scaffoldBackgroundColor,
child: Row(
children: <Widget>[
FlatButton.icon(
icon: Icon(Icons.folder),
label: Text(folderName),
onPressed: () {
var note = editorState.getNote();
editor.moveNoteToFolderSelected(note);
},
)
],
mainAxisAlignment: MainAxisAlignment.center,
),
),
);
}
class StickyBottomAppBar extends StatelessWidget {
final BottomAppBar child;
StickyBottomAppBar({#required this.child});
#override
Widget build(BuildContext context) {
return Transform.translate(
offset: Offset(0.0, -1 * MediaQuery.of(context).viewInsets.bottom),
child: child,
);
}
}
I achieved this by a mix of two things I found separated in the web:
1 - Inside the Scaffold, I put other with only a bottomNavigationBar with a empty Container. For some reason, this trick push all my real bottomNavigationBar up to the top of the keyboard.
Scaffold(
bottomNavigationBar: Container(
height: 0,
),
body: Scaffold(
body: MyWidget(
But, I did not want all the content up, so I got that Package:
2 - I added flutter_keyboard_visibility: ^5.1.0 from
https://pub.dev/packages/flutter_keyboard_visibility
With this Package, you can do anything you want in response to keyboard visibility - is up to you. In my case, I made all content of my real bottomNavigationBar disappear except the textfield, which stay on the top of the keyboard:
[TextFormField] // dont go away,
//The others:
KeyboardVisibilityBuilder(builder: (context, visible) {
return Column(
children: [
visible
? SizedBox(
height: 0,
)
: OtherWidgets(
If you need some kind of button; you can do:
Scaffold(
bottomNavigationBar: bottomNavigationBar,
floatingActionButton: ExampleButton(
text: 'Hello',
),
body: body,
),
You can apply further customizations on the Floating Action Button using parameters in the Scaffold.
There is a simple way to do this if you want to really need to use the bottom navigation bar of the scaffold to put your widgets in rather than put it on a stack. Just wrap your scaffold with another scaffold and it should solve the problem.
return Scaffold(
body: Scaffold(
bottomNavigationBar: yourBottomNavigationBarWidget(),
body: yourBody(),
This works best especially when the height of your widget changes dynamically (because the text user types may introduce multiple lines) and you want the body to resize accordingly. A body in the stack, as suggested by many, will require a bottom padding to be visible over the text field and need to change dynamically as user types which is difficult to handle when you have multiple widgets sitting in and around the text field.
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?