Is there a way to render a list then scroll to the bottom.
I understand you can manually scroll to the bottom using ScrollController when a new item is added (like in this question: Programmatically scrolling to the end of a ListView), but how should I automatically scroll to the bottom of the list when the list is built without adding a new item.
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage();
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return new Scaffold(
body: new Column(
children: <Widget>[
new Expanded(
child: new ListView.builder(
itemCount: 200,
itemBuilder: (context, index) {
return new ListTile(
title: new Text("title $index"),
);
},
),
),
],
),
);
}
}
You get this behavior if you use reverse: true
child: new ListView.builder(
reverse: true
https://docs.flutter.io/flutter/widgets/ListView/ListView.builder.html
Related
I build an app in which there are two pages(screens),the first page receives the data from second page.But the problem is that before getting the data from second page it is showing "null" on the first page screen.Below are the codes of these two pages.Note:The first page screen is the main launcher screen.
First Page
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
String value;
MyHomePage({Key key,this.value}):super(key:key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Flutter"),
),
body:Center(
child:new Text("${widget.value}") )
}
Second Page
class _List extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: MyList(),
);
}
}
class MyList extends StatefulWidget {
#override
_MyListState createState() => _MyListState();
}
class _MyListState extends State<MyList> {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: Text("List"),
),
body: new Container(
padding: new EdgeInsets.only(left: 5.0,top: 20.0,right: 5.0),
child: new Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
GestureDetector(
onTap: (){
var route=new MaterialPageRoute(builder: (BuildContext context)=>new MyHomePage(value: "Apple",),
);
Navigator.of(context).push(route);
},
child: new Card(
child:
new Column(
children: <Widget>[
new Text('Apple'),
new Text('Banana')
],
),
),
),
);
}
}
You can use a blank Container() widget instead of Text() widget like the code below :
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Flutter"),
),
body:Center(
child: widget.value==null ? Container() : new Text("${widget.value}")
)
);
}
}
I want to display an Image on top of my entire app. So I Placed an image and my dashboard in a column in Main.dart file
My main.dart file.
void main() => runApp(new MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
body: new SafeArea(
child: Column(
children: <Widget>[
new Image.asset('assets/ads.png'),
new Expanded(
child: Dashboard(),
)
],
),
),
),
);
}
}
and Dashboard.dart
import 'package:flutter/material.dart';
class Dashboard extends StatefulWidget {
#override
_DashboardState createState() => _DashboardState();
}
class _DashboardState extends State<Dashboard> {
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new Scaffold(
appBar: new AppBar(title: new Text('Books')),
body: new Container(
child: new Center(
child: new Text('data'),
),
),
),
);
}
}
Now, this code generates output like this.
I need regular sized Appar. This AppBar is really big. Can someone suggest what's wrong here?
Do Like This :-
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
return new MaterialApp(
debugShowCheckedModeBanner: false,
home: new Scaffold(
body: new SafeArea(
child: Column(
children: <Widget>[
new Image.network("https://via.placeholder.com/350x100"),
new Expanded(
child: Dashboard(),
)
],
),
),
),
);
}
}
class Dashboard extends StatefulWidget {
#override
_DashboardState createState() => _DashboardState();
}
class _DashboardState extends State<Dashboard> {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(title: new Text('Books')),
body: new Container(
child: new Center(
child: new Text('data'),
),
),
);
}
}
I'm using the Flutter UserAccountsDrawerHeader widget to display the user's data but I could not figure out how to implement the onDetailsPressed() function to call the user details. Here is my code:
import 'package:flutter/material.dart';
class HomeScreen extends StatefulWidget {
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
#override
Widget build(BuildContext context) {
return new Scaffold(
drawer: _buildDrawer(context),
appBar: _buildAppBar(),
);
}
}
Widget _buildAppBar() {
return new AppBar();
}
Widget _buildDrawer(BuildContext context) {
return new Drawer(
child: new ListView(
children: <Widget>[
new UserAccountsDrawerHeader(
accountName: new Text("Cleudice Santos"),
accountEmail: new Text("cleudice.ms#gmail.com"),
onDetailsPressed: () {},
),
new ListTile(
title: new Text("Visão geral"),
leading: new Icon(Icons.dashboard),
onTap: () {
print("Visão geral");
},
),
],
),
);
}
I want to click the arrow and show the account details as shown below. That is, overlapping the content of the drawer. As the Gmail app does.
Basically, what you should be doing is replacing the rest of the content with user details rather than the current list. The simplest way to do this is to make your drawer into a stateful widget and have a boolean that keeps track of whether user details or the normal list should be shown.
I've added that to your code (and added a bit to make it self-contained so you can paste it to a new file to test out):
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
MyAppState createState() => MyAppState();
}
class MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: HomeScreen(),
);
}
}
class HomeScreen extends StatefulWidget {
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
#override
Widget build(BuildContext context) {
return Scaffold(
drawer: UserDetailDrawer(),
appBar: _buildAppBar(),
);
}
}
Widget _buildAppBar() {
return AppBar();
}
class UserDetailDrawer extends StatefulWidget {
#override
_UserDetailDrawerState createState() => _UserDetailDrawerState();
}
class _UserDetailDrawerState extends State<UserDetailDrawer> {
bool showUserDetails = false;
Widget _buildDrawerList() {
return ListView(
children: <Widget>[
ListTile(
title: Text("Visão geral"),
leading: Icon(Icons.dashboard),
onTap: () {
print("Visão geral");
},
),
ListTile(
title: Text("Another tile??"),
leading: Icon(Icons.question_answer),
),
],
);
}
Widget _buildUserDetail() {
return Container(
color: Colors.lightBlue,
child: ListView(
children: [
ListTile(
title: Text("User details"),
leading: Icon(Icons.info_outline),
)
],
),
);
}
#override
Widget build(BuildContext context) {
return Drawer(
child: Column(children: [
UserAccountsDrawerHeader(
accountName: Text("Cleudice Santos"),
accountEmail: Text("cleudice.ms#gmail.com"),
onDetailsPressed: () {
setState(() {
showUserDetails = !showUserDetails;
});
},
),
Expanded(child: showUserDetails ? _buildUserDetail() : _buildDrawerList())
]),
);
}
}
I am learning flutter and currently testing different aspects of it for app development. My eventual plan is to have two tabs, each pulling a list from an API and displaying it in a list view. My concern is that it seems every time you switch tabs, the tabs get fully redrawn as new. How do I save the current state of a tab and all the children so they don't reset when I visit the tab again? Am i thinking about i wrong? Am I supposed to manually save everything to variables and re-populate it every time the tab is drawn?
Below is a quick example I have been testing. It is a simple two tab app with form fields on each page. If I run the app, then type something into the form field, when I switch to tab two and back, the contents of the form field have been removed.
import 'package:flutter/material.dart';
void main() {
print("start");
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Tab Test',
home: new MyTabbedPage(),
);
}
}
class MyTabbedPage extends StatefulWidget {
const MyTabbedPage({Key key}) : super(key: key);
#override
_MyTabbedPageState createState() => new _MyTabbedPageState();
}
class _MyTabbedPageState extends State<MyTabbedPage>
with SingleTickerProviderStateMixin {
final List<Tab> myTabs = <Tab>[
new Tab(text: 'LEFT'),
new Tab(text: 'RIGHT'),
];
TabController _tabController;
var index = 0;
#override
void initState() {
super.initState();
_tabController = new TabController(
vsync: this, length: myTabs.length, initialIndex: index);
}
#override
void dispose() {
_tabController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
bottom: new TabBar(
controller: _tabController,
tabs: myTabs,
),
),
body: new TabBarView(
controller: _tabController,
children: myTabs.map((Tab tab) {
return new Center(
child: new TextFormField(
decoration: new InputDecoration(labelText: 'Type Something:'),
));
}).toList(),
),
);
}
}
So, i think I found the answer in setState. I reworked my sample above to have a button that increments a counter on each tab respectively. Using setState to update the vote count allows me to save the state of the field and persist it when I changes tabs. I am adding my sample code below for reference.
import 'package:flutter/material.dart';
void main() {
print("start");
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Tab Test',
home: new MyTabbedPage(),
);
}
}
class MyTabbedPage extends StatefulWidget {
const MyTabbedPage({Key key}) : super(key: key);
#override
_MyTabbedPageState createState() => new _MyTabbedPageState();
}
class _MyTabbedPageState extends State<MyTabbedPage>
with SingleTickerProviderStateMixin {
final List<Tab> myTabs = <Tab>[
new Tab(text: 'LEFT'),
new Tab(text: 'RIGHT'),
];
TabController _tabController;
var index = 0;
#override
void initState() {
super.initState();
_tabController = new TabController(
vsync: this, length: myTabs.length, initialIndex: index);
}
#override
void dispose() {
_tabController.dispose();
super.dispose();
}
int votesA = 0;
int votesB = 0;
void voteUpA() {
setState(() => votesA++);
}
void voteUpB() {
setState(() => votesB++);
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
bottom: new TabBar(
controller: _tabController,
tabs: myTabs,
),
),
body: new TabBarView(
controller: _tabController,
children: <Widget>[
new Column(
children: <Widget>[
Text("Hello Flutter - $votesA"),
new RaisedButton(onPressed: voteUpA, child: new Text("click here"))
],
),
new Column(
children: <Widget>[
Text("Hello Flutter - $votesB"),
new RaisedButton(onPressed: voteUpB, child: new Text("click here"))
],
),
],
),
);
}
}
I was following this Stack Overflow post for making a sticky footer. The footer performs like it needs to, but is there a way to add transparency so the items in the list behind the footer can be visible?
Solid footer
Transparent footer
Here is all the code for making the solid footer
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage();
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return new Scaffold(
body: new Column(
children: <Widget>[
new Expanded(
child: new ListView.builder(
itemCount: 200,
itemBuilder: (context, index) {
return new ListTile(
title: new Text("title $index"),
);
},
),
),
new Container(
height: 40.0,
color: Colors.red,
),
],
),
);
}
}
You can use Stack to display widgets on the top of each others.
new Scaffold(
body: new Stack(
alignment: Alignment.bottomCenter,
children: [
new ListView(...),
new Container(height: 40.0, color: Colors.red),
],
),
),