1
0
mirror of https://github.com/nisrulz/flutter-examples.git synced 2025-11-09 04:58:58 +00:00

redo the app file structure and small cleanup in code

This commit is contained in:
Nishant Srivastava
2023-10-17 16:04:06 +02:00
parent fb6f505cbc
commit a9773768eb
132 changed files with 1004 additions and 41 deletions

View File

@@ -0,0 +1,247 @@
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:github.nisrulz.todo_app/Home.dart';
class AppTodo extends StatefulWidget {
const AppTodo({super.key});
@override
State<AppTodo> createState() => _AppTodoState();
}
class _AppTodoState extends State<AppTodo> {
String type = 'food';
String SelectedCategory1 = 'important';
TextEditingController titleController = TextEditingController();
TextEditingController descriptionController = TextEditingController();
void saveTodoToFirebase() async {
try {
final User? user = FirebaseAuth.instance.currentUser;
if (user != null) {
Map<String, dynamic> todoData = {
'title': titleController.text,
'description': descriptionController.text,
'category': SelectedCategory1,
'type': type,
'createdAt': Timestamp.now(),
'userId': user.uid,
};
CollectionReference todos =
FirebaseFirestore.instance.collection('todos');
await todos.add(todoData);
titleController.clear();
descriptionController.clear();
Get.snackbar(
"Added successfully",
"You have added",
backgroundColor: Colors.green,
snackPosition: SnackPosition.BOTTOM,
duration: Duration(seconds: 3),
);
Get.to(() => HomePage());
}
} catch (e) {
print('Error: $e');
Get.snackbar(
"Error",
e.toString(),
backgroundColor: Colors.red,
snackPosition: SnackPosition.BOTTOM,
duration: Duration(seconds: 3),
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Create Todo'),
),
body: Container(
decoration: BoxDecoration(
color: Colors.grey[200],
),
padding: EdgeInsets.all(16.0),
height: double.infinity,
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Card(
elevation: 4,
child: Container(
padding: EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Title',
style: TextStyle(
fontSize: 16, fontWeight: FontWeight.bold),
),
TextField(
controller: titleController,
decoration: InputDecoration(
hintText: 'Enter Title',
filled: true,
fillColor: Colors.white,
),
),
],
),
),
),
SizedBox(height: 16),
Card(
elevation: 4,
child: Container(
padding: EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Task Type',
style: TextStyle(
fontSize: 16, fontWeight: FontWeight.bold),
),
Row(
children: [
ChoiceChip(
label: Text('Important'),
selected: SelectedCategory1 == 'important',
onSelected: (selected) {
setState(() {
SelectedCategory1 = 'important';
});
},
),
SizedBox(width: 8),
ChoiceChip(
label: Text('Planner'),
selected: SelectedCategory1 == 'planner',
onSelected: (selected) {
setState(() {
SelectedCategory1 = 'planner';
});
},
),
],
),
],
),
),
),
SizedBox(height: 16),
Card(
elevation: 4,
child: Container(
padding: EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Description',
style: TextStyle(
fontSize: 16, fontWeight: FontWeight.bold),
),
TextFormField(
controller: descriptionController,
maxLines: 4,
decoration: InputDecoration(
hintText: 'Enter Description',
filled: true,
fillColor: Colors.white,
),
),
],
),
),
),
SizedBox(height: 16),
Card(
elevation: 4,
child: Container(
padding: EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Category',
style: TextStyle(
fontSize: 16, fontWeight: FontWeight.bold),
),
Wrap(
spacing: 8,
children: [
FilterChip(
label: Text('Food'),
selected: type == 'food',
onSelected: (selected) {
setState(() {
type = 'food';
});
},
),
FilterChip(
label: Text('Workout'),
selected: type == 'workout',
onSelected: (selected) {
setState(() {
type = 'workout';
});
},
),
FilterChip(
label: Text('Run'),
selected: type == 'run',
onSelected: (selected) {
setState(() {
type = 'run';
});
},
),
FilterChip(
label: Text('Design'),
selected: type == 'design',
onSelected: (selected) {
setState(() {
type = 'design';
});
},
),
],
),
],
),
),
),
SizedBox(
height: 50,
),
Center(
child: FloatingActionButton(
backgroundColor: Colors.blue,
onPressed: saveTodoToFirebase,
child: Icon(
Icons.add,
color: Colors.white,
),
),
)
],
),
),
),
);
}
}

View File

@@ -0,0 +1,47 @@
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
class Delete extends StatelessWidget {
final String taskId;
const Delete({required this.taskId, Key? key}) : super(key: key);
void _deleteTask() {
final CollectionReference tasks =
FirebaseFirestore.instance.collection('todos');
tasks.doc(taskId).delete().then((value) {
Get.back();
Get.snackbar(
'Success',
'Task updated successfully',
snackPosition: SnackPosition.BOTTOM,
backgroundColor: Colors.green,
colorText: Colors.white,
);
}).catchError((error) {
print('Error deleting task in Firestore: $error');
});
}
@override
Widget build(BuildContext context) {
return AlertDialog(
title: Text('Delete Task'),
content: Text('Are you sure you want to delete this task?'),
actions: <Widget>[
ElevatedButton(
onPressed: () {
Get.back();
},
child: Text('Cancel'),
),
ElevatedButton(
onPressed: _deleteTask,
child: Text('Delete'),
),
],
);
}
}

View File

@@ -0,0 +1,247 @@
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
class Edit extends StatefulWidget {
final String taskId;
final String initialTitle;
final String initialDescription;
final String initialTaskType;
final String initialCategory;
const Edit({
super.key,
required this.taskId,
required this.initialTitle,
required this.initialDescription,
required this.initialTaskType,
required this.initialCategory,
});
@override
State<Edit> createState() => _EditState();
}
class _EditState extends State<Edit> {
late TextEditingController titleController;
late TextEditingController descriptionController;
String selectedTaskType = '';
String selectedCategory = '';
@override
void initState() {
super.initState();
titleController = TextEditingController(text: widget.initialTitle);
descriptionController =
TextEditingController(text: widget.initialDescription);
selectedTaskType = widget.initialTaskType;
selectedCategory = widget.initialCategory;
}
void updateTask() async {
try {
CollectionReference todos =
FirebaseFirestore.instance.collection('todos');
await todos.doc(widget.taskId).update({
'title': titleController.text,
'description': descriptionController.text,
'type': selectedTaskType,
'category': selectedCategory,
});
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Task updated successfully.'),
),
);
Navigator.of(context).pop();
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Failed to update the task: $e'),
),
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Edit Task'),
),
body: Container(
decoration: BoxDecoration(
color: Colors.grey[200],
),
padding: EdgeInsets.all(16.0),
height: double.infinity,
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Card(
elevation: 4,
child: Container(
padding: EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Title',
style: TextStyle(
fontSize: 16, fontWeight: FontWeight.bold),
),
TextField(
controller: titleController,
decoration: InputDecoration(
hintText: 'Enter Title',
filled: true,
fillColor: Colors.white,
),
),
],
),
),
),
SizedBox(height: 16),
Card(
elevation: 4,
child: Container(
padding: EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Task Type',
style: TextStyle(
fontSize: 16, fontWeight: FontWeight.bold),
),
Row(
children: [
ChoiceChip(
label: Text('Important'),
selected: selectedTaskType == 'important',
onSelected: (selected) {
setState(() {
selectedTaskType = 'important';
});
},
),
SizedBox(width: 8),
ChoiceChip(
label: Text('Planner'),
selected: selectedTaskType == 'planner',
onSelected: (selected) {
setState(() {
selectedTaskType = 'planner';
});
},
),
],
),
],
),
),
),
SizedBox(height: 16),
Card(
elevation: 4,
child: Container(
padding: EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Description',
style: TextStyle(
fontSize: 16, fontWeight: FontWeight.bold),
),
TextFormField(
controller: descriptionController,
maxLines: 4,
decoration: InputDecoration(
hintText: 'Enter Description',
filled: true,
fillColor: Colors.white,
),
),
],
),
),
),
SizedBox(height: 16),
Card(
elevation: 4,
child: Container(
padding: EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Category',
style: TextStyle(
fontSize: 16, fontWeight: FontWeight.bold),
),
Wrap(
spacing: 8,
children: [
FilterChip(
label: Text('Food'),
selected: selectedCategory == 'food',
onSelected: (selected) {
setState(() {
selectedCategory = 'food';
});
},
),
FilterChip(
label: Text('Workout'),
selected: selectedCategory == 'workout',
onSelected: (selected) {
setState(() {
selectedCategory = 'workout';
});
},
),
FilterChip(
label: Text('Run'),
selected: selectedCategory == 'run',
onSelected: (selected) {
setState(() {
selectedCategory = 'run';
});
},
),
FilterChip(
label: Text('Design'),
selected: selectedCategory == 'design',
onSelected: (selected) {
setState(() {
selectedCategory = 'design';
});
},
),
],
),
],
),
),
),
SizedBox(
height: 50,
),
Center(
child: ElevatedButton(
onPressed: updateTask,
child: Text('Save Changes'),
),
),
],
),
),
),
);
}
}

View File

@@ -0,0 +1,151 @@
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:github.nisrulz.todo_app/AddTodo.dart';
import 'package:github.nisrulz.todo_app/Delete.dart';
import 'package:github.nisrulz.todo_app/Edit.dart';
import 'package:github.nisrulz.todo_app/Signin.dart';
class HomePage extends StatelessWidget {
final FirebaseAuth _auth = FirebaseAuth.instance;
HomePage({super.key});
Future<void> _signOut() async {
try {
await _auth.signOut();
Get.offAll(() => Signin());
} catch (e) {
print('Sign-out error: $e');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: [
IconButton(
icon: Icon(Icons.logout),
onPressed: () {
_signOut();
},
),
],
),
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.blue,
onPressed: () {
Get.to(() => AppTodo());
},
child: Icon(Icons.add, color: Colors.white),
),
body: _buildTodoList(),
);
}
Widget _buildTodoList() {
final User? user = FirebaseAuth.instance.currentUser;
if (user == null) {
return Center(
child: Text('User not logged in.'),
);
}
return StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance
.collection('todos')
.where('userId', isEqualTo: user.uid)
.snapshots(),
builder: (context, snapshot) {
if (snapshot.hasError) {
return Center(
child: Text('Error: ${snapshot.error}'),
);
}
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: CircularProgressIndicator(),
);
}
final List<Widget> todoWidgets = [];
final todos = snapshot.data?.docs;
for (var todo in todos!) {
final title = todo['title'];
final description = todo['description'];
final taskType = todo['type'];
final category = todo['category'];
todoWidgets.add(
Card(
elevation: 4,
margin: EdgeInsets.all(19.0),
child: Padding(
padding: const EdgeInsets.all(19.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Title: $title',
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
Text('Description: $description'),
Text('Task Type: $taskType'),
Text('Category: $category'),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
ElevatedButton.icon(
onPressed: () {
Get.to(() => Edit(
taskId: todo.id,
initialTitle: todo['title'],
initialDescription: todo['description'],
initialTaskType: todo['type'],
initialCategory: todo['category'],
));
},
icon: Icon(Icons.edit),
label: const Text(
"Edit",
style: TextStyle(color: Colors.orange),
),
),
const SizedBox(
height: 20,
),
ElevatedButton.icon(
onPressed: () {
Get.to(() => Delete(taskId: todo.id));
},
icon: Icon(Icons.delete, color: Colors.red),
label: const Text(
"Delete",
style: TextStyle(color: Colors.pink),
),
)
],
)
],
),
),
),
);
}
return ListView(
children: todoWidgets,
);
},
);
}
}

View File

@@ -0,0 +1,142 @@
import 'package:firebase_auth/firebase_auth.dart' as firebase_auth;
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:github.nisrulz.todo_app/Home.dart';
import 'package:github.nisrulz.todo_app/Signup.dart';
class Signin extends StatefulWidget {
const Signin({super.key});
@override
State<Signin> createState() => _SigninState();
}
class _SigninState extends State<Signin> {
firebase_auth.FirebaseAuth firebaseauth = firebase_auth.FirebaseAuth.instance;
final TextEditingController _emailcontroller = TextEditingController();
final TextEditingController _passwordcontroller = TextEditingController();
@override
void dispose() {
_emailcontroller.dispose();
_passwordcontroller.dispose();
super.dispose();
}
Future<void> _Signin() async {
try {
final String email = _emailcontroller.text;
final String password = _passwordcontroller.text;
await firebaseauth.signInWithEmailAndPassword(
email: email,
password: password,
);
Get.snackbar(
"Sign In Success",
"You have successfully signed in.",
backgroundColor: Colors.green,
snackPosition: SnackPosition.BOTTOM,
duration: Duration(seconds: 3),
);
Get.to(() => HomePage());
} catch (e) {
Get.snackbar(
"Sign In Error",
e.toString(),
backgroundColor: Colors.red,
snackPosition: SnackPosition.BOTTOM,
duration: Duration(seconds: 3),
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: Container(
height: Get.size.height,
width: Get.size.width,
color: Colors.black,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
"Login ",
style: TextStyle(
color: Colors.green,
fontSize: 25,
fontWeight: FontWeight.bold),
),
const SizedBox(height: 20),
const SizedBox(height: 20),
SizedBox(
height: 20,
),
SizedBox(height: 20),
Container(
width: Get.size.width - 60,
height: 60,
child: Card(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: Center(
child: TextField(
controller: _emailcontroller,
decoration: InputDecoration(
hintText: 'Email',
border: InputBorder.none,
),
),
),
),
),
),
SizedBox(height: 20),
Container(
width: Get.size.width - 60,
height: 60,
child: Card(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: Center(
child: TextField(
controller: _passwordcontroller,
obscureText: true,
decoration: InputDecoration(
hintText: 'Password',
border: InputBorder.none,
),
),
),
),
),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: _Signin,
child: Text("Sign In"),
),
SizedBox(height: 20),
GestureDetector(
onTap: () {
Get.to(() => Signup());
},
child: const Text(
"Don't have an account? Sign Up",
style: TextStyle(
color: Colors.white,
decoration: TextDecoration.underline,
fontSize: 18),
),
),
],
),
),
),
);
}
}

View File

@@ -0,0 +1,141 @@
import 'package:firebase_auth/firebase_auth.dart' as firebase_auth;
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:github.nisrulz.todo_app/Signin.dart';
class Signup extends StatefulWidget {
const Signup({super.key});
@override
State<Signup> createState() => _SignupState();
}
class _SignupState extends State<Signup> {
firebase_auth.FirebaseAuth firebaseauth = firebase_auth.FirebaseAuth.instance;
final TextEditingController _emailcontroller = TextEditingController();
final TextEditingController _passwordcontroller = TextEditingController();
@override
void dispose() {
_emailcontroller.dispose();
_passwordcontroller.dispose();
super.dispose();
}
Future<void> _signUp() async {
try {
final String email = _emailcontroller.text;
final String password = _passwordcontroller.text;
await firebaseauth.createUserWithEmailAndPassword(
email: email,
password: password,
);
Get.snackbar(
"Signed Up Success",
"You have successfully signed up.",
backgroundColor: Colors.green,
snackPosition: SnackPosition.BOTTOM,
duration: Duration(seconds: 3),
);
Get.to(() => const Signin());
} catch (e) {
Get.snackbar(
"Sign Up Error",
e.toString(),
backgroundColor: Colors.red,
snackPosition: SnackPosition.BOTTOM,
duration: Duration(seconds: 3),
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: Container(
height: Get.size.height,
width: Get.size.width,
color: Colors.black,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
"Sign Up",
style: TextStyle(
color: Colors.orange,
fontSize: 25,
fontWeight: FontWeight.bold),
),
const SizedBox(height: 20),
const SizedBox(height: 20),
SizedBox(
height: 20,
),
SizedBox(height: 20),
Container(
width: Get.size.width - 60,
height: 60,
child: Card(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: Center(
child: TextField(
controller: _emailcontroller,
decoration: InputDecoration(
hintText: 'Email',
border: InputBorder.none,
),
),
),
),
),
),
SizedBox(height: 20),
Container(
width: Get.size.width - 60,
height: 60,
child: Card(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: Center(
child: TextField(
controller: _passwordcontroller,
obscureText: true,
decoration: InputDecoration(
hintText: 'Password',
border: InputBorder.none,
),
),
),
),
),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: _signUp,
child: Text("Sign Up"),
),
SizedBox(height: 20),
GestureDetector(
onTap: () {
Get.to(() => Signin());
},
child: const Text(
"Already have an account? Login ",
style: TextStyle(
color: Colors.white,
decoration: TextDecoration.underline,
fontSize: 18),
),
),
],
),
),
),
);
}
}

View File

@@ -0,0 +1,80 @@
// File generated by FlutterFire CLI.
// ignore_for_file: lines_longer_than_80_chars, avoid_classes_with_only_static_members
import 'package:firebase_core/firebase_core.dart' show FirebaseOptions;
import 'package:flutter/foundation.dart'
show defaultTargetPlatform, kIsWeb, TargetPlatform;
/// Default [FirebaseOptions] for use with your Firebase apps.
///
/// Example:
/// ```dart
/// import 'firebase_options.dart';
/// // ...
/// await Firebase.initializeApp(
/// options: DefaultFirebaseOptions.currentPlatform,
/// );
/// ```
class DefaultFirebaseOptions {
static FirebaseOptions get currentPlatform {
if (kIsWeb) {
return web;
}
switch (defaultTargetPlatform) {
case TargetPlatform.android:
return android;
case TargetPlatform.iOS:
return ios;
case TargetPlatform.macOS:
return macos;
case TargetPlatform.windows:
throw UnsupportedError(
'DefaultFirebaseOptions have not been configured for windows - '
'you can reconfigure this by running the FlutterFire CLI again.',
);
case TargetPlatform.linux:
throw UnsupportedError(
'DefaultFirebaseOptions have not been configured for linux - '
'you can reconfigure this by running the FlutterFire CLI again.',
);
default:
throw UnsupportedError(
'DefaultFirebaseOptions are not supported for this platform.',
);
}
}
static const FirebaseOptions web = FirebaseOptions(
apiKey: 'AIzaSyAZcBxEiSUSbrJdh2TqJfO4ySu_RRydpmk',
appId: '1:845969639687:web:5e46819431e9bc03ba9da2',
messagingSenderId: '845969639687',
projectId: 'todoapp-cbd21',
authDomain: 'todoapp-cbd21.firebaseapp.com',
storageBucket: 'todoapp-cbd21.appspot.com',
);
static const FirebaseOptions android = FirebaseOptions(
apiKey: 'AIzaSyDJUJmEdax-zup4YIu4-Jc_E8VUaga-QC4',
appId: '1:845969639687:android:fa41ba9dffeec1edba9da2',
messagingSenderId: '845969639687',
projectId: 'todoapp-cbd21',
storageBucket: 'todoapp-cbd21.appspot.com',
);
static const FirebaseOptions ios = FirebaseOptions(
apiKey: 'AIzaSyBeRsZEhruSSbrrn-ayR5Nh5uuv-nTXeVs',
appId: '1:845969639687:ios:3416ba56912c41d1ba9da2',
messagingSenderId: '845969639687',
projectId: 'todoapp-cbd21',
storageBucket: 'todoapp-cbd21.appspot.com',
iosBundleId: 'com.example.todoApp',
);
static const FirebaseOptions macos = FirebaseOptions(
apiKey: 'AIzaSyBeRsZEhruSSbrrn-ayR5Nh5uuv-nTXeVs',
appId: '1:845969639687:ios:e5ec4ea82076de1cba9da2',
messagingSenderId: '845969639687',
projectId: 'todoapp-cbd21',
storageBucket: 'todoapp-cbd21.appspot.com',
iosBundleId: 'com.example.todoApp.RunnerTests',
);
}

View File

@@ -0,0 +1,120 @@
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:get/get_navigation/src/root/get_material_app.dart';
import 'package:github.nisrulz.todo_app/Signup.dart';
import 'firebase_options.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return GetMaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: Signup(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
// This widget is the home page of your application. It is stateful, meaning
// that it has a State object (defined below) that contains fields that affect
// how it looks.
// This class is the configuration for the state. It holds the values (in this
// case the title) provided by the parent (in this case the App widget) and
// used by the build method of the State. Fields in a Widget subclass are
// always marked "final".
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
// This call to setState tells the Flutter framework that something has
// changed in this State, which causes it to rerun the build method below
// so that the display can reflect the updated values. If we changed
// _counter without calling setState(), then the build method would not be
// called again, and so nothing would appear to happen.
_counter++;
});
}
@override
Widget build(BuildContext context) {
// This method is rerun every time setState is called, for instance as done
// by the _incrementCounter method above.
//
// The Flutter framework has been optimized to make rerunning build methods
// fast, so that you can just rebuild anything that needs updating rather
// than having to individually change instances of widgets.
return Scaffold(
appBar: AppBar(
// TRY THIS: Try changing the color here to a specific color (to
// Colors.amber, perhaps?) and trigger a hot reload to see the AppBar
// change color while the other colors stay the same.
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title),
),
body: Center(
// Center is a layout widget. It takes a single child and positions it
// in the middle of the parent.
child: Column(
// Column is also a layout widget. It takes a list of children and
// arranges them vertically. By default, it sizes itself to fit its
// children horizontally, and tries to be as tall as its parent.
//
// Column has various properties to control how it sizes itself and
// how it positions its children. Here we use mainAxisAlignment to
// center the children vertically; the main axis here is the vertical
// axis because Columns are vertical (the cross axis would be
// horizontal).
//
// TRY THIS: Invoke "debug painting" (choose the "Toggle Debug Paint"
// action in the IDE, or press "p" in the console), to see the
// wireframe for each widget.
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headlineMedium,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}