├── ch16 ├── ex16-1.md ├── ex16-2.md ├── ex16-4.md ├── ex16-3.md ├── ex16-6.md ├── README.md └── ex16-5.md ├── appendix ├── ex1-7.md ├── ex1-5.md ├── ex1-2.md ├── ex1-1.md ├── ex1-4.md ├── ex1-6.md ├── ex1-3.md └── README.md ├── ch14 ├── ex14-3.md ├── README.md ├── ex14-2.md └── ex14-1.md ├── ch13 ├── ex13-6.md ├── ex13-4.md ├── ex13-5.md ├── ex13-7.md ├── README.md ├── ex13-1.md ├── ex13-2.md └── ex13-3.md ├── ch15 ├── ex15-1.md ├── ex15-2.md ├── ex15-10.md ├── ex15-7.md ├── ex15-3.md ├── ex15-8.md ├── ex15-4.md ├── ex15-5.md ├── README.md ├── ex15-9.md └── ex15-6.md ├── ch17 ├── ex17-9.md ├── ex17-1.md ├── ex17-2.md ├── ex17-5.md ├── examples │ └── lab01 │ │ └── README.md ├── ex17-3.md ├── README.md ├── ex17-6.md ├── ex17-4.md ├── ex17-7.md └── ex17-8.md ├── assets ├── example1.json └── example2.json ├── ch07 ├── ex7-1.md ├── ex7-2.md ├── README.md ├── ex7-6.md ├── ex7-4.md ├── ex7-3.md └── ex7-5.md ├── images ├── flame_solar_system.png └── flutter-dart-cookbook-sml.png ├── ch01 ├── ex-double.md ├── ex-integer.md ├── ex-bool.md ├── ex-dart.md ├── ex-string.md ├── ex-final.md ├── ex-null.md ├── README.md ├── ex1-11.md ├── ex1-10.md ├── ex-const.md └── ex-print.md ├── ch03 ├── ex3-1.md ├── README.md ├── ex3-2.md ├── ex3-4.md ├── ex3-5.md ├── ex3-6.md └── ex3-3.md ├── .gitignore ├── ch04 ├── ex4-1.md ├── ex4-5.md ├── ex4-2.md ├── ex4-6.md ├── README.md ├── ex4-4.md ├── ex4-3.md └── ex4-7.md ├── ch06 ├── ex6-1.md ├── ex6-0.md ├── README.md ├── ex6-2.md ├── ex6-3.md ├── ex6-4.md ├── ex6-5.md ├── ex6-7.md └── ex6-6.md ├── ch05 ├── README.md ├── ex5-2.md ├── ex5-1.md ├── ex5-4.md ├── ex5-3.md └── ex5-5.md ├── ch02 ├── README.md ├── ex-if.md ├── ex-switch.md ├── ex-exception.md ├── ex-enum.md ├── ex-while.md └── ex-for.md ├── ch09 ├── ex9-5.md ├── ex9-4.md ├── README.md ├── ex9-1.md ├── ex9-2.md ├── ex9-3.md ├── ex9-6.md ├── ex9-8.md ├── column-example.md └── ex9-7.md ├── ch12 ├── ex12-5.md ├── README.md ├── ex12-4.md ├── ex12-1.md ├── ex12-3.md ├── ex12-2.md └── ex12-6.md ├── ch11 ├── README.md ├── ex11-3.md ├── ex11-4.md ├── ex11-1.md ├── ex11-2.md ├── ex11-5.md └── ex11-6.md └── ch10 ├── README.md ├── ex10-4.md ├── ex10-1.md ├── ex10-2.md ├── ex10-5.md ├── ex10-6.md └── ex10-3.md /ch16/ex16-1.md: -------------------------------------------------------------------------------- 1 | # 16.1 Introducing Cloud Providers 2 | 3 | # Example 4 | -------------------------------------------------------------------------------- /appendix/ex1-7.md: -------------------------------------------------------------------------------- 1 | # 1.7 Selecting a release channel 2 | 3 | ## Example 4 | 5 | -------------------------------------------------------------------------------- /ch14/ex14-3.md: -------------------------------------------------------------------------------- 1 | # 14.3 Testing Android/iOS device compatibility 2 | 3 | # Example 4 | 5 | -------------------------------------------------------------------------------- /ch13/ex13-6.md: -------------------------------------------------------------------------------- 1 | # 13.6 Using JSON Serialization 2 | 3 | # Example 4 | 5 | ```dart 6 | ``` 7 | -------------------------------------------------------------------------------- /ch15/ex15-1.md: -------------------------------------------------------------------------------- 1 | # 15.1 Integrating Firebase backend with Flutter 2 | 3 | # Example 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /ch17/ex17-9.md: -------------------------------------------------------------------------------- 1 | # 17.9 Adding input for user interactivity 2 | 3 | # Example 4 | 5 | ```dart 6 | ``` 7 | 8 | -------------------------------------------------------------------------------- /assets/example1.json: -------------------------------------------------------------------------------- 1 | { 2 | "1": "January", 3 | "2": "February", 4 | "3": "March", 5 | "4": "April" 6 | } 7 | -------------------------------------------------------------------------------- /ch07/ex7-1.md: -------------------------------------------------------------------------------- 1 | # 7.1 Mocking an interface 2 | 3 | link needed for (Figure 3.1. Example Excalidraw drawing) 4 | 5 | -------------------------------------------------------------------------------- /appendix/ex1-5.md: -------------------------------------------------------------------------------- 1 | # Installing the Dart SDK 2 | 3 | ## Example 4 | 5 | [https://dart.dev/get-dart](dart.dev/getdart) 6 | -------------------------------------------------------------------------------- /ch15/ex15-2.md: -------------------------------------------------------------------------------- 1 | # 15.2 Setting up Firebase Project 2 | 3 | [https://console.firebase.google.com](Firebase Console) 4 | 5 | 6 | -------------------------------------------------------------------------------- /images/flame_solar_system.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rosera/flutter-and-dart-cookbook/HEAD/images/flame_solar_system.png -------------------------------------------------------------------------------- /ch16/ex16-2.md: -------------------------------------------------------------------------------- 1 | # 16.2 Working with Identity and Access Management 2 | 3 | # Example 4 | 5 | *add link to figure 13.1* 6 | 7 | 8 | -------------------------------------------------------------------------------- /images/flutter-dart-cookbook-sml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rosera/flutter-and-dart-cookbook/HEAD/images/flutter-dart-cookbook-sml.png -------------------------------------------------------------------------------- /appendix/ex1-2.md: -------------------------------------------------------------------------------- 1 | # 1.2 How to run a Dart application 2 | 3 | ## Example 4 | 5 | From the command line: 6 | ```dart 7 | dart main.dart 8 | ``` 9 | -------------------------------------------------------------------------------- /appendix/ex1-1.md: -------------------------------------------------------------------------------- 1 | # 1.1 How to install the Dart SDK 2 | 3 | ## Example 4 | 5 | Follow the instructions at: [https://dart.dev/get-dart](dart.dev/get-dart) 6 | 7 | -------------------------------------------------------------------------------- /appendix/ex1-4.md: -------------------------------------------------------------------------------- 1 | # 1.4 Developing with VS Code 2 | 3 | # Example 4 | 5 | [https://docs.flutter.dev/development/tools/vs-code](flutter.dev/vscode) 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /appendix/ex1-6.md: -------------------------------------------------------------------------------- 1 | # Running a Dart application 2 | 3 | ## Example 4 | 5 | ```dart 6 | void main() { 7 | print('Hello, Dart World!'); 8 | } 9 | 10 | ``` 11 | -------------------------------------------------------------------------------- /ch16/ex16-4.md: -------------------------------------------------------------------------------- 1 | # 16.4 Using a spreadsheet as a backend 2 | 3 | # Example 4 | 5 | ```console 6 | [https://docs.google.com/document/d/documentId/edit]() 7 | ``` 8 | 9 | 10 | -------------------------------------------------------------------------------- /ch16/ex16-3.md: -------------------------------------------------------------------------------- 1 | # 16.3 Using Cloud Storage to host an API 2 | 3 | # Example: curl 4 | 5 | ``` 6 | curl --request GET [STORAGE_ENDPOINT]/[FOLDER]/[JSON_FILE] 7 | 8 | ``` 9 | 10 | 11 | -------------------------------------------------------------------------------- /appendix/ex1-3.md: -------------------------------------------------------------------------------- 1 | # 1.3 Extending Android Studio to support Dart 2 | 3 | ## Example 4 | Follow the instructions at: [https://docs.flutter.dev/development/tools/android-studio#installation-and-setup](flutter.dev) 5 | -------------------------------------------------------------------------------- /assets/example2.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [ 3 | { 4 | "title": "January" 5 | }, 6 | { 7 | "title": "February" 8 | }, 9 | { 10 | "title": "March" 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /ch15/ex15-10.md: -------------------------------------------------------------------------------- 1 | # 15.10 Using Flutter Web with Firebase Hosting 2 | 3 | ## Example: Firevase Emulator Suite 4 | 5 | ```bash 6 | firebase init 7 | ``` 8 | 9 | ```bash 10 | flutter build web 11 | ``` 12 | 13 | ```bash 14 | firebase emulators:start --only hosting 15 | ``` 16 | 17 | -------------------------------------------------------------------------------- /ch15/ex15-7.md: -------------------------------------------------------------------------------- 1 | # 15.7 Setting up Cloud Firestore 2 | 3 | 4 | # Example: Firestore image 5 | 6 | *link to image needed (no fig no in document)* 7 | 8 | # Example: Initilization code 9 | 10 | ```dart 11 | ``` 12 | 13 | # Example: Collection images 14 | 15 | 16 | *link to image needed (no fig no in document)* 17 | 18 | 19 | -------------------------------------------------------------------------------- /ch17/ex17-1.md: -------------------------------------------------------------------------------- 1 | # 17.1 Adding the Flame package to Flutter 2 | 3 | 4 | # Example: Adding flame to Flutter 5 | 6 | ```console 7 | flutter pub add flame 8 | 9 | ``` 10 | 11 | # Example: Pubspec.yaml 12 | 13 | ```dart 14 | dependencies: 15 | flutter: 16 | sdk: flutter 17 | flame: ^1.2.0 18 | 19 | ``` 20 | 21 | # Example: Imports 22 | 23 | ```dart 24 | import 'package:flame/game.dart'; 25 | 26 | ``` 27 | 28 | 29 | -------------------------------------------------------------------------------- /ch15/ex15-3.md: -------------------------------------------------------------------------------- 1 | # 15.3 Initializine Firebase on the Client 2 | 3 | # Example: Firebase tools 4 | 5 | ```console 6 | npm install - -location=global firebase firebase-tools 7 | 8 | ``` 9 | 10 | # Example: Login 11 | 12 | ```console 13 | firebase login [--no-localhost] 14 | 15 | ``` 16 | 17 | # Example: Project list 18 | 19 | ```console 20 | firebase projects:list 21 | 22 | ``` 23 | 24 | # Example: Init 25 | 26 | ```console 27 | firebase init 28 | 29 | ``` 30 | 31 | 32 | -------------------------------------------------------------------------------- /ch15/ex15-8.md: -------------------------------------------------------------------------------- 1 | # 15.8 Writing data to Cloud Firestore 2 | 3 | 4 | # Example: Add packages 5 | 6 | ```console 7 | flutter pub add firebase_core 8 | flutter pub add cloud_firestore 9 | 10 | ``` 11 | 12 | # Example: Firebase essentials II 13 | 14 | [https://docs.google.com/document/d/1EWne4Bd0ETHkEQgWuvrVZeQXEgDLXMY69iHw138PYNk/edit?resourcekey=0-8K3f5lNqMJyX2L9aQucPag#](Firebase & Flutter) 15 | 16 | 17 | # Example: Write image 18 | 19 | *link needed for write image no fig gib=ven in document* 20 | 21 | 22 | -------------------------------------------------------------------------------- /ch01/ex-double.md: -------------------------------------------------------------------------------- 1 | # 1.3 Declaring a Double variable 2 | 3 | ## Example Code: 4 | The data type of myVariable is double. 5 | This means that myVariable can store any floating-point number. 6 | Floating-point numbers are numbers that have a decimal point and can be represented in scientific notation. 7 | 8 | ```dart 9 | 10 | void main() { 11 | double myVariable = 2.99; 12 | 13 | print(myVariable); 14 | } 15 | ``` 16 | 17 | ## Example Output: 18 | 19 | The result of the print statement is shown below: 20 | 21 | ```dart 22 | 2.99 23 | ``` 24 | -------------------------------------------------------------------------------- /ch01/ex-integer.md: -------------------------------------------------------------------------------- 1 | # 1.2 Declaring an Integer variable 2 | 3 | ## Example Code: 4 | 5 | The print() function print the value of myVariable, which is 35. 6 | 7 | The data type of myVariable is int. 8 | This means that myVariable can store any whole number. 9 | Whole numbers are numbers that do not have a decimal point. 10 | 11 | ```dart 12 | void main() { 13 | int myVariable = 35; 14 | 15 | print(myVariable); 16 | } 17 | ``` 18 | 19 | ## Example Output: 20 | 21 | The result of the application code is shown below: 22 | 23 | ```dart 24 | 35 25 | ``` 26 | -------------------------------------------------------------------------------- /ch15/ex15-4.md: -------------------------------------------------------------------------------- 1 | # 15.4 Firebase/Flutter Client Integration 2 | 3 | # Example: Flutterfire init 4 | 5 | ```console 6 | dart pub global activate flutterfire_cli 7 | 8 | ``` 9 | 10 | # Example: Project ID 11 | 12 | ```console 13 | flutterfire configure --project=[PROJECT_ID] 14 | 15 | ``` 16 | 17 | # Example: Initialize Firebase 18 | 19 | ```dart 20 | import 'package:firebase_core/firebase_core.dart'; 21 | import 'firebase_options.dart'; 22 | 23 | // ... 24 | WidgetsFlutterBinding.ensureInitialized(); 25 | await Firebase.initializeApp( 26 | options: DefaultFirebaseOptions.currentPlatform, 27 | ); 28 | ``` 29 | 30 | 31 | -------------------------------------------------------------------------------- /ch01/ex-bool.md: -------------------------------------------------------------------------------- 1 | # 1.4 Declaring a Bool variable 2 | 3 | ## Example Code: 4 | 5 | * The first line declares a variable called myVariable and assigns it the type bool. 6 | * The second line assigns the value true to the variable myVariable. 7 | * The third line calls the print() function and passes the value of myVariable as an argument. 8 | * The print() function will then print the value of myVariable to the console. 9 | 10 | ```dart 11 | void main() { 12 | bool myVariable = true; 13 | 14 | print(myVariable); 15 | } 16 | ``` 17 | 18 | ## Example Output: 19 | 20 | The result of the print statement is shown below: 21 | ```dart 22 | true 23 | ``` 24 | 25 | -------------------------------------------------------------------------------- /ch03/ex3-1.md: -------------------------------------------------------------------------------- 1 | # 3.1 Declaring Functions 2 | 3 | ## Example Code: 4 | 5 | The getCurrentDateTime() function gets the current date and time in London and prints it to the console. 6 | 7 | The DateTime.now() method returns the current date and time in the local time zone. 8 | In this case, the local time zone is London. 9 | 10 | The print() function prints the value of the timeLondon variable to the console. 11 | 12 | ```dart 13 | void main() { 14 | getCurrentDateTime(); 15 | } 16 | 17 | void getCurrentDateTime() { 18 | var timeLondon = DateTime.now(); 19 | print('London: $timeLondon'); 20 | } 21 | ``` 22 | 23 | ## Example Output: 24 | ```dart 25 | London: 2023-08-31 09:42:34.310135 26 | ``` 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://www.dartlang.org/guides/libraries/private-files 2 | 3 | # Files and directories created by pub 4 | .dart_tool/ 5 | .packages 6 | build/ 7 | # If you're building an application, you may want to check-in your pubspec.lock 8 | pubspec.lock 9 | 10 | # Directory created by dartdoc 11 | # If you don't generate documentation locally you can remove this line. 12 | doc/api/ 13 | 14 | # Avoid committing generated Javascript files: 15 | *.dart.js 16 | *.info.json # Produced by the --dump-info flag. 17 | *.js # When generated by dart2js. Don't specify *.js if your 18 | # project includes source files written in JavaScript. 19 | *.js_ 20 | *.js.deps 21 | *.js.map 22 | -------------------------------------------------------------------------------- /ch01/ex-dart.md: -------------------------------------------------------------------------------- 1 | # 1.1 Running a Dart application 2 | 3 | ## Example Code: 4 | 5 | The print() function is used to print text to the console. 6 | In this case, the text that is printed is "Hello, Dart World!". 7 | 8 | The print() function is a built-in function in Dart. 9 | It can be used to print any type of data, including strings, numbers, and objects. 10 | 11 | Use Dart to print a message on screen. 12 | 13 | ```dart 14 | void main() { 15 | print('Hello, Dart World!'); 16 | } 17 | ``` 18 | 19 | To run a dart application from the command line: 20 | 21 | ```dart 22 | dart main.dart 23 | ``` 24 | 25 | ## Example Output: 26 | 27 | The result of the print statement is shown below: 28 | 29 | ```dart 30 | Hello, Dart World! 31 | ``` 32 | -------------------------------------------------------------------------------- /ch01/ex-string.md: -------------------------------------------------------------------------------- 1 | # 1.5 Declaring a String variable 2 | 3 | ## Example Code: 4 | 5 | The variable myVariable is assigned the string literal "I am a string". 6 | The variable myVariable2 is assigned a multiline string literal, which is enclosed in three double quotes. 7 | The print() function prints the value of the variable to the console. 8 | 9 | ```dart 10 | void main() { 11 | String myVariable = "I am a string"; 12 | 13 | String myVariable2 = """ 14 | I am a multiline 15 | string 16 | """; 17 | 18 | print(myVariable); 19 | print(myVariable2); 20 | } 21 | ``` 22 | 23 | ## Example Output: 24 | 25 | The result of the print statement is shown below: 26 | 27 | ```dart 28 | I am a string 29 | I am a multiline 30 | string 31 | ``` 32 | -------------------------------------------------------------------------------- /ch04/ex4-1.md: -------------------------------------------------------------------------------- 1 | # 4.1 Creating Lists of Data 2 | 3 | ## Example Code: 4 | The main() function first creates a list of months. 5 | The list contains the months January, February, and March. 6 | The function then calls the forEach() method on the list. 7 | The forEach() method iterates over the elements of the list and calls the specified function on each element. 8 | In this case, the specified function is the print() function. 9 | The print() function prints the value of the current element to the console. 10 | 11 | ```dart 12 | void main() { 13 | List listMonths = ['January', 'February', 'March']; 14 | listMonths.forEach(print); 15 | } 16 | ``` 17 | 18 | ## Example Output: 19 | ```dart 20 | January 21 | February 22 | March 23 | ``` 24 | -------------------------------------------------------------------------------- /ch06/ex6-1.md: -------------------------------------------------------------------------------- 1 | # 6.1 Adding the Dart Test Package to Your Application 2 | 3 | ## Example Code: 4 | 5 | The command dart pub add test --dev adds the test package to your project as a development dependency. 6 | The test package provides a testing framework for Dart. 7 | 8 | ```bash 9 | dart pub add test --dev 10 | ``` 11 | 12 | To use the test package, you need to import it into your code: 13 | 14 | ```dart 15 | import 'package:test/test.dart'; 16 | ``` 17 | 18 | You can then write tests using the test() function: 19 | 20 | ```dart 21 | void main() { 22 | test('This is a test', () { 23 | // Your test code goes here. 24 | }); 25 | } 26 | ``` 27 | 28 | To use the test package, please see the documentation: [test package](https://pub.dev/packages/test). 29 | -------------------------------------------------------------------------------- /ch13/ex13-4.md: -------------------------------------------------------------------------------- 1 | # 13.4 Remote Data Management JSON 2 | 3 | # Example: Imports 4 | 5 | ```dart 6 | import 'package:http/http.dart' as http; 7 | import 'dart:async' show Future; 8 | import 'dart:convert'; 9 | 10 | ``` 11 | 12 | # Example: Status code 13 | 14 | ```dart 15 | import 'package:http/http.dart' as http; 16 | import 'dart:async' show Future; 17 | import 'dart:convert'; 18 | 19 | Future _loadRemoteData() async { 20 | final response = await (http.get(Uri.parse('https://oreil.ly/ndCPN'))); 21 | if (response.statusCode == 200) { 22 | print('response statusCode is 200'); 23 | return response.body; 24 | } else { 25 | print('Http Error: ${response.statusCode}!'); 26 | throw Exception('Invalid data source.'); 27 | } 28 | } 29 | ``` 30 | -------------------------------------------------------------------------------- /ch04/ex4-5.md: -------------------------------------------------------------------------------- 1 | # 4.5 Printing Map Data Structure Content 2 | 3 | ## Example Code: 4 | 5 | The main() function first creates a map. 6 | The map mapMonths contains the months January, February, and March. 7 | The function then prints the value of the month January using the mapMonths[0] syntax. 8 | The mapMonths[0] syntax gets the value of the key 0 from the map mapMonths. 9 | The function then prints the entire map mapMonths to the console. 10 | 11 | ```dart 12 | void main() { 13 | Map mapMonths = {0: 'January', 1: 'February', 2: 'March'}; 14 | print ("Month: ${mapMonths[0]}"); 15 | print ("Map: $mapMonths"); 16 | } 17 | ``` 18 | 19 | ## Example Output: 20 | 21 | ```dart 22 | Month: January 23 | Map: {0: January, 1: February, 2: March} 24 | ``` 25 | -------------------------------------------------------------------------------- /ch15/ex15-5.md: -------------------------------------------------------------------------------- 1 | # 15.5 Configuring Firebase Emulators for local development 2 | 3 | # Example: Login Localhost 4 | 5 | ```console 6 | firebase login [--no-localhost] 7 | 8 | ``` 9 | 10 | # Example: Firebase init 11 | 12 | ```console 13 | firebase init 14 | 15 | ``` 16 | 17 | # Example: Emulator 18 | 19 | ```dart 20 | /// Requires that a Firestore emulator is running locally. 21 | /// See https://firebase.flutter.dev/docs/firestore/usage#emulator-usage 22 | bool shouldUseFirestoreEmulator = true; 23 | 24 | await Firebase.initializeApp(options: DefaultFirebaseConfig.platformOptions); 25 | 26 | if (shouldUseFirestoreEmulator) { 27 | FirebaseFirestore.instance.useFirestoreEmulator('localhost', 8080); 28 | } 29 | runApp(FirestoreExampleApp()); 30 | ``` 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /ch14/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Flutter Full stack examples 3 | 4 | Developing Full-Stack Applications for the Cloud 5 | 6 | ![Flutter & Dart Cookbook](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/images/flutter-dart-cookbook-sml.png "Flutter & Dart Cookbook") 7 | 8 | Companion repository for O'Reilly Flutter & Dart Full Stack Cookbook 9 | 10 | ## Testing the Flutter user interface 11 | 12 | - [x] [14.1 Testing widgets in Flutter](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch14/ex14-1.md) 13 | - [x] [14.2 Performing integration testing with Flutter Driver](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch14/ex14-2.md) 14 | - [x] [14.3 Testing Android/iOS device compatibility ](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch14/ex14-3.md) 15 | -------------------------------------------------------------------------------- /ch16/ex16-6.md: -------------------------------------------------------------------------------- 1 | # 16.6 Backend HTTP Server 2 | ## Example: HTTP Server 3 | ```dart 4 | import 'dart:convert'; 5 | import 'dart:io'; 6 | 7 | const port = 8080; 8 | 9 | Future main(List arguments) async { 10 | final httpServer = await createHTTPServer(); 11 | await httpRequest(httpServer); 12 | } 13 | 14 | Future createHTTPServer() async { 15 | final intAddress = InternetAddress.anyIPv4; 16 | return await HttpServer.bind(intAddress, port); 17 | } 18 | 19 | Future httpRequest(HttpServer server) async { 20 | await for (HttpRequest request in server) { 21 | if (request.method == 'GET'){ 22 | request.response 23 | ..write(' { "data": [ {"title": "January"}, {"title:": "February"}, {"title": "March"} ] }\n') 24 | ..close(); 25 | } 26 | } 27 | } 28 | ``` 29 | -------------------------------------------------------------------------------- /ch01/ex-final.md: -------------------------------------------------------------------------------- 1 | # 1.8 Using Final 2 | 3 | ## Example Code: 4 | 5 | Use final when the variable value is defined at runtime. 6 | 7 | The code first creates a variable called today and assigns it the value of the current date and time. 8 | Then, it calls the weekday() method on the today variable and passes the result to the print() function. 9 | The weekday() method returns an integer representing the day of the week, 1 representing Monday, 2 representing Tuesday and so on. 10 | 11 | ```dart 12 | void main() { 13 | final today = DateTime.now(); 14 | 15 | print('Today is day ${today.weekday}'); 16 | } 17 | ``` 18 | 19 | ## Example Output: 20 | 21 | The result of the print statement is shown below: 22 | 23 | ```dart 24 | Today is day 2 25 | ``` 26 | 27 | Note: As the today variable is determined at runtime, a different value may be shown. 28 | -------------------------------------------------------------------------------- /ch07/ex7-2.md: -------------------------------------------------------------------------------- 1 | # 7.2 Creating a Boilerplate Flutter Project 2 | 3 | # Example Code: Flutter create 4 | 5 | ```bash 6 | flutter create my_awesome_app 7 | 8 | ``` 9 | 10 | 11 | # Example Code: Flutter create module 12 | 13 | ```bash 14 | flutter create -t module my_awesome_module 15 | 16 | ``` 17 | 18 | 19 | # Example Code: Flutter create package 20 | 21 | ```bash 22 | flutter create -t package my_awesome_package 23 | 24 | ``` 25 | 26 | 27 | # Example Code: Flutter create plugin 28 | 29 | ```bash 30 | flutter create -t plugin my_awesome_plugin --platforms web --platform android 31 | 32 | ``` 33 | 34 | # Example Code: skeleton 35 | 36 | ```bash 37 | flutter create -t skeleton my_awesome_skeleton 38 | ``` 39 | 40 | # Example Code: Sample code 41 | 42 | ```bash 43 | flutter create -s widgets.GestureDetector.1 my_awesome_sample 44 | 45 | ``` 46 | -------------------------------------------------------------------------------- /ch04/ex4-2.md: -------------------------------------------------------------------------------- 1 | # 4.2 Amending a List of Data 2 | 3 | ## Example Code: 4 | 5 | The main() function first creates a list of months. 6 | The list contains the months January, February, and March. 7 | The function then calls the add() method on the list to add the month April to the list. 8 | The function then calls the forEach() method on the list. 9 | The forEach() method iterates over the elements of the list and calls the specified function on each element. 10 | In this case, the specified function is the print() function. The print() function prints the value of the current element to the console. 11 | 12 | ```dart 13 | void main() { 14 | List listMonths = ['January', 'February', 'March']; 15 | listMonths.add('April'); 16 | listMonths.forEach(print); 17 | } 18 | ``` 19 | 20 | ## Example Output: 21 | ```dart 22 | January 23 | February 24 | March 25 | April 26 | ``` 27 | -------------------------------------------------------------------------------- /ch01/ex-null.md: -------------------------------------------------------------------------------- 1 | # 1.9 Working with Null 2 | 3 | 4 | ## Example Code 5 | 6 | The variable myVariable is declared as an nullable integer. 7 | Nullable integers can store either an integer value or the value null. 8 | 9 | When myVariable is declared, it is not assigned a value, so it is set to the value null. 10 | The first print() statement will then print the value of myVariable, which is null. 11 | 12 | The second print() statement assigns the value 10 to myVariable. 13 | The second print() statement will then print the value of myVariable, which is now 10. 14 | 15 | ```dart 16 | void main(){ 17 | int ?myVariable; 18 | print ('ten: $myVariable'); 19 | 20 | myVariable = 10; 21 | print ('ten: $myVariable'); 22 | } 23 | ``` 24 | 25 | ## Example Output: 26 | 27 | The result of the print statement is shown below: 28 | 29 | ```dart 30 | ten: null 31 | ten: 10 32 | ``` 33 | 34 | -------------------------------------------------------------------------------- /ch05/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Flutter Full stack examples 3 | 4 | Developing Full-Stack Applications for the Cloud 5 | 6 | ![Flutter & Dart Cookbook](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/images/flutter-dart-cookbook-sml.png "Flutter & Dart Cookbook") 7 | 8 | Companion repository for O'Reilly Flutter & Dart Full Stack Cookbook 9 | 10 | ## Leveraging classes 11 | 12 | - [x] [5.1 Creating a class](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch05/ex5-1.md) 13 | - [x] [5.2 Initializing a class using a constructor](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch05/ex5-2.md) 14 | - [x] [5.3 Adding class Inheritance](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch05/ex5-3.md) 15 | - [x] [5.4 Adding a Class Interface](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch05/ex5-4.md) 16 | - [x] [5.5 Adding a Class Mixin](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch05/ex5-5.md) 17 | -------------------------------------------------------------------------------- /ch06/ex6-0.md: -------------------------------------------------------------------------------- 1 | # Chapter 6 Creating A Sample Test Application 2 | 3 | ## Example Code: 4 | 5 | The code provided defines a class called Travel. 6 | The Travel class has a property called distance, which is of type double. 7 | The Travel class also has two methods: DistanceToMiles() and DistanceToKilometers(). 8 | 9 | The DistanceToMiles() method returns the distance in miles. 10 | The DistanceToKilometers() method returns the distance in kilometers. 11 | 12 | The convertToMiles and convertToKilometers constants are used to convert between miles and kilometers. 13 | 14 | ```dart 15 | const convertToKiloMeters = 1.60934; 16 | const convertToMiles = 0.62137119; 17 | 18 | class Travel { 19 | late double distance; 20 | 21 | Travel(double newDistance) { 22 | distance = newDistance; 23 | } 24 | 25 | double DistanceToMiles() { 26 | return distance * convertToMiles; 27 | } 28 | 29 | double DistanceToKilometers() { 30 | return distance * convertToKiloMeters; 31 | } 32 | } 33 | 34 | ``` 35 | 36 | -------------------------------------------------------------------------------- /ch13/ex13-5.md: -------------------------------------------------------------------------------- 1 | # 13.5 Automating JSON to Dart classes 2 | 3 | 4 | # Example 5 | 6 | ```dart 7 | class Month { 8 | List data; 9 | 10 | Month({this.data}); 11 | 12 | Month.fromJson(Map json) { 13 | if (json['data'] != null) { 14 | data = new List(); 15 | json['data'].forEach((v) { 16 | data.add(new Data.fromJson(v)); 17 | }); 18 | } 19 | } 20 | 21 | Map toJson() { 22 | final Map data = new Map(); 23 | if (this.data != null) { 24 | data['data'] = this.data.map((v) => v.toJson()).toList(); 25 | } 26 | return data; 27 | } 28 | } 29 | 30 | class Data { 31 | String title; 32 | 33 | Data({this.title}); 34 | 35 | Data.fromJson(Map json) { 36 | title = json['title']; 37 | } 38 | 39 | Map toJson() { 40 | final Map data = new Map(); 41 | data['title'] = this.title; 42 | return data; 43 | } 44 | } 45 | 46 | ``` 47 | -------------------------------------------------------------------------------- /ch13/ex13-7.md: -------------------------------------------------------------------------------- 1 | # 13.7 Generating Dart Classes from JSON 2 | 3 | ## Example 4 | 5 | ```dart 6 | class Month { 7 | List? data; 8 | 9 | Month({this.data}); 10 | 11 | Month.fromJson(Map json) { 12 | if (json['data'] != null) { 13 | data = []; 14 | json['data'].forEach((v) { 15 | data!.add(new Data.fromJson(v)); 16 | }); 17 | } 18 | } 19 | Map toJson() { 20 | final Map data = new Map(); 21 | if (this.data != null) { 22 | data['data'] = this.data!.map((v) => v.toJson()).toList(); 23 | } 24 | return data; 25 | 26 | class Data { 27 | String? title; 28 | 29 | Data({this.title}); 30 | 31 | Data.fromJson(Map json) { 32 | title = json['title']; 33 | } 34 | 35 | Map toJson() { 36 | final Map data = new Map(); 37 | data['title'] = this.title; 38 | return data; 39 | } 40 | } 41 | ``` 42 | -------------------------------------------------------------------------------- /ch02/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Flutter Full stack examples 3 | 4 | Developing Full-Stack Applications for the Cloud 5 | 6 | ![Flutter & Dart Cookbook](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/images/flutter-dart-cookbook-sml.png "Flutter & Dart Cookbook") 7 | 8 | Companion repository for O'Reilly Flutter & Dart Full Stack Cookbook 9 | 10 | ## Exploring control flow 11 | 12 | - [x] [2.1 Using an If statement](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch02/ex-if.md) 13 | - [x] [2.2 Using While/Do while](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch02/ex-while.md) 14 | - [x] [2.3 Using a For statement](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch02/ex-for.md) 15 | - [x] [2.4 Using a Switch statement](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch02/ex-switch.md) 16 | - [x] [2.5 Using an Enum](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch02/ex-enum.md) 17 | - [x] [2.6 Handling exceptions](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch02/ex-exception.md) 18 | -------------------------------------------------------------------------------- /ch02/ex-if.md: -------------------------------------------------------------------------------- 1 | # 2.1 Using an If statement 2 | 3 | 4 | ## Example Code: 5 | 6 | The variable isFootball is assigned the value true. 7 | The if statement checks if the value of isFootball is true. 8 | If it is, the body of the if statement is executed. 9 | The body of the if statement prints the message "Go Football!" to the console. 10 | If the value of isFootball is not true, the body of the if statement is not executed, and the else statement is executed. 11 | The else statement prints the message "Go Sports!" to the console. 12 | 13 | The if statement is a control flow statement that allows you to execute a block of code if a condition is true. 14 | The else statement allows you to execute a different block of code if the condition is false. 15 | 16 | ```dart 17 | void main() { 18 | bool isFootball = true; 19 | 20 | if (isFootball) { 21 | print('Go Football!'); 22 | } else { 23 | print('Go Sports!'); 24 | } 25 | } 26 | ``` 27 | 28 | ## Example Output: 29 | 30 | The result of the print statement is shown below: 31 | ```dart 32 | Go Football! 33 | ``` 34 | 35 | -------------------------------------------------------------------------------- /ch09/ex9-5.md: -------------------------------------------------------------------------------- 1 | # 9.5 Using a Center widget 2 | 3 | # Example 4 | 5 | ```dart 6 | import 'package:flutter/material.dart'; 7 | 8 | void main() => runApp(const MyApp()); 9 | 10 | class MyApp extends StatelessWidget { 11 | const MyApp({Key? key}) : super(key: key); 12 | static const String _title = 'Center Widget Demo'; 13 | @override 14 | Widget build(BuildContext context) { 15 | return const MaterialApp( 16 | title: _title, 17 | home: MyStatelessWidget(), 18 | ); 19 | } 20 | } 21 | 22 | class MyStatelessWidget extends StatelessWidget { 23 | const MyStatelessWidget({Key? key}) : super(key: key); 24 | @override 25 | Widget build(BuildContext context) { 26 | return Scaffold( 27 | appBar: AppBar(title: const Text('Center Example')), 28 | body: _buildCenterWidget(), 29 | ); 30 | } 31 | 32 | Widget _buildCenterWidget() { 33 | return const Center( 34 | child: Text( 35 | "Top Five Spoken Languages - 2022", 36 | style: TextStyle(fontSize: 30, color: Colors.grey), 37 | ), 38 | ); 39 | } 40 | } 41 | ``` 42 | -------------------------------------------------------------------------------- /ch12/ex12-5.md: -------------------------------------------------------------------------------- 1 | # 12.5 Using Keys to pass information 2 | 3 | # Example 4 | 5 | ```dart 6 | 7 | import 'package:flutter/material.dart'; 8 | 9 | void main() { 10 | runApp(const MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | const MyApp({Key? key}) : super(key: key); 15 | @override 16 | Widget build(BuildContext context) { 17 | const paramTitle = 'My Title'; 18 | const paramName = 'My Name'; 19 | return MaterialApp( 20 | title: paramTitle, 21 | home: Scaffold( 22 | appBar: AppBar( 23 | title: const Text(paramTitle), 24 | ), 25 | body: const MyTextWidget(name: paramName, title: paramTitle), 26 | ), 27 | ); 28 | } 29 | } 30 | 31 | class MyTextWidget extends StatelessWidget { 32 | final String title; 33 | final String name; 34 | const MyTextWidget({Key? key, required this.title, required this.name}) 35 | : super(key: key); 36 | @override 37 | Widget build(BuildContext context) { 38 | return Center( 39 | child: Text("$title $name"), 40 | ); 41 | } 42 | } 43 | 44 | ``` 45 | -------------------------------------------------------------------------------- /ch03/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Flutter Full stack examples 3 | 4 | Developing Full-Stack Applications for the Cloud 5 | 6 | ![Flutter & Dart Cookbook](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/images/flutter-dart-cookbook-sml.png "Flutter & Dart Cookbook") 7 | 8 | Companion repository for O'Reilly Flutter & Dart Full Stack Cookbook 9 | 10 | ## Implementing Functions 11 | 12 | - [x] [3.1 Declaring functions](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch03/ex3-1.md) 13 | - [x] [3.2 Adding Parameters to functions](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch03/ex3-2.md) 14 | - [x] [3.3 Using Optional parameters](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch03/ex3-3.md) 15 | - [x] [3.4 Returning values from functions](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch03/ex3-4.md) 16 | - [x] [3.5 Declaring anonymous functions](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch03/ex3-5.md) 17 | - [x] [3.6 Adding a Functional Delay Using a Future](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch03/ex3-6.md) 18 | -------------------------------------------------------------------------------- /ch07/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Flutter Full stack examples 3 | 4 | Developing Full-Stack Applications for the Cloud 5 | 6 | ![Flutter & Dart Cookbook](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/images/flutter-dart-cookbook-sml.png "Flutter & Dart Cookbook") 7 | 8 | Companion repository for O'Reilly Flutter & Dart Full Stack Cookbook 9 | 10 | ## Introducing the Flutter framework 11 | 12 | - [x] [7.1 Mocking an interface](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch07/ex7-1.md) 13 | - [x] [7.2 Creating a Flutter project](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch07/ex7-2.md) 14 | - [x] [7.3 Working with a stateful widget](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch07/ex7-3.md) 15 | - [x] [7.4 Working with a stateless widget](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch07/ex7-4.md) 16 | - [x] [7.5 Refactoring widgets](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch07/ex7-5.md) 17 | - [x] [7.6 Removing the Flutter debug banner](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch07/ex7-6.md) 18 | -------------------------------------------------------------------------------- /ch11/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Flutter Full stack examples 3 | 4 | Developing Full-Stack Applications for the Cloud 5 | 6 | ![Flutter & Dart Cookbook](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/images/flutter-dart-cookbook-sml.png "Flutter & Dart Cookbook") 7 | 8 | Companion repository for O'Reilly Flutter & Dart Full Stack Cookbook 9 | 10 | ## Organising on screen data 11 | 12 | - [x] [11.1 Implementing a vertical list](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch11/ex11-1.md) 13 | - [x] [11.2 Implementing a horizontal list](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch11/ex11-2.md) 14 | - [x] [11.3 Adding a SliverAppBar](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch11/ex11-3.md) 15 | - [x] [11.4 Adding a grid of items](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch11/ex11-4.md) 16 | - [x] [11.5 Adding a SnackBar (pop up notification](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch11/ex11-5.md) 17 | - [x] [11.6 Adding a SliverList](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch11/ex11-6.md) 18 | -------------------------------------------------------------------------------- /ch06/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Flutter Full stack examples 3 | 4 | Developing Full-Stack Applications for the Cloud 5 | 6 | ![Flutter & Dart Cookbook](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/images/flutter-dart-cookbook-sml.png "Flutter & Dart Cookbook") 7 | 8 | Companion repository for O'Reilly Flutter & Dart Full Stack Cookbook 9 | 10 | ## Using Dart test cases 11 | 12 | - [x] [6.0 Using Dart test cases](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch06/ex6-0.md) 13 | - [x] [6.1 Adding the Dart test package](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch06/ex6-1.md) 14 | - [x] [6.2 Creating a Sample Test Application](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch06/ex6-2.md) 15 | - [x] [6.3 Running Unit Tests in Your Dart Application](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch06/ex6-3.md) 16 | - [x] [6.4 Grouping Multiple Unit Tests](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch06/ex6-4.md) 17 | - [x] [6.5 Adding Mock Data for Testing](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch06/ex6-5.md) 18 | -------------------------------------------------------------------------------- /ch12/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Flutter Full stack examples 3 | 4 | Developing Full-Stack Applications for the Cloud 5 | 6 | ![Flutter & Dart Cookbook](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/images/flutter-dart-cookbook-sml.png "Flutter & Dart Cookbook") 7 | 8 | Companion repository for O'Reilly Flutter & Dart Full Stack Cookbook 9 | 10 | ## Flutter page navigation 11 | 12 | - [x] [12.1 Adding page navigation with routes ](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch12/ex12-1.md) 13 | - [x] [12.2 Implementing a navigational drawer](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch12/ex12-2.md) 14 | - [x] [12.3 Working with tabs](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch12/ex12-3.md) 15 | - [x] [12.4 Adding bottom navigation ](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch12/ex12-4.md) 16 | - [x] [12.5 Using keys to pass information](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch12/ex12-5.md) 17 | - [x] [12.6 Adding page navigation with routes ](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch12/ex12-6.md) 18 | -------------------------------------------------------------------------------- /ch09/ex9-4.md: -------------------------------------------------------------------------------- 1 | # 9.4 Building with a Container 2 | 3 | # Example 4 | 5 | ```dart 6 | import 'package:flutter/material.dart'; 7 | 8 | void main() { 9 | runApp(const MyApp()); 10 | } 11 | 12 | class MyApp extends StatelessWidget { 13 | const MyApp({Key? key}) : super(key: key); 14 | @override 15 | Widget build(BuildContext context) { 16 | const title = 'Container Widget Demo'; 17 | return MaterialApp( 18 | title: title, 19 | home: Scaffold( 20 | appBar: AppBar( 21 | title: const Text(title), 22 | ), 23 | body: const MyContainerWidget(), 24 | ), 25 | ); 26 | } 27 | } 28 | 29 | class MyContainerWidget extends StatelessWidget { 30 | const MyContainerWidget({Key? key}) : super(key: key); 31 | @override 32 | Widget build(BuildContext context) { 33 | return Container( 34 | alignment: Alignment.center, 35 | height: 200, 36 | width: 200, 37 | color: Colors.red[300], 38 | child: Container( 39 | height: 100, 40 | width: 100, 41 | color: Colors.yellow, 42 | ), 43 | ); 44 | } 45 | } 46 | 47 | ``` 48 | -------------------------------------------------------------------------------- /ch10/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Flutter Full stack examples 3 | 4 | Developing Full-Stack Applications for the Cloud 5 | 6 | ![Flutter & Dart Cookbook](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/images/flutter-dart-cookbook-sml.png "Flutter & Dart Cookbook") 7 | 8 | Companion repository for O'Reilly Flutter & Dart Full Stack Cookbook 9 | 10 | ## Developing user interfaces 11 | 12 | - [x] [10.1 Incorporating rich text](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch10/ex10-1.md) 13 | - [x] [10.2 Incororating the Google Fonts package](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch10/ex10-2.md) 14 | - [x] [10.3 Identifying the host platform](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch10/ex10-3.md) 15 | - [x] [10.4 Using a Placeholder widget](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch10/ex10-4.md) 16 | - [x] [10.5 Using a Layout builder](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch10/ex10-5.md) 17 | - [x] [10.6 Getting screen dimensions with Media query](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch10/ex10-6.md) 18 | -------------------------------------------------------------------------------- /ch16/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Flutter Full stack examples 3 | 4 | Developing Full-Stack Applications for the Cloud 5 | 6 | ![Flutter & Dart Cookbook](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/images/flutter-dart-cookbook-sml.png "Flutter & Dart Cookbook") 7 | 8 | Companion repository for O'Reilly Flutter & Dart Full Stack Cookbook 9 | 10 | ## Introducing Cloud services 11 | 12 | - [x] [16.1 Introducing cloud providers](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch16/ex16-1.md) 13 | - [x] [16.2 Working with identity and access management](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch16/ex16-2.md) 14 | - [x] [16.3 Using cloud storage to host and API](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch16/ex16-3.md) 15 | - [x] [16.4 Using a spreadsheet as a backend](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch16/ex16-4.md) 16 | - [x] [16.5 Developing with serverless (cloud run)](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch16/ex16-5.md) 17 | - [x] [16.6 Backend HTTP Server](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch16/ex16-6.md) 18 | -------------------------------------------------------------------------------- /ch06/ex6-2.md: -------------------------------------------------------------------------------- 1 | # 6.2 Creating a Sample Test Application 2 | 3 | ## Example Code: 4 | 5 | The code provided defines a class called Travel. 6 | The Travel class has two constants: 7 | * convertToKilometers 8 | * convertToMiles. 9 | 10 | The constants are used to convert between kilometers and miles. 11 | 12 | The Travel class also has a constructor that takes a distance in kilometers as an argument. 13 | The constructor sets the distance property to the value of the argument. 14 | 15 | The Travel class has two methods: 16 | * distanceToMiles() 17 | * distanceToKilometers(). 18 | 19 | The distanceToMiles() method returns the distance in miles. 20 | The distanceToKilometers() method returns the distance in kilometers. 21 | 22 | ```dart 23 | const convertToKilometers = 1.60934; 24 | const convertToMiles = 0.62137119; 25 | 26 | class Travel { 27 | late double distance; 28 | Travel(double newDistance) { 29 | distance = newDistance; 30 | } 31 | 32 | double distanceToMiles() { 33 | return distance * convertToMiles; 34 | } 35 | 36 | double distanceToKilometers() { 37 | return distance * convertToKilometers; 38 | } 39 | } 40 | ``` 41 | -------------------------------------------------------------------------------- /ch04/ex4-6.md: -------------------------------------------------------------------------------- 1 | # 4.6 Validating That Content Exists in a Map 2 | 3 | # Example 4 | 5 | The main() function first creates a map. 6 | The map mapMonths contains the months January, February, and March. 7 | The function then calls the containsKey() method on the mapMonths map. 8 | The containsKey() method returns true if the map contains the specified key and false if it does not. 9 | 10 | The first if statement checks if the map contains the key 0. 11 | The key 0 is present in the map, so the if statement prints the message "Test 1: Key exists" to the console. 12 | 13 | The second if statement checks if the map contains the key 2. 14 | The key 2 is also present in the map, so the if statement prints the message "Test 2: Key exists" to the console. 15 | 16 | 17 | ```dart 18 | void main() { 19 | Map mapMonths = {0: 'January', 1: 'February', 2: 'March'}; 20 | if (mapMonths[0]!=null) { 21 | print ('Test 1: Key exists'); 22 | } 23 | 24 | if (mapMonths.containsKey(2)) { 25 | print('Test 2: Key exists'); 26 | } 27 | } 28 | ``` 29 | 30 | 31 | ## Example Output: 32 | 33 | ```dart 34 | Test 1: Key exists 35 | Test 2: Key exists 36 | ``` 37 | -------------------------------------------------------------------------------- /ch13/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Flutter Full stack examples 3 | 4 | Developing Full-Stack Applications for the Cloud 5 | 6 | ![Flutter & Dart Cookbook](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/images/flutter-dart-cookbook-sml.png "Flutter & Dart Cookbook") 7 | 8 | Companion repository for O'Reilly Flutter & Dart Full Stack Cookbook 9 | 10 | ## Handling data assets 11 | 12 | - [x] [13.1 Refactoring data](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch13/ex13-1.md) 13 | - [x] [13.2 Local data management](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch13/ex13-2.md) 14 | - [x] [13.3 Asset folder management](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch13/ex13-3.md) 15 | - [x] [13.4 Remote data management JSON](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch13/ex13-4.md) 16 | - [x] [13.5 Automating JSON to Dart classes](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch13/ex13-5.md) 17 | - [x] [13.6 Using JSON serialization](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch13/ex13-6.md) 18 | - [x] [13.7 Generating Dart Classes from JSON](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch13/ex13-7.md) 19 | -------------------------------------------------------------------------------- /ch04/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Flutter Full stack examples 3 | 4 | Developing Full-Stack Applications for the Cloud 5 | 6 | ![Flutter & Dart Cookbook](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/images/flutter-dart-cookbook-sml.png "Flutter & Dart Cookbook") 7 | 8 | Companion repository for O'Reilly Flutter & Dart Full Stack Cookbook 9 | 10 | ## Handling maps and lists 11 | 12 | - [x] [4.1 Creating Lists of Data](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch04/ex4-1.md) 13 | - [x] [4.2 Amending a List of Data](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch04/ex4-2.md) 14 | - [x] [4.3 Using lists with complex types](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch04/ex4-3.md) 15 | - [x] [4.4 Handling Map Key/Value Pairings](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch04/ex4-4.md) 16 | - [x] [4.5 Printing Map Data Structure Content](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch04/ex4-5.md) 17 | - [x] [4.6 Validating That Content exists in a Map](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch04/ex4-6.md) 18 | - [x] [4.7 Printing Complex Data Types](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch04/ex4-7.md) 19 | -------------------------------------------------------------------------------- /ch04/ex4-4.md: -------------------------------------------------------------------------------- 1 | # 4.4 Handling Map Key/Value Pairings 2 | 3 | ## Example Code: 4 | 5 | The main() function first creates two maps. 6 | The first map mapMonths contains the months January, February, and March. 7 | The second map moreMonths contains the months April and May. 8 | The function then calls the addEntries() method on the mapMonths map. 9 | The addEntries() method adds the key-value pairs of the moreMonths map to the mapMonths map. 10 | The function then calls the forEach() method on the mapMonths map. 11 | The forEach() method iterates over the key-value pairs of the map and calls the specified function on each pair. 12 | In this case, the specified function is the print() function. 13 | The print() function prints the key and value of the current pair to the console. 14 | 15 | ```dart 16 | void main() { 17 | Map mapMonths = {0: 'January', 1: 'February', 2: 'March'}; 18 | Map moreMonths = {3: 'April', 4: 'May'}; 19 | mapMonths.addEntries(moreMonths.entries); 20 | mapMonths.forEach((key, value){ 21 | print('$key: $value'); 22 | }); 23 | } 24 | ``` 25 | 26 | ## Example Output: 27 | 28 | ```dart 29 | 0: January 30 | 1: February 31 | 2: March 32 | 3: April 33 | 4: May 34 | ``` 35 | 36 | -------------------------------------------------------------------------------- /ch14/ex14-2.md: -------------------------------------------------------------------------------- 1 | # 14.2 Performing Integration Testing with Flutter Driver 2 | 3 | # Example: Basic interface 4 | 5 | ```dart 6 | import 'package:flutter/material.dart'; 7 | import 'package:flutter_driver/driver_extension.dart'; 8 | 9 | void main() { 10 | enableFlutterDriverExtension(); 11 | runApp(MyApp()); 12 | } 13 | 14 | class MyApp extends StatelessWidget { 15 | … 16 | } 17 | 18 | class MyWidget extends StatelessWidget { 19 | … 20 | } 21 | 22 | ``` 23 | 24 | # Example: Create integration test 25 | 26 | ```dart 27 | final txtUsername = find.byType(Text); 28 | final btnAddition = find.byType(FloatingActionButton); 29 | 30 | FlutterDriver driver; 31 | 32 | setUpAll(()) async { 33 | driver = await FlutterDriver.connect(); 34 | }); 35 | 36 | tearDownAll(()) async { 37 | if (driver != null) { 38 | driver.close(); 39 | } 40 | } 41 | 42 | test ('Should enter username and press button', ()async { 43 | await driver.tap(txtUsername); 44 | await driver.enterText("Martha Kent") 45 | await driver.tap(btnAddition); 46 | await driver.waitFor(find.text("Welcome")); 47 | }); 48 | 49 | ``` 50 | 51 | # Example: Initiate test 52 | 53 | ```console 54 | flutter drive –target=test_driver/main.dart 55 | 56 | ``` 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /ch13/ex13-1.md: -------------------------------------------------------------------------------- 1 | # 13.1 Refactoring Data 2 | 3 | 4 | # Example 5 | 6 | ```dart 7 | import 'package:flutter/material.dart'; 8 | 9 | void main() { 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyData { 14 | final List items = [ 15 | 'January', 16 | 'February', 17 | 'March', 18 | 'April', 19 | 'May', 20 | 'June', 21 | 'July', 22 | 'August', 23 | 'September', 24 | 'October', 25 | 'November', 26 | 'December' 27 | ]; 28 | 29 | MyData(); 30 | } 31 | 32 | class MyApp extends StatelessWidget { 33 | MyApp({Key? key}) : super(key: key); 34 | final MyData data = MyData(); 35 | 36 | 37 | @override 38 | Widget build(BuildContext context) { 39 | 40 | const title = 'MyAwesome App'; 41 | List items = data.items; 42 | 43 | return MaterialApp( 44 | title: title, 45 | home: Scaffold( 46 | appBar: AppBar( 47 | title: const Text(title), 48 | ), 49 | body: ListView.builder( 50 | itemCount: items.length, 51 | itemBuilder: (context, index) { 52 | return ListTile( 53 | title: Text(items[index]), 54 | ); 55 | }, 56 | ), 57 | ), 58 | ); 59 | } 60 | } 61 | ``` 62 | -------------------------------------------------------------------------------- /ch11/ex11-3.md: -------------------------------------------------------------------------------- 1 | # 11.3 Adding a SliverAppBar 2 | 3 | # Example 4 | 5 | ```dart 6 | import 'package:flutter/material.dart'; 7 | 8 | void main() => runApp(MyApp()); 9 | 10 | class MyApp extends StatelessWidget { 11 | @override 12 | Widget build(BuildContext context) { 13 | return MaterialApp( 14 | title: 'SliverAppBar Demo', 15 | debugShowCheckedModeBanner: false, 16 | theme: ThemeData( 17 | primarySwatch: Colors.blue, 18 | ), 19 | home: const MyHomePage(title: 'Flutter and Dart Cookbook'), 20 | ); 21 | } 22 | } 23 | 24 | class MyHomePage extends StatelessWidget { 25 | final String title; 26 | const MyHomePage({ 27 | Key? key, 28 | required this.title, 29 | }) : super(key: key); 30 | @override 31 | Widget build(BuildContext context) { 32 | return Scaffold( 33 | backgroundColor: Colors.grey[300], 34 | body: const CustomScrollView( 35 | slivers: [ 36 | SliverAppBar( 37 | leading: Icon(Icons.menu), 38 | title: Text('Sliver App Bar'), 39 | expandedHeight: 300, 40 | collapsedHeight: 150, 41 | floating: false, 42 | ), 43 | ], // End 44 | ), 45 | ); 46 | } 47 | } 48 | 49 | ``` 50 | -------------------------------------------------------------------------------- /ch03/ex3-2.md: -------------------------------------------------------------------------------- 1 | # 3.2 Adding parameters to Functions 2 | 3 | ## Example Code: 4 | 5 | The getCurrentDateTime() function gets the current date and time in London and prints it to the console. 6 | The function also subtracts 7 hours from the current time and prints the result. 7 | 8 | The DateTime.now() method returns the current date and time in the local time zone. 9 | In this case, the local time zone is London. 10 | 11 | The add() method adds a duration to a DateTime object. 12 | The Duration() constructor takes an argument that specifies the number of hours to add. 13 | In this case, the number of hours to add is -7. 14 | 15 | The print() function prints the value of the timeNow and timeDifference variables to the console. 16 | 17 | ```dart 18 | void main() { 19 | getCurrentDateTime(-7); 20 | } 21 | 22 | void getCurrentDateTime(int hourDifference) { 23 | var timeNow = DateTime.now(); 24 | var timeDifference = timeNow.add(Duration(hours: hourDifference)); 25 | 26 | print('The time now is: $timeNow'); 27 | print('The time minus 7 hours is: $timeDifference'); 28 | } 29 | ``` 30 | 31 | 32 | ## Example Output: 33 | 34 | ```dart 35 | The time now is: 2023-08-31 09:43:05.729546 36 | The time minus 7 hours is: 2023-08-31 02:43:05.729546 37 | ``` 38 | -------------------------------------------------------------------------------- /ch04/ex4-3.md: -------------------------------------------------------------------------------- 1 | # 4.3 Using Lists with Complex Types 2 | 3 | The main() function first creates three maps. 4 | The maps contain information about three Star Wars films: Star Wars, The Empire Strikes Back, and The Return of the Jedi. 5 | The function then creates a list of the maps. 6 | The function then sets the variable currentFilm to the first element of the list. 7 | The function then prints the value of the currentFilm variable to the console. 8 | The currentFilm variable is a map, so the function prints the key-value pairs of the map. 9 | The function then prints the value of the title key of the currentFilm variable. 10 | 11 | ## Example Code: 12 | 13 | ```dart 14 | void main() { 15 | Map filmStarWars = {"title": "Star Wars", "year": 1977}; 16 | Map filmEmpire = {"title": "The Empire Strikes Back", "year": 1980}; 17 | Map filmJedi = {"title": "The Return of the Jedi", "year": 1983}; 18 | 19 | List listFilms = [filmStarWars, filmEmpire, filmJedi]; 20 | 21 | Map currentFilm = listFilms[0]; 22 | 23 | print(currentFilm); 24 | print(currentFilm['title']); 25 | } 26 | ``` 27 | 28 | ## Example Output: 29 | 30 | ```dart 31 | {title: Star Wars, year: 1977} 32 | Star Wars 33 | ``` 34 | -------------------------------------------------------------------------------- /appendix/README.md: -------------------------------------------------------------------------------- 1 | # Flutter Full stack examples 2 | 3 | Developing Full-Stack Applications for the Cloud 4 | 5 | ![Flutter & Dart Cookbook](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/images/flutter-dart-cookbook-sml.png "Flutter & Dart Cookbook") 6 | 7 | Companion repository for O'Reilly Flutter & Dart Full Stack Cookbook 8 | 9 | ## Setting up your environment 10 | 11 | - [x] [18.1 How to install the Dart SDK](http://github.com/rosera/flutter-and-dart-cookbook/blob/main/appendix/ex1-1.md) 12 | - [x] [18.2 How to run a Dart application](http://github.com/rosera/flutter-and-dart-cookbook/blob/main/appendix/ex1-2.md) 13 | - [x] [18.3 Extending Android Studio to support Dart](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/appendix/ex1-3.md) 14 | - [x] [18.4 Developing with VS Code](http://github.com/rosera/flutter-and-dart-cookbook/blob/main/appendix/ex1-4.md) 15 | - [x] [18.5 Installing the Dart SDK](http://github.com/rosera/flutter-and-dart-cookbook/blob/main/appendix/ex1-5.md) 16 | - [x] [18.6 Running a Dart application](http://github.com/rosera/flutter-and-dart-cookbook/blob/main/appendix/ex1-6.md) 17 | - [x] [18.7 Selecting a release channel](http://github.com/rosera/flutter-and-dart-cookbook/blob/main/appendix/ex1-7.md) 18 | 19 | 20 | -------------------------------------------------------------------------------- /ch09/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Flutter Full stack examples 3 | 4 | Developing Full-Stack Applications for the Cloud 5 | 6 | ![Flutter & Dart Cookbook](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/images/flutter-dart-cookbook-sml.png "Flutter & Dart Cookbook") 7 | 8 | Companion repository for O'Reilly Flutter & Dart Full Stack Cookbook 9 | 10 | ## Working with widgets 11 | 12 | - [x] [9.1 Using the scaffold class](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch09/ex9-1.md) 13 | - [x] [9.2 Using an AppBar](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch09/ex9-2.md) 14 | - [x] [9.3 Using an Expanded widget](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch09/ex9-3.md) 15 | - [x] [9.4 Building with a container](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch09/ex9-4.md) 16 | - [x] [9.5 Using a Center widget](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch09/ex9-5.md) 17 | - [x] [9.6 Using a SizedBox](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch09/ex9-6.md) 18 | - [x] [9.7 Using a Column](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch09/ex9-7.md) 19 | - [x] [9.8 Using a Row](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch09/ex9-8.md) 20 | -------------------------------------------------------------------------------- /ch05/ex5-2.md: -------------------------------------------------------------------------------- 1 | # 5.2 Initializing a Class Using a Constructor 2 | 3 | ## Example Code: 4 | 5 | The DaysLeftInWeek class constructor initializes the currentDay property to the current day of the week. 6 | If today is Wednesday, then the value of currentDay will be 3. 7 | The howManyDaysLeft() method then returns the number of days left in the week, minus the current day of the week. 8 | In this case, there are 5 days left in the week (Sunday, Monday, Tuesday, Wednesday, and Thursday). 9 | 10 | The print() statements then print the current day of the week and the number of days left in the week to the console. 11 | 12 | If you run the code on a different day of the week, the output will be different. 13 | 14 | ```dart 15 | const numDays = 7; 16 | 17 | class DaysLeftInWeek { 18 | int currentDay = 0; 19 | 20 | DaysLeftInWeek(){ 21 | currentDay = DateTime.now().weekday.toInt(); 22 | } 23 | 24 | int howManyDaysLeft(){ 25 | return numDays - currentDay; 26 | } 27 | } 28 | 29 | void main() { 30 | var currentDay = DaysLeftInWeek(); 31 | 32 | print ('Today is day ${currentDay.currentDay}'); 33 | print ('We have ${currentDay.howManyDaysLeft()} day(s) left in the week'); 34 | } 35 | ``` 36 | 37 | ## Example Output: 38 | 39 | ```dart 40 | Today is day 6 41 | We have 1 day(s) left in the week 42 | ``` 43 | -------------------------------------------------------------------------------- /ch10/ex10-4.md: -------------------------------------------------------------------------------- 1 | # 10.4 Using a Placeholder widget 2 | 3 | 4 | # Example 5 | 6 | ```dart 7 | import 'package:flutter/material.dart'; 8 | 9 | void main() { 10 | runApp(const MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | const MyApp({Key? key}) : super(key: key); 15 | @override 16 | Widget build(BuildContext context) { 17 | const title = 'Expanded Widget'; 18 | return MaterialApp( 19 | title: title, 20 | home: Scaffold( 21 | appBar: AppBar( 22 | title: const Text(title), 23 | ), 24 | body: const MyExpandedWidget(), 25 | ), 26 | ); 27 | } 28 | } 29 | 30 | class MyExpandedWidget extends StatelessWidget { 31 | const MyExpandedWidget(); 32 | @override 33 | Widget build(BuildContext context) { 34 | return Column( 35 | children: const [ 36 | Expanded( 37 | child: Placeholder( 38 | fallbackHeight: 400, strokeWidth: 10, color: Colors.red), 39 | ), 40 | Expanded( 41 | child: Placeholder( 42 | fallbackHeight: 400, strokeWidth: 10, color: Colors.white), 43 | ), 44 | Expanded( 45 | child: Placeholder( 46 | fallbackHeight: 400, strokeWidth: 10, color: Colors.blue), 47 | ), 48 | ], 49 | ); 50 | } 51 | } 52 | ``` 53 | -------------------------------------------------------------------------------- /ch07/ex7-6.md: -------------------------------------------------------------------------------- 1 | # 7.6 Removing the Flutter Debug banner 2 | 3 | 4 | # Example Code: 5 | 6 | The code provided defines a Flutter application with a MaterialApp widget. 7 | 8 | The debugShowMaterialGrid and debugShowCheckedModeBanner properties are used to control the visibility of debugging tools in Flutter. 9 | The debugShowMaterialGrid property controls the visibility of the material grid, which is a grid that is used to help developers align widgets. 10 | The debugShowCheckedModeBanner property controls the visibility of the debug banner, which is a banner that is displayed at the top of the screen when the application is running in debug mode. 11 | 12 | ```dart 13 | import 'package:flutter/material.dart'; 14 | 15 | void main() { 16 | runApp(MyApp()); 17 | } 18 | 19 | class MyApp extends StatelessWidget { 20 | final appTitle = 'Cert In'; 21 | 22 | @override 23 | Widget build(BuildContext context) { 24 | return MaterialApp( 25 | title: appTitle, 26 | theme: ThemeData( 27 | primarySwatch: Colors.blue, 28 | visualDensity: VisualDensity.adaptivePlatformDensity, 29 | textTheme: GoogleFonts.montserratTextTheme(), 30 | ), 31 | debugShowMaterialGrid: false, 32 | debugShowCheckedModeBanner: false, 33 | home: Professional(title: appTitle), 34 | ); 35 | } 36 | } 37 | ``` 38 | -------------------------------------------------------------------------------- /ch14/ex14-1.md: -------------------------------------------------------------------------------- 1 | # 14.1 Testing Widgets in Flutter 2 | 3 | # Example: Flutter demo screeen image 4 | 5 | * add link to image no figure given in document* 6 | 7 | # Example: code 8 | 9 | ```dart 10 | import 'package:flutter/material.dart'; 11 | import 'package:flutter_test/flutter_test.dart'; 12 | 13 | import 'package:test_widget_app/main.dart'; 14 | 15 | void main() { 16 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 17 | // Build our app and trigger a frame. 18 | await tester.pumpWidget(const MyApp()); 19 | 20 | // Verify that our counter starts at 0. 21 | expect(find.text('0'), findsOneWidget); 22 | expect(find.text('1'), findsNothing); 23 | 24 | // Tap the '+' icon and trigger a frame. 25 | await tester.tap(find.byIcon(Icons.add)); 26 | await tester.pump(); 27 | 28 | // Verify that our counter has incremented. 29 | expect(find.text('0'), findsNothing); 30 | expect(find.text('1'), findsOneWidget); 31 | }); 32 | } 33 | 34 | ``` 35 | 36 | # Example: testyer.pumpWidget 37 | 38 | ```dart 39 | // Build our app and trigger a frame. 40 | await tester.pumpWidget(const MyApp()); 41 | 42 | ``` 43 | 44 | # Example: child of screen 45 | 46 | ```dart 47 | // Build our app and trigger a frame. 48 | await tester.pumpWidget(MaterialApp(detail: DetailPage())); 49 | ``` 50 | 51 | 52 | -------------------------------------------------------------------------------- /ch10/ex10-1.md: -------------------------------------------------------------------------------- 1 | # 10.1 Incorporating Rich Text 2 | 3 | # Example 4 | 5 | ```dart 6 | import 'package:flutter/material.dart'; 7 | 8 | void main() { 9 | runApp(const MyApp()); 10 | } 11 | 12 | class MyApp extends StatelessWidget { 13 | const MyApp({Key? key}) : super(key: key); 14 | @override 15 | Widget build(BuildContext context) { 16 | const title = 'RichText Demo'; 17 | return MaterialApp( 18 | title: title, 19 | home: Scaffold( 20 | appBar: AppBar( 21 | title: const Text(title), 22 | ), 23 | body: const MyRichText(), 24 | ), 25 | ); 26 | } 27 | } 28 | 29 | double screenHeight = 0.0; 30 | 31 | class MyRichText extends StatelessWidget { 32 | const MyRichText({Key? key}) : super(key: key); 33 | @override 34 | Widget build(BuildContext context) { 35 | screenHeight = MediaQuery.of(context).size.height / 3; 36 | return RichText( 37 | text: const TextSpan( 38 | children: [ 39 | TextSpan( 40 | text: 'Hello', 41 | style: TextStyle(fontWeight: FontWeight.bold, fontSize: 24), 42 | ), 43 | TextSpan( 44 | text: 'Luxembourg', 45 | style: TextStyle( 46 | fontWeight: FontWeight.bold, fontSize: 32, color: Colors.grey), 47 | ), 48 | ], 49 | ), 50 | ); 51 | } 52 | } 53 | ``` 54 | -------------------------------------------------------------------------------- /ch16/ex16-5.md: -------------------------------------------------------------------------------- 1 | # 16.5 Developing with Serverless (Cloud Run) 2 | 3 | # Example: create service account 4 | 5 | ```console 6 | gcloud iam service-accounts create api-cloud-run-invoker \ 7 | --display-name "My Cool Service Account" 8 | 9 | ``` 10 | 11 | # Example: Permissions 12 | 13 | ```console 14 | gcloud run services add-iam-policy-binding api-service \ 15 | --member=serviceAccount:api-cloud-run-invoker@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com \ 16 | --role=roles/run.invoker --platform managed 17 | 18 | ``` 19 | 20 | # Example: API's 21 | 22 | ```console 23 | const express = require('express'); 24 | const PORT = process.env.PORT || 8080; 25 | const app = express(); 26 | 27 | app.use(express.json()); 28 | 29 | app.listen(PORT, () => { 30 | console.log(`Simple REST API listening on port ${PORT}`); 31 | }); 32 | 33 | app.get('/', async (req, res) => { 34 | return res.status(200).json({'Status':'OK', 'Payload':'GET: Up and Running'}); 35 | }) 36 | 37 | app.post('/', async (req, res) => { 38 | return res.status(200).json({'Status':'OK', 'Payload':'POST: Up and Running'}); 39 | }) 40 | 41 | ``` 42 | # Example: Container Image 43 | 44 | ```console 45 | gcloud beta run deploy api-service \ 46 | --image gcr.io/[PROJECT_ID/api-service-image:latest 47 | 48 | ``` 49 | 50 | # Example : interact 51 | 52 | ```console 53 | curl --request GET [CLOUD_RUN_ENDPOINT] 54 | ``` 55 | -------------------------------------------------------------------------------- /ch07/ex7-4.md: -------------------------------------------------------------------------------- 1 | # 7.4 Working with a Stateless Widget 2 | 3 | ## Example Code: 4 | 5 | The code provided defines a Flutter application with a stateless widget. 6 | 7 | The MyApp class is a stateless widget. 8 | It defines the title of the application and the home screen. 9 | The home screen is a Scaffold widget with an AppBar and a body. 10 | The body is a MyTextWidget widget. 11 | 12 | The MyTextWidget class is a stateless widget. 13 | It defines a Center widget with a Text widget as its child. 14 | The Text widget displays the text "Hello". 15 | 16 | ```dart 17 | import 'package:flutter/material.dart'; 18 | 19 | void main() { 20 | runApp(const MyApp()); 21 | } 22 | 23 | class MyApp e 24 | xtends StatelessWidget { 25 | const MyApp({Key? key}) : super(key: key); 26 | 27 | @override 28 | Widget build(BuildContext context) { 29 | const title = 'Stateless Widget demo'; 30 | 31 | return MaterialApp( 32 | title: title, 33 | home: Scaffold( 34 | appBar: AppBar( 35 | title: const Text(title), 36 | ), 37 | body: const MyTextWidget(), 38 | ), 39 | ); 40 | } 41 | } 42 | 43 | class MyTextWidget extends StatelessWidget { 44 | const MyTextWidget({Key? key}) : super(key: key); 45 | 46 | @override 47 | Widget build(BuildContext context) { 48 | return const Center( 49 | child: Text('Hello'), 50 | ); 51 | } 52 | } 53 | ``` 54 | -------------------------------------------------------------------------------- /ch09/ex9-1.md: -------------------------------------------------------------------------------- 1 | # 9.1 Using the Scaffold class 2 | 3 | # Example 4 | 5 | ```dart 6 | import 'package:flutter/material.dart'; 7 | 8 | void main() => runApp(const MyApp()); 9 | 10 | class MyApp extends StatelessWidget { 11 | const MyApp({Key? key}) : super(key: key); 12 | 13 | static const String _title = 'Example'; 14 | 15 | @override 16 | Widget build(BuildContext context) { 17 | return const MaterialApp( 18 | title: _title, 19 | home: MyStatelessWidget(), 20 | ); 21 | } 22 | } 23 | 24 | class MyStatelessWidget extends StatelessWidget { 25 | const MyStatelessWidget({Key? key}) : super(key: key); 26 | 27 | @override 28 | Widget build(BuildContext context) { 29 | return Scaffold( 30 | appBar: AppBar(title: const Text('Scaffold Example')), 31 | backgroundColor: Colors.blueGrey, 32 | bottomNavigationBar: const BottomAppBar( 33 | color: Colors.blueAccent, 34 | shape: CircularNotchedRectangle(), 35 | child: SizedBox( 36 | height: 300, 37 | child: Center(child: Text("bottomNavigationBar")), 38 | ), 39 | ), 40 | body: _buildCardWidget(), 41 | ); 42 | } 43 | 44 | Widget _buildCardWidget() { 45 | return const SizedBox( 46 | height: 200, 47 | child: Card( 48 | child: Center( 49 | child: Text('Top Level Card'), 50 | ), 51 | ), 52 | ); 53 | } 54 | } 55 | 56 | ``` 57 | -------------------------------------------------------------------------------- /ch11/ex11-4.md: -------------------------------------------------------------------------------- 1 | # 11.4 Adding a grid of items 2 | 3 | # Example 4 | 5 | ```dart 6 | import 'package:flutter/material.dart'; 7 | 8 | void main() { 9 | runApp(const MyApp()); 10 | } 11 | 12 | class MyApp extends StatelessWidget { 13 | const MyApp({Key? key}) : super(key: key); 14 | @override 15 | Widget build(BuildContext context) { 16 | const title = 'MyAwesome App'; 17 | return MaterialApp( 18 | title: title, 19 | home: Scaffold( 20 | appBar: AppBar( 21 | title: const Text(title), 22 | ), 23 | body: const MyGridViewBuilderWidget(), 24 | ), 25 | ); 26 | } 27 | } 28 | 29 | class MyGridViewBuilderWidget extends StatelessWidget { 30 | const MyGridViewBuilderWidget({Key? key}) : super(key: key); 31 | final gridItems = 10; 32 | @override 33 | Widget build(BuildContext context) { 34 | return GridView.builder( 35 | itemCount: gridItems, 36 | gridDelegate: 37 | const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 5), 38 | itemBuilder: (context, index) { 39 | return Padding( 40 | padding: const EdgeInsets.all(8.0), 41 | child: Container( 42 | height: 50, 43 | width: 50, 44 | color: Colors.blue, 45 | child: Center(child: Text(index.toString())), 46 | )); 47 | }); 48 | } 49 | } 50 | 51 | ``` 52 | -------------------------------------------------------------------------------- /ch17/ex17-2.md: -------------------------------------------------------------------------------- 1 | # 17.2 Using the Flame Boilerplate 2 | 3 | # Example: main.dart 4 | 5 | ```dart 6 | import 'dart:async'; 7 | import 'package:flame/flame.dart'; 8 | import 'package:flame/game.dart'; 9 | import 'package:flutter/material.dart'; 10 | 11 | void main() async { 12 | WidgetsFlutterBinding.ensureInitialized(); 13 | await Flame.device.setPortrait(); 14 | final shapeGame = ShapesExample(); 15 | 16 | runApp(GameWidget(game: shapeGame)); 17 | } 18 | 19 | class ShapesExample extends FlameGame { 20 | double xStartPosition = 0; 21 | double yStartPosition = 0; 22 | static double xRectWidth = 50; 23 | static double yRectHeight = 50; 24 | 25 | final paint = Paint() 26 | ..color = Colors.white 27 | ..strokeWidth = 4; 28 | 29 | @override 30 | Future onLoad() async { 31 | super.onLoad(); 32 | 33 | // Set the start position of the Rect - center of the screen 34 | xStartPosition = (size[0]) / 2; 35 | yStartPosition = (size[1]) / 2; 36 | } 37 | 38 | @override 39 | void update(double dt) { 40 | super.update(dt); 41 | } 42 | 43 | @override 44 | void render(Canvas canvas) { 45 | super.render(canvas); 46 | 47 | // xStartPos, yStartPos, xRectWidth, yRectHeight 48 | canvas.drawRect( 49 | Rect.fromLTWH( 50 | xStartPosition, 51 | yStartPosition, 52 | xRectWidth, 53 | yRectHeight), 54 | paint); 55 | } 56 | } 57 | 58 | ``` 59 | -------------------------------------------------------------------------------- /ch04/ex4-7.md: -------------------------------------------------------------------------------- 1 | # 4.7 Printing Complex Data Types 2 | 3 | ## Example Code: 4 | 5 | The main() function first creates a JSON value. 6 | The JSON value is a map with two key-value pairs. 7 | The key "title" has the value "Star Wars" and the key "year" has the value 1977. 8 | The function then decodes the JSON value into a Dart map. 9 | The Dart map is assigned to the variable items. 10 | 11 | The function then prints the value of the items variable to the console. 12 | The items variable is a Dart map, so the function prints the key-value pairs of the map. 13 | The function then prints the value of the title key of the items variable. 14 | The function then prints the value of the title key of the items variable using two different string interpolation syntaxes. 15 | 16 | ```dart 17 | import 'dart:convert'; 18 | 19 | void main() { 20 | // Create JSON value 21 | Map data = { 22 | jsonEncode('title'): json.encode('Star Wars'), 23 | jsonEncode('year'): json.encode(1979) 24 | }; 25 | 26 | // Decode the JSON 27 | Map items = json.decode(data.toString()); 28 | 29 | print(items); 30 | print(items['title']); 31 | print("This is the title: $items['title']"); 32 | print('This is the title: ${items['title']}'); 33 | } 34 | 35 | ``` 36 | 37 | ## Example Output: 38 | 39 | ```dart 40 | {title: Star Wars, year: 1977} 41 | Star Wars 42 | This is the title: Star Wars 43 | This is the title: Star Wars 44 | ``` 45 | -------------------------------------------------------------------------------- /ch06/ex6-3.md: -------------------------------------------------------------------------------- 1 | # 6.3 Running Unit Tests in Your Dart Application 2 | 3 | ## Example Code: 4 | 5 | The code provided defines a test for the Travel class. 6 | It uses the expect() function from the test package to assert that the expected value is equal to the actual value. 7 | The test ensures that the distance property is set correctly when the Travel class is instantiated. 8 | 9 | The test first creates two variables: 10 | * distance 11 | * expectedDistance. 12 | 13 | The distance variable is assigned the value 10.0. 14 | The expectedDistance variable is assigned the same value. 15 | 16 | The test then creates an instance of the Travel class and passes the value of expectedDistance to the constructor. 17 | The test then creates a variable called result and sets it to the value of the distance property on the Travel instance. 18 | 19 | The test then asserts that the value of result is equal to the value of expectedDistance. 20 | This ensures that the distance property is set correctly when the Travel class is instantiated. 21 | 22 | 23 | ```dart 24 | import 'package:test_dart_sample/test_dart_sample.dart'; 25 | 26 | void main() { 27 | test('Travel Distance', () { 28 | // Arrange 29 | var distance = 10.0; 30 | var expectedDistance = distance; 31 | 32 | // Act 33 | var travel = Travel(expectedDistance); 34 | var result = travel.distance; 35 | 36 | // Assert 37 | expect(expectedDistance, result); 38 | }); 39 | } 40 | ``` 41 | -------------------------------------------------------------------------------- /ch01/README.md: -------------------------------------------------------------------------------- 1 | # Flutter and Dart Cookbook examples 2 | 3 | Developing Full-Stack Applications for the Cloud 4 | 5 | ![Flutter & Dart Cookbook](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/images/flutter-dart-cookbook-sml.png "Flutter & Dart Cookbook") 6 | 7 | Companion repository for O'Reilly Flutter & Dart Full Stack Cookbook 8 | 9 | ## Learning Dart variables 10 | 11 | - [x] [1.1 Running a Dart application](http://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch01/ex-dart.md) 12 | - [x] [1.2 Working with Integer values](http://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch01/ex-integer.md) 13 | - [x] [1.3 Working with Double values](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch01/ex-double.md) 14 | - [x] [1.4 Working with Boolean values](http://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch01/ex-bool.md) 15 | - [x] [1.5 Working with Strings](http://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch01/ex-string.md) 16 | - [x] [1.6 Printing information to the console](http://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch01/ex-print.md) 17 | - [x] [1.7 Adding a Constant Variable (Compile Time)](http://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch01/ex-const.md) 18 | - [x] [1.8 Adding a Constant Variable (Runtime)](http://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch01/ex-final.md) 19 | - [x] [1.9 Working with Null variables](http://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch01/ex-null.md) 20 | -------------------------------------------------------------------------------- /ch02/ex-switch.md: -------------------------------------------------------------------------------- 1 | # 2.4 Using a Switch statement 2 | 3 | # Example Code: 4 | 5 | The variable myValue is assigned the value 1. 6 | The switch statement checks if the value of myValue is equal to 1, 2, or another value that is specified in a case clause. 7 | If the value of myValue is equal to one of the values that is specified in a case clause, the body of the case clause is executed. 8 | If the value of myValue is not equal to any of the values that is specified in a case clause, the body of the default clause is executed. 9 | 10 | In this case, the value of myValue is equal to 1, so the body of the case clause with the value 1 is executed. 11 | The body of the case clause prints the message "Monday" to the console. 12 | 13 | The break statement is used to terminate the execution of the switch statement. 14 | If the break statement is not used, the body of the next case clause will also be executed. 15 | 16 | The default clause is used to execute a block of code if the value of the expression in the switch statement does not match any of the values that are specified in the case clauses. 17 | 18 | ```dart 19 | void main() { 20 | int myValue = 1; 21 | 22 | switch (myValue) { 23 | case 1: print('Monday'); 24 | break; 25 | case 2: print('Tuesday'); 26 | break; 27 | default: 28 | print('Error: Value not defined?'); 29 | break; 30 | } 31 | } 32 | ``` 33 | 34 | ## Example Output: 35 | 36 | The result of the print statement is shown below: 37 | ```dart 38 | Monday 39 | ``` 40 | -------------------------------------------------------------------------------- /ch01/ex1-11.md: -------------------------------------------------------------------------------- 1 | # 2.11 How to use Import 2 | 3 | ## Example Code: 4 | 5 | Generate a random number between 0 and 9, inclusive. 6 | The Random() class is used to generate random numbers in Dart. 7 | The nextInt() method of the Random() class generates a random integer between 0 and the specified maximum value, exclusive. 8 | In this case, the maximum value is 10, so the random number will be between 0 and 9. 9 | The print() function prints the value of the seed variable to the console. 10 | 11 | A breakdown of the code: 12 | 13 | * The first line imports the dart:math library, which contains the Random() class. 14 | * The second line declares a variable called seed and assigns it the value of the nextInt() method of the Random() class. 15 | * The third line calls the print() function and passes the value of the seed variable as an argument. 16 | * The nextInt() method of the Random() class generates a random integer using a pseudorandom number generator. This means that the sequence of random numbers generated by the nextInt() method will be deterministic, given the same seed value. 17 | 18 | 19 | 20 | ```dart 21 | import 'dart:math'; 22 | 23 | void main() { 24 | 25 | // Generate random number between 0-9 26 | int seed = Random().nextInt(10); 27 | 28 | print ('Seed: $seed'); 29 | } 30 | ``` 31 | 32 | ## Example Output: 33 | 34 | The result of the print statement is shown below: 35 | 36 | ```dart 37 | Seed: 4 38 | ``` 39 | 40 | Note: As the seed variable is random, a different value may be shown at runtime. 41 | -------------------------------------------------------------------------------- /ch11/ex11-1.md: -------------------------------------------------------------------------------- 1 | # 11.1 Implementing a vertical list 2 | 3 | # Example 4 | 5 | ```dart 6 | import 'package:flutter/material.dart'; 7 | 8 | class ListTileItem { 9 | final String monthItem; 10 | const ListTileItem({ 11 | required this.monthItem, 12 | }); 13 | } 14 | 15 | class ListDataItems { 16 | final List monthItems = [ 17 | 'January', 18 | 'February', 19 | 'March', 20 | 'April', 21 | 'May', 22 | 'June', 23 | 'July', 24 | 'August', 25 | 'September', 26 | 'October', 27 | 'November', 28 | 'December', 29 | ]; 30 | ListDataItems(); 31 | } 32 | 33 | void main() { 34 | runApp(const MyApp()); 35 | } 36 | 37 | class MyApp extends StatelessWidget { 38 | const MyApp({Key? key}) : super(key: key); 39 | @override 40 | Widget build(BuildContext context) { 41 | const title = 'MyAwesome App'; 42 | return MaterialApp( 43 | title: title, 44 | home: Scaffold( 45 | appBar: AppBar( 46 | title: const Text(title), 47 | ), 48 | body: MyListView(), 49 | ), 50 | ); 51 | } 52 | } 53 | 54 | class MyListView extends StatelessWidget { 55 | MyListView(); 56 | final ListDataItems item = ListDataItems(); 57 | @override 58 | Widget build(BuildContext context) { 59 | return ListView.builder( 60 | itemCount: item.monthItems.length, 61 | itemBuilder: (context, index) { 62 | return ListTile(title: Text(item.monthItems[index])); 63 | }, 64 | ); 65 | } 66 | } 67 | 68 | ``` 69 | -------------------------------------------------------------------------------- /ch01/ex1-10.md: -------------------------------------------------------------------------------- 1 | # 2.7 How to handle Exceptions 2 | 3 | ## Example Code: 4 | 5 | The indexOf() method throws a RangeError exception when the specified substring is not found. 6 | In this case, the substring name[0] is not found at the index name.length - (name.length+2), so the RangeError exception is thrown. 7 | The try block is used to execute code that might cause an exception. 8 | The catch block is used to handle the exception. 9 | The finally block is always executed, regardless of whether an exception is thrown. 10 | In this case, the try block executes the code that calls the indexOf() method. 11 | The indexOf() method throws a RangeError exception, which is caught by the catch block. 12 | The catch block prints the exception message to the console. 13 | The finally block prints the message "Mission completed!" to the console. 14 | This message is always printed, regardless of whether an exception is thrown. 15 | 16 | ```dart 17 | void main(){ 18 | String name = "Dart"; 19 | 20 | try{ 21 | print ('Name: $name'); 22 | 23 | // The following line generates a RangeError 24 | name.indexOf(name[0], name.length - (name.length+2)); 25 | } catch (exception) { 26 | print ('Exception: $exception'); 27 | } finally { 28 | print ('Mission completed!'); 29 | } 30 | } 31 | ``` 32 | 33 | ## Example Output: 34 | 35 | The result of the print statement is shown below: 36 | 37 | ```dart 38 | Name: Dart 39 | Exception: RangeError: Invalid value: Not in inclusive range 0..4: -2 40 | Mission completed! 41 | ``` 42 | -------------------------------------------------------------------------------- /ch06/ex6-4.md: -------------------------------------------------------------------------------- 1 | # 6.4 Grouping Multiple Unit Tests 2 | 3 | ## Example Code: 4 | 5 | The code you have provided defines three tests for the Travel class. 6 | * Travel Distance 7 | * Travel Distance to Miles 8 | * Travel Distance to Kilometers 9 | 10 | The tests ensure that the distance property is set correctly when the Travel class is instantiated, that the distanceToMiles() method returns the correct value, and that the distanceToKilometers() method returns the correct value. 11 | 12 | ```dart 13 | import 'package:test_dart_sample/test_dart_sample.dart'; import 'package:test/test.dart'; 14 | 15 | void main() { 16 | test('Travel Distance', () { 17 | // Arrange 18 | var distance = 10.0; 19 | var expectedDistance = distance; 20 | // Act 21 | var travel = Travel(expectedDistance); 22 | var result = travel.distance; 23 | // Assert 24 | expect(expectedDistance, result); 25 | }); 26 | 27 | test('Travel Distance to Miles', () { 28 | // Arrange 29 | var miles = 10.0; 30 | var expectedMiles = miles * convertToMiles; 31 | // Act 32 | var travel = Travel(miles); 33 | var result = travel.distanceToMiles(); 34 | // Assert 35 | expect(expectedMiles, result); 36 | }); 37 | 38 | test('Travel Distance to Kilometers', () { 39 | // Arrange 40 | var kilometers = 10.0; 41 | var expectedKiloMeters = kilometers * convertToKilometers; 42 | // Act 43 | var travel = Travel(kilometers); 44 | var result = travel.distanceToKilometers(); 45 | // Assert 46 | expect(expectedKiloMeters, result); 47 | }); 48 | } 49 | ``` 50 | -------------------------------------------------------------------------------- /ch03/ex3-4.md: -------------------------------------------------------------------------------- 1 | # 3.4 Returning Values from Functions 2 | 3 | ## Example Code: 4 | 5 | The getCurrentDateTime() function gets the current date and time in London and returns a DateTime object. 6 | The main() function calls the getCurrentDateTime() function twice, once with an argument of 0 and once with an argument of -7. The main() function then prints the value of the timeNow and timeDifference variables to the console. 7 | 8 | The DateTime.now() method returns the current date and time in the local time zone. 9 | In this case, the local time zone is London. 10 | 11 | The add() method adds a duration to a DateTime object. 12 | The Duration() constructor takes an argument that specifies the number of hours. 13 | A positive value means add, a negative value means subtract. 14 | In this case, the duration is set to a negative, meaning subtract 7 hours. 15 | 16 | The print() function prints the value of the timeNow and timeDifference variables to the console. 17 | 18 | 19 | ```dart 20 | void main() { 21 | DateTime timeNow = getCurrentDateTime(0); 22 | DateTime timeDifference = getCurrentDateTime(-7); 23 | 24 | print('The time now is: $timeNow'); 25 | print('The time minus 7 hours is: $timeDifference'); 26 | } 27 | 28 | DateTime getCurrentDateTime(int hourDifference) { 29 | DateTime timeNow = DateTime.now(); 30 | DateTime timeDifference = timeNow.add(Duration(hours: hourDifference)); 31 | 32 | return timeDifference; 33 | } 34 | ``` 35 | 36 | ## Example Output: 37 | 38 | ```dart 39 | The time now is: 2022-08-31 09:44:49.540889 40 | The time minus 7 hours is: 2022-08-31 02:44:49.540889 41 | ``` 42 | -------------------------------------------------------------------------------- /ch09/ex9-2.md: -------------------------------------------------------------------------------- 1 | # 9.2 Using an AppBar 2 | 3 | # Example 4 | 5 | ```dart 6 | import 'package:flutter/material.dart'; 7 | 8 | void main() { 9 | runApp(const MyApp()); 10 | } 11 | 12 | class MyApp extends StatelessWidget { 13 | final String title = 'Container Widget'; 14 | const MyApp({Key? key}) : super(key: key); 15 | 16 | @override 17 | Widget build(BuildContext context) { 18 | return MaterialApp( 19 | debugShowCheckedModeBanner: false, 20 | title: title, 21 | home: Scaffold( 22 | appBar: MyAppBar(title: title), 23 | body: const MyCenterWidget(), 24 | ), 25 | ); 26 | } 27 | } 28 | 29 | class MyAppBar extends StatelessWidget implements PreferredSizeWidget { 30 | final String title; 31 | final double sizeAppBar = 200.0; 32 | 33 | const MyAppBar({Key? key, required this.title}) : super(key: key); 34 | 35 | @override 36 | Size get preferredSize => Size.fromHeight(sizeAppBar); 37 | 38 | @override 39 | build(BuildContext context) { 40 | return AppBar( 41 | title: Text(title), 42 | backgroundColor: Colors.black, 43 | elevation: 0.0, 44 | leading: IconButton(onPressed: () {}, icon: const Icon(Icons.menu)), 45 | actions: [IconButton(onPressed: () {}, icon: const Icon(Icons.settings))], 46 | ); 47 | } 48 | } 49 | 50 | class MyCenterWidget extends StatelessWidget { 51 | const MyCenterWidget({Key? key}) : super(key: key); 52 | 53 | @override 54 | Widget build(BuildContext context) { 55 | return const Center( 56 | child: Text('Hello Flutter!'), 57 | ); 58 | } 59 | } 60 | 61 | 62 | ``` 63 | -------------------------------------------------------------------------------- /ch17/ex17-5.md: -------------------------------------------------------------------------------- 1 | # 17.5 Adding Text rendering 2 | 3 | 4 | # Example 5 | 6 | ```dart 7 | import 'dart:async'; 8 | import 'package:flame/flame.dart'; 9 | import 'package:flame/game.dart'; 10 | import 'package:flame/components.dart'; 11 | import 'package:flutter/material.dart'; 12 | 13 | void main() async { 14 | WidgetsFlutterBinding.ensureInitialized(); 15 | await Flame.device.setPortrait(); 16 | final shapeGame = ShapesExample(); 17 | 18 | runApp(GameWidget(game: shapeGame)); 19 | } 20 | 21 | class ShapesExample extends FlameGame { 22 | @override 23 | Future onLoad() async { 24 | super.onLoad(); 25 | 26 | add(TextComponent(size[0], size[1])); 27 | } 28 | 29 | // @override 30 | // void update(double dt) { 31 | // super.update(dt); 32 | // } 33 | 34 | // @override 35 | // void render(Canvas canvas) { 36 | // super.render(canvas); 37 | // } 38 | } 39 | 40 | class TextComponent extends TextBoxComponent { 41 | final double screenWidth; 42 | final double screenHeight; 43 | double xP1 = 0; 44 | double yP1 = 0; 45 | 46 | final textPaint = TextPaint( 47 | style: const TextStyle( 48 | color: Colors.white, 49 | fontSize: 22.0, 50 | fontFamily: 'Awesome Font')); 51 | 52 | TextComponent(this.screenWidth, this.screenHeight); 53 | 54 | @override 55 | Future onLoad() async { 56 | super.onLoad(); 57 | 58 | xP1 = screenWidth / 2; 59 | yP1 = screenHeight / 2; 60 | } 61 | 62 | @override 63 | void render(Canvas canvas) { 64 | textPaint.render(canvas, "Flame Game Engine", Vector2(xP1, yP1)); 65 | } 66 | } 67 | ``` 68 | 69 | -------------------------------------------------------------------------------- /ch01/ex-const.md: -------------------------------------------------------------------------------- 1 | # 1.7 Using a Const 2 | 3 | ## Example Code 1 (Compile Time): 4 | 5 | A compile time value is known when the application code is generated. 6 | 7 | * The first line declares a variable called daysInYear and assigns it the type const. 8 | * The second line assigns the value 365 to the variable daysInYear. 9 | * The third line calls the print() function and passes the value of daysInYear as an argument. 10 | * The print() function will then print the value of daysInYear to the console. 11 | 12 | ```dart 13 | void main() { 14 | const daysInYear = 365; 15 | 16 | print ('There are $daysInYear days in a year'); 17 | } 18 | 19 | ``` 20 | 21 | ## Example Output: 22 | 23 | The result of the print statement is shown below: 24 | 25 | ```dart 26 | There are 365 days in a year 27 | ``` 28 | 29 | 30 | ## Example Code 2 (Run Time): 31 | 32 | A run time value is known when the application is run. 33 | 34 | * The first line declares a variable called today and assigns it the value of the current date and time. 35 | * The second line calls the weekday() method on the today variable and passes the result to the print() function. 36 | * The weekday() method returns an integer representing the day of the week, with 1 representing Monday, 2 representing Tuesday, and so on. 37 | * The print() function will then print the value of the weekday() method to the console. 38 | 39 | ```dart 40 | void main() { 41 | final today = DateTime.now(); 42 | 43 | print ('Today is day ${today.weekday} '); 44 | } 45 | 46 | ``` 47 | 48 | ## Example Output: 49 | 50 | The result of the print statement is shown below: 51 | 52 | ```dart 53 | Today is day XXX 54 | ``` 55 | -------------------------------------------------------------------------------- /ch09/ex9-3.md: -------------------------------------------------------------------------------- 1 | # 9.3 Using an Expanded widget 2 | 3 | # Example 4 | 5 | ```dart 6 | import 'package:flutter/material.dart'; 7 | 8 | void main() { 9 | runApp(const MyApp()); 10 | } 11 | 12 | class MyApp extends StatelessWidget { 13 | const MyApp({Key? key}) : super(key: key); 14 | 15 | @override 16 | Widget build(BuildContext context) { 17 | const title = 'Expanded Widget'; 18 | 19 | return MaterialApp( 20 | title: title, 21 | home: Scaffold( 22 | appBar: AppBar( 23 | title: const Text(title), 24 | ), 25 | body: const MyExpandedWidget(), 26 | ), 27 | ); 28 | } 29 | } 30 | 31 | class MyExpandedWidget extends StatelessWidget { 32 | const MyExpandedWidget(); 33 | 34 | @override 35 | Widget build(BuildContext context) { 36 | return Column( 37 | children: [ 38 | Expanded( 39 | child: Container( 40 | color: Colors.red, 41 | ), 42 | ), 43 | Expanded( 44 | child: Container( 45 | ), 46 | ), 47 | RichText( 48 | text: const TextSpan( 49 | text: 'Luxembourg', 50 | style: TextStyle( 51 | fontWeight: FontWeight.bold, 52 | fontSize: 24, 53 | color: Colors.grey, 54 | ), 55 | ), 56 | ), 57 | Expanded( 58 | child: Container( 59 | ), 60 | ), 61 | Expanded( 62 | child: Container( 63 | color: Colors.blue, 64 | ), 65 | ), 66 | ], 67 | ); 68 | } 69 | } 70 | 71 | ``` 72 | 73 | *Add links to fig 4.1 and 4.2 images* 74 | 75 | 76 | -------------------------------------------------------------------------------- /ch17/examples/lab01/README.md: -------------------------------------------------------------------------------- 1 | # Flutter and Dart Cookbook 2 | ## Building a Solar System Simulation 3 | 4 | ![Flame Solar System](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/images/flame_solar_system.png "Flame Solar System") 5 | 6 | * GitHub: [lab01 - Building a Solar System](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch15/examples/lab01/flame_solar_system.md) 7 | 8 | ## Overview 9 | The beauty of the solar system example, is once you know how to display a planet, a similar approach can be used to display the others. 10 | To keep things simple, the example does not use sprites, so will work with dartpad.dev. 11 | Note: This is a demo, so for simplicity some coding shortcuts apply. 12 | 13 | Just to get you up to speed on the solar system, there are eight planets that rotate in an anticlockwise direction around the sun. 14 | In the demo code, a two dimensional (2d) simulation will be used to replicate the rotational orbit of the planets. 15 | To achieve the objective the canvas object will be used to map our objects into a 2d setting. 16 | 17 | ## Example 18 | In this example build a model solar System where you will: 19 | 20 | * Use the basics of the Flame game engine 21 | * Understand how to use Canvas tools to draw shapes such as a circle 22 | * Translate an object in two dimensional space 23 | * Rotate an object about an axis 24 | * Add Canvas text to an onscreen object 25 | 26 | ## Learn More 27 | You can learn more about the solar system at the following links: 28 | * Wikipedia: https://en.wikipedia.org/wiki/Rotation_period 29 | * Nasa: https://spaceplace.nasa.gov/years-on-other-planets/en/ 30 | * Orrery: https://en.wikipedia.org/wiki/Orrery 31 | -------------------------------------------------------------------------------- /ch10/ex10-2.md: -------------------------------------------------------------------------------- 1 | # 10.2 Incorporating the Google fonts package 2 | 3 | 4 | # Example: depenencies 5 | 6 | ```dart 7 | . 8 | . 9 | . 10 | dependencies: 11 | flutter: 12 | sdk: flutter 13 | 14 | cupertino_icon: ^1.0.2 15 | google_fonts: 2.2.0 16 | 17 | 18 | ``` 19 | 20 | # Example: main.dart 21 | 22 | ```dart 23 | import 'package:flutter/material.dart'; 24 | import 'package:google_fonts/google_fonts.dart'; 25 | 26 | void main() => runApp(MyApp()); 27 | 28 | class MyApp extends StatelessWidget { 29 | @override 30 | Widget build(BuildContext context) { 31 | return MaterialApp( 32 | title: 'Google Fonts Demo', 33 | debugShowCheckedModeBanner: false, 34 | theme: ThemeData( 35 | primarySwatch: Colors.blue, 36 | textTheme: TextTheme( 37 | bodyText1: GoogleFonts.aBeeZee(fontSize: 30, color: Colors.deepOrange), 38 | bodyText2: GoogleFonts.aBeeZee(fontSize: 30, color: Colors.white60)) 39 | ), 40 | home: const MyHomePage(title: 'Flutterand Dart Cookbook'), 41 | ); 42 | } 43 | } 44 | 45 | class MyHomePage extends StatelessWidget { 46 | final String title; 47 | 48 | const MyHomePage({ 49 | Key? key, 50 | required this.title, 51 | }) : super(key: key); 52 | 53 | @override 54 | Widget build(BuildContext context) { 55 | return Scaffold( 56 | backgroundColor: Colors.black, 57 | body: Column(children: [ 58 | const Text('Yo MTV Raps'), 59 | Text('Yo MTV Raps', style: GoogleFonts.coiny(fontSize: 30, color: Colors.blueGrey),), 60 | Text('Yo MTV Raps', style: GoogleFonts.actor(fontSize: 30, color: Colors.indigo),), 61 | ]), 62 | ); 63 | } 64 | } 65 | 66 | ``` 67 | -------------------------------------------------------------------------------- /ch15/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Flutter Full stack examples 3 | 4 | Developing Full-Stack Applications for the Cloud 5 | 6 | ![Flutter & Dart Cookbook](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/images/flutter-dart-cookbook-sml.png "Flutter & Dart Cookbook") 7 | 8 | Companion repository for O'Reilly Flutter & Dart Full Stack Cookbook 9 | 10 | ## Working with Firebase and Flutter 11 | 12 | - [x] [15.1 Integrating Firebase backend with Flutter](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch15/ex15-1.md) 13 | - [x] [15.2 Setting up a Firebase project](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch15/ex15-2.md) 14 | - [x] [15.3 Initilise Firebase on the client](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch15/ex15-3.md) 15 | - [x] [15.4 Firebase/Flutter client integration](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch15/ex15-4.md) 16 | - [x] [15.5 Configuring Firebase emulators for local development](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch15/ex15-5.md) 17 | - [x] [15.6 Adding Firebase authentication to Flutter ](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch15/ex15-6.md) 18 | - [x] [15.7 Setting up cloud Firestore](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch15/ex15-7.md) 19 | - [x] [15.8 Writing data to cloud Firestore](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch15/ex15-8.md) 20 | - [x] [15.9 Reading data from cloud Firestore](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch15/ex15-9.md) 21 | - [x] [15.10 Using Flutter Web with Firebase Hosting](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch15/ex15-10.md) 22 | -------------------------------------------------------------------------------- /ch03/ex3-5.md: -------------------------------------------------------------------------------- 1 | # 3.5 Declaring Anonymous functions 2 | 3 | ## Example Code: 4 | The code defines two anonymous functions, ex1Squared() and ex1Cubed(). 5 | Anonymous functions are functions that do not have a name. 6 | They are often used when you need to define a function inline, without having to declare it first. 7 | 8 | The ex1Squared() function takes an integer as input and returns the square of that integer. 9 | The ex1Cubed() function takes an integer as input and returns the cube of that integer. 10 | 11 | The code then calls both anonymous functions twice, once with the value 5 as input. 12 | The results of the function calls are printed to the console. 13 | 14 | In the first style of anonymous function, the function body is defined using the => operator. 15 | In the second style of anonymous function, the function body is defined using curly braces ({}) and the return statement. 16 | 17 | ```dart 18 | void main() { 19 | int value = 5; 20 | 21 | // Anonymous Function - Style 1 22 | int ex1Squared(num1) => num1 * num1; 23 | int ex1Cubed(num1) => num1 * num1 * num1; 24 | 25 | // Anonymous Function - Style 2 26 | int ex2Squared(num1){ return num1 * num1; } 27 | int ex2Cubed(num1){ return num1 * num1 * num1; } 28 | 29 | // Anonymous Function - Style 1 30 | print('EX1: $value squared is ${ex1Squared(value)}'); 31 | print('EX1: $value cubed is ${ex1Cubed(value)}'); 32 | 33 | // Anonymous Function - Style 2 34 | print('EX2: $value squared is ${ex2Squared(value)}'); 35 | print('EX2: $value cubed is ${ex2Cubed(value)}'); 36 | } 37 | 38 | ``` 39 | 40 | ## Example Output: 41 | ```dart 42 | EX1: 5 squared is 25 43 | EX1: 5 cubed is 125 44 | EX2: 5 squared is 25 45 | EX2: 5 cubed is 125 46 | ``` 47 | -------------------------------------------------------------------------------- /ch09/ex9-6.md: -------------------------------------------------------------------------------- 1 | # 9.6 Using a SizedBox 2 | 3 | # Example 4 | 5 | ```dart 6 | import 'package:flutter/material.dart'; 7 | 8 | void main() => runApp(const MyApp()); 9 | 10 | class MyApp extends StatelessWidget { 11 | const MyApp({Key? key}) : super(key: key); 12 | static const String _title = 'SizedBox Widget Demo'; 13 | @override 14 | Widget build(BuildContext context) { 15 | return const MaterialApp( 16 | title: _title, 17 | home: MyStatelessWidget(), 18 | ); 19 | } 20 | } 21 | 22 | class MyStatelessWidget extends StatelessWidget { 23 | const MyStatelessWidget({Key? key}) : super(key: key); 24 | @override 25 | Widget build(BuildContext context) { 26 | return Scaffold( 27 | appBar: AppBar(title: const Text('SizedBox Example')), 28 | body: _buildSizedBoxWidget(), 29 | ); 30 | } 31 | 32 | Widget _buildSizedBoxWidget() { 33 | return SingleChildScrollView( 34 | padding: const EdgeInsets.all(10.0), 35 | child: Column( 36 | children: const [ 37 | SizedBox( 38 | width: 200, 39 | height: 100, 40 | child: Card( 41 | color: Colors.amber, child: Center(child: Text('Developer'))), 42 | ), 43 | SizedBox( 44 | width: 300, 45 | height: 100, 46 | child: Card( 47 | color: Colors.green, 48 | child: Center(child: Text('Flutter Framework'))), 49 | ), 50 | SizedBox( 51 | width: 400, 52 | height: 100, 53 | child: Card( 54 | color: Colors.blue, child: Center(child: Text('Dart SDK'))), 55 | ), 56 | ], 57 | ), 58 | ); 59 | } 60 | } 61 | 62 | ``` 63 | -------------------------------------------------------------------------------- /ch05/ex5-1.md: -------------------------------------------------------------------------------- 1 | # 5.1 Creating a Class 2 | 3 | ## Example Code: 4 | 5 | The code provided defines a class called DaysLeftInWeek. 6 | The class has two properties: 7 | * currentDay 8 | * howManyDaysLeft. 9 | 10 | The currentDay property stores the current day of the week. 11 | The howManyDaysLeft property stores the number of days left in the week. 12 | 13 | The class also has two constructors: the default constructor and a parameterized constructor. 14 | The default constructor initializes the currentDay property to the current day of the week. 15 | The parameterized constructor takes an integer argument as input and initializes the currentDay property to the value of the argument. 16 | 17 | The class also has one method: howManyDaysLeft(). 18 | The howManyDaysLeft() method returns the number of days left in the week. 19 | The method subtracts the value of the currentDay property from the constant numDays. 20 | The DaysLeftInWeek class constructor initializes the currentDay property to the current day of the week. 21 | If today is Wednesday, then the value of currentDay will be 3. 22 | The howManyDaysLeft() method then returns the number of days left in the week, minus the current day of the week. 23 | In this case, there are 5 days left in the week (Sunday, Monday, Tuesday, Wednesday, and Thursday). 24 | 25 | 26 | ```dart 27 | const numDays = 7; 28 | 29 | class DaysLeftInWeek { 30 | int currentDay = 0; 31 | 32 | DaysLeftInWeek(){ 33 | currentDay = DateTime.now().weekday.toInt(); 34 | } 35 | 36 | int howManyDaysLeft(){ 37 | return numDays - currentDay; 38 | } 39 | } 40 | 41 | void main() { 42 | DaysLeftInWeek daysLeftInWeek = DaysLeftInWeek(); 43 | print(daysLeftInWeek.howManyDaysLeft()); 44 | } 45 | ``` 46 | 47 | 48 | ## Example Output: 49 | ```dart 50 | 5 51 | ``` 52 | -------------------------------------------------------------------------------- /ch11/ex11-2.md: -------------------------------------------------------------------------------- 1 | # 11.2 Implementing a horizontal list 2 | 3 | # Example 4 | 5 | ```dart 6 | import 'package:flutter/material.dart'; 7 | 8 | class ListTileItem { 9 | final String monthItem; 10 | const ListTileItem({ 11 | required this.monthItem, 12 | }); 13 | } 14 | 15 | class ListDataItems { 16 | final List monthItems = [ 17 | 'January', 18 | 'February', 19 | 'March', 20 | 'April', 21 | 'May', 22 | 'June', 23 | 'July', 24 | 'August', 25 | 'September', 26 | 'October', 27 | 'November', 28 | 'December', 29 | ]; 30 | ListDataItems(); 31 | } 32 | 33 | void main() { 34 | runApp(const MyApp()); 35 | } 36 | 37 | class MyApp extends StatelessWidget { 38 | const MyApp({Key? key}) : super(key: key); 39 | @override 40 | Widget build(BuildContext context) { 41 | const title = 'MyAwesome App'; 42 | return MaterialApp( 43 | title: title, 44 | home: Scaffold( 45 | appBar: AppBar( 46 | title: const Text(title), 47 | ), 48 | body: MyListView(), 49 | ), 50 | ); 51 | } 52 | } 53 | 54 | class MyListView extends StatelessWidget { 55 | MyListView({Key? key}) : super(key: key); 56 | final ListDataItems item = ListDataItems(); 57 | @override 58 | Widget build(BuildContext context) { 59 | return ListView.builder( 60 | scrollDirection: Axis.horizontal, 61 | itemCount: item.monthItems.length, 62 | itemBuilder: (context, index) { 63 | return Row( 64 | crossAxisAlignment: CrossAxisAlignment.start, 65 | children: [ 66 | Text(item.monthItems[index]), 67 | const SizedBox( 68 | width: 10.0, 69 | ), 70 | ], 71 | ); 72 | }, 73 | ); 74 | } 75 | } 76 | 77 | 78 | ``` 79 | -------------------------------------------------------------------------------- /ch02/ex-exception.md: -------------------------------------------------------------------------------- 1 | # 2.6 Handling Exceptions 2 | 3 | ## Example Code: 4 | 5 | The indexOf() method throws a RangeError exception when the specified substring is not found. 6 | In this case, the substring name[0] is not found at the index name.length - (name.length+2), so the RangeError exception is thrown. 7 | 8 | The try block is used to execute code that might cause an exception. 9 | The on clause specifies the type of exception that is expected. 10 | In this case, the on clause specifies that a RangeError exception is expected. 11 | 12 | The catch clause is used to handle the exception. 13 | The catch clause prints the exception message to the console. 14 | 15 | The finally block is always executed, regardless of whether an exception is thrown. 16 | 17 | In this case, the try block executes the code that calls the indexOf() method. 18 | The indexOf() method throws a RangeError exception, which is handled by the on clause. 19 | The on clause prints the exception message to the console. 20 | 21 | The finally block prints the message "Mission completed!" to the console. 22 | This message is always printed, regardless of whether an exception is thrown. 23 | 24 | ```dart 25 | void main(){ 26 | String name = "Dart"; 27 | 28 | try{ 29 | print ('Name: $name'); 30 | // The following line generates a RangeError 31 | name.indexOf(name[0], name.length - (name.length+2)); 32 | } on RangeError catch (exception) { 33 | print ('On Exception: $exception'); 34 | } 35 | catch (exception) { 36 | print ('Catch Exception: $exception'); 37 | } finally { 38 | print ('Mission completed!'); 39 | } 40 | } 41 | ``` 42 | 43 | ## Example Output: 44 | 45 | The result of the print statement is shown below: 46 | 47 | ```dart 48 | Name: Dart 49 | On Exception: substring not found 50 | Mission completed! 51 | ``` 52 | -------------------------------------------------------------------------------- /ch17/ex17-3.md: -------------------------------------------------------------------------------- 1 | # 17.3 Refactoring with Flame components 2 | 3 | # Example 4 | 5 | ```dart 6 | import 'dart:async'; 7 | import 'package:flame/flame.dart'; 8 | import 'package:flame/game.dart'; 9 | import 'package:flame/components.dart'; 10 | import 'package:flutter/material.dart'; 11 | 12 | void main() async { 13 | WidgetsFlutterBinding.ensureInitialized(); 14 | await Flame.device.setPortrait(); 15 | final shapeGame = ShapesExample(); 16 | 17 | runApp(GameWidget(game: shapeGame)); 18 | } 19 | 20 | class ShapesExample extends FlameGame { 21 | @override 22 | Future onLoad() async { 23 | super.onLoad(); 24 | 25 | add(RectComponent(size[0], size[1])); 26 | } 27 | 28 | // @override 29 | // void update(double dt) { 30 | // super.update(dt); 31 | // } 32 | 33 | // @override 34 | // void render(Canvas canvas) { 35 | // super.render(canvas); 36 | // } 37 | 38 | } 39 | 40 | // Add a [Color] Rect on screen 41 | class RectComponent extends Component { 42 | final double screenWidth; 43 | final double screenHeight; 44 | double xStartPosition = 0; 45 | double yStartPosition = 0; 46 | static double xRectWidth = 50; 47 | static double yRectHeight = 50; 48 | 49 | final paint = Paint() 50 | ..color = Colors.white 51 | ..strokeWidth = 4; 52 | 53 | RectComponent(this.screenWidth, this.screenHeight); 54 | 55 | @override 56 | void update(double dt) { 57 | super.update(dt); 58 | xStartPosition = screenWidth / 2; 59 | yStartPosition = screenHeight / 2; 60 | } 61 | 62 | @override 63 | void render(Canvas canvas) { 64 | super.render(canvas); 65 | 66 | // xStartPos, yStartPos, xRectWidth, yRectHeight 67 | canvas.drawRect( 68 | Rect.fromLTWH( 69 | xStartPosition, 70 | yStartPosition, 71 | xRectWidth, 72 | yRectHeight), 73 | paint); 74 | } 75 | } 76 | ``` 77 | -------------------------------------------------------------------------------- /ch03/ex3-6.md: -------------------------------------------------------------------------------- 1 | # 3.6 Functional Delay using a Future 2 | 3 | ## Example Code 4 | 5 | The main() function first prints the message "Hello" to the console. 6 | Then, the function calls the `_customDelay()` function with the argument myDelay. 7 | The `_customDelay()` function is an asynchronous function, which means that it does not return immediately. Instead, it returns a Future object. The Future object will eventually be completed with the value of the delay argument. 8 | 9 | The main() function then calls the await keyword on the Future object returned by the `_customDelay()` function. 10 | The await keyword tells the main() function to wait until the Future object is completed. 11 | Once the Future object is completed, the main() function prints the value of the delay argument to the console. 12 | 13 | The `_customDelay()` function uses the Future.delayed() method to create a Future object that will be completed after delay seconds. 14 | The Future.delayed() method takes a Duration object as an argument. The Duration object specifies the amount of time to wait before completing the Future object. 15 | 16 | If an error occurs while the `_customDelay()` function is running, the catch block will be executed. 17 | The catch block prints the error message to the console and returns the value of the delay argument. 18 | 19 | ```dart 20 | void main() async { 21 | int myDelay = 5; 22 | print('Hello'); 23 | var value = await _customDelay(myDelay); 24 | var customText = myDelay == 1 ? "second later" : "seconds later"; 25 | print('Its $value $customText'); 26 | } 27 | 28 | Future _customDelay(int delay) async { 29 | try { 30 | await Future.delayed(Duration(seconds: delay)); 31 | return delay; 32 | } catch (e) { 33 | print(e); 34 | return delay; 35 | } 36 | } 37 | ``` 38 | 39 | ## Example Output 40 | 41 | ```dart 42 | Hello 43 | Its 5 seconds later 44 | ``` 45 | -------------------------------------------------------------------------------- /ch11/ex11-5.md: -------------------------------------------------------------------------------- 1 | # 11.5 Adding a Snackbar (Popup notification) 2 | 3 | # Example: Snackbar 4 | 5 | ```dart 6 | import 'package:flutter/material.dart'; 7 | 8 | void main() { 9 | runApp(const MyApp()); 10 | } 11 | 12 | class MyApp extends StatelessWidget { 13 | const MyApp({Key? key}) : super(key: key); 14 | @override 15 | Widget build(BuildContext context) { 16 | const title = 'MyAwesome App'; 17 | return MaterialApp( 18 | title: title, 19 | home: Scaffold( 20 | appBar: AppBar( 21 | title: const Text(title), 22 | ), 23 | body: MyListView(), 24 | ), 25 | ); 26 | } 27 | } 28 | 29 | class ListViewData { 30 | final List monthItems = [ 31 | 'January', 32 | 'February', 33 | 'March', 34 | ]; 35 | } 36 | 37 | class MyListView extends StatelessWidget { 38 | MyListView({Key? key}) : super(key: key); 39 | final ListViewData items = ListViewData(); 40 | @override 41 | Widget build(BuildContext context) { 42 | return ListView.builder( 43 | itemCount: items.monthItems.length, 44 | itemBuilder: (context, index) { 45 | return ListTile( 46 | title: Text(items.monthItems[index]), 47 | onTap: () { 48 | ScaffoldMessenger.of(context).showSnackBar( 49 | SnackBar( 50 | content: Text('You selected ${items.monthItems[index]}'), 51 | ), 52 | ); 53 | }, 54 | ); 55 | }); 56 | } 57 | } 58 | 59 | ``` 60 | 61 | # Example: Snackbar Action 62 | 63 | ```dart 64 | SnackBar( 65 | action: SnackBarAction( 66 | label: 'action', 67 | onPressed: () {}, 68 | 69 | ), 70 | duration: const Duration(seconds: 10, milliseconds: 500), 71 | content: Text('You selected $listTitle'), 72 | ), 73 | 74 | ``` 75 | -------------------------------------------------------------------------------- /ch07/ex7-3.md: -------------------------------------------------------------------------------- 1 | # 7.3 Working with a Stateful Widget 2 | 3 | # Example Code: 4 | 5 | The MyApp class is a stateless widget. 6 | It defines the title of the application and the home screen. 7 | The home screen is a Scaffold widget with an AppBar and a body. 8 | The body is a MyTextWidget widget. 9 | 10 | The MyTextWidget class is a stateful widget. 11 | It defines a count property that keeps track of the number of times the widget has been tapped. 12 | The build() method of the MyTextWidget class returns a GestureDetector widget. 13 | The GestureDetector widget listens for taps and calls the setState() method of the MyTextWidget class when it is tapped. 14 | The setState() method updates the value of the count property and triggers a re-render of the MyTextWidget widget. 15 | 16 | ```dart 17 | import 'package:flutter/material.dart'; 18 | 19 | void main() { 20 | runApp(const MyApp()); 21 | } 22 | 23 | class MyApp extends StatelessWidget { 24 | const MyApp({Key? key}) : super(key: key); 25 | 26 | @override 27 | Widget build(BuildContext context) { 28 | const title = 'Stateless Widget demo'; 29 | 30 | return MaterialApp( 31 | title: title, 32 | home: Scaffold( 33 | appBar: AppBar( 34 | title: const Text(title), 35 | ), 36 | body: const MyTextWidget(), 37 | ), 38 | ); 39 | } 40 | } 41 | 42 | class MyTextWidget extends StatefulWidget { 43 | const MyTextWidget({Key? key}) : super(key: key); 44 | 45 | @override 46 | _MyTextWidget createState() => _MyTextWidget(); 47 | } 48 | 49 | class _MyTextWidget extends State { 50 | int count = 0; 51 | 52 | @override 53 | Widget build(BuildContext context){ 54 | return GestureDetector( 55 | onTap: () { 56 | setState((){ 57 | count++; 58 | }); 59 | }, 60 | child: Center(child: Text('Click Me: $count')), 61 | ); 62 | } 63 | } 64 | ``` 65 | -------------------------------------------------------------------------------- /ch06/ex6-5.md: -------------------------------------------------------------------------------- 1 | # 6.5 Adding Mock Data for Testing 2 | 3 | # Example Code: 4 | 5 | The code provided defines a test for the Travel class. 6 | It uses the asyncExpect() and timeout() functions from the test package to ensure that the test fails if the loadResource() method takes too long to return the value. 7 | The test ensures that the distance property is set correctly when the Travel class is instantiated, even if the loadResource() method takes some time to return the value. 8 | 9 | The test uses the asyncExpect() function from the test package to fail the test if the loadResource() method takes more than 6 seconds to return the value. 10 | This is a good way to ensure that the test fails if the loadResource() method takes too long to return the value. 11 | 12 | The test also uses the timeout() function from the test package to fail the test if the asyncExpect() function does not return within a specified amount of time. 13 | This will ensure that the test fails if the loadResource() method takes too long to return the value, even if the asyncExpect() function does return within the specified amount of time. 14 | 15 | ```dart 16 | import 'package:test/test.dart'; 17 | 18 | Future _loadResource(int testDelay) async { 19 | try { 20 | await Future.delayed(Duration(seconds: testDelay)); 21 | return 10.0; 22 | } catch (e) { 23 | print(e); 24 | return 0.0; 25 | } 26 | } 27 | 28 | void main() { 29 | test('Travel Distance Delay', () async { 30 | // Arrange 31 | int customDelay = 5; 32 | 33 | var distance = await _loadResource(customDelay); 34 | var expectedDistance = distance; 35 | 36 | // Act 37 | var travel = Travel(expectedDistance); 38 | var result = travel.distance; 39 | 40 | // Assert 41 | // Use asyncExpect() to fail the test if _loadResource() takes too long 42 | asyncExpect(result == expectedDistance, timeout: Duration(seconds: customDelay + 1)); 43 | }); 44 | } 45 | ``` 46 | -------------------------------------------------------------------------------- /ch06/ex6-7.md: -------------------------------------------------------------------------------- 1 | # 6.7 Adding Mock Data for Testing 2 | 3 | # Example 4 | 5 | The code provided defines an asynchronous test for a login widget. 6 | The test ensures that the login widget allows the user to login successfully. 7 | 8 | The test first creates three variables: 9 | * testUsername 10 | * testPassword 11 | * testLoginBtn. 12 | 13 | These variables are used to store the keys of the widgets that will be interacted with in the test. 14 | 15 | The test then calls the pumpWidget() method on the WidgetTester object. 16 | This method renders the widget tree to the screen. 17 | 18 | The test then calls the enterText() method on the WidgetTester object to enter the username and password into the corresponding text fields. 19 | 20 | The test then calls the tap() method on the WidgetTester object to tap the login button. 21 | 22 | The test finally calls the pump() method on the WidgetTester object to flush the pending changes to the screen. 23 | 24 | The test then asserts that the text "Login credentials supplied" is displayed. This ensures that the login widget allowed the user to login successfully. 25 | 26 | It uses the WidgetTester class to interact with the widget tree and to assert that the desired results are achieved. 27 | 28 | 29 | ```dart 30 | void main(){ 31 | testLoginWidget(“should allow login”, (WidgetTester testWorker) async { 32 | // Arrange 33 | final testUsername = find.byKey(ValueKey(“testUsername”)); 34 | final testPassword = find.byKey(ValueKey(“testPassword”)); 35 | final testLoginBtn = find.byKey(ValueKey(“testLoginBtn”)); 36 | 37 | // Act 38 | await testWorker.pumpWidget(MaterialApp(home: Home())); 39 | await testWorker.enterText(testUsername, “username”); 40 | await testWorker.enterText(testPassword, “password”); 41 | await testWorker.tap(testLoginBtn); 42 | Await testWorker.pump(); 43 | 44 | // Assert 45 | expect(find.text(“Login credentials supplied”), findsOneWidget); 46 | } 47 | } 48 | ``` 49 | -------------------------------------------------------------------------------- /ch05/ex5-4.md: -------------------------------------------------------------------------------- 1 | # 5.4 Extending Classes with Mixins 2 | 3 | 4 | ## Example Code: 5 | 6 | The CandyBar class inherits the properties and methods of the ChocolateBar class and the SnickersOriginal class. 7 | The SnickersOriginal class has the properties hasHazelnut and hasRice, which are both set to true. 8 | The ChocolateBar class has the property hasChocolate, which is also set to true. 9 | 10 | The CandyBar class constructor iterates over the properties of the SnickersOriginal class and the ChocolateBar class and adds them to the ingredients list. 11 | The getIngredients() method then returns the ingredients list. 12 | 13 | The main() function creates an instance of the CandyBar class and calls the getIngredients() method. 14 | The getIngredients() method returns the ingredients list, which is then printed to the console. 15 | 16 | ```dart 17 | abstract class SnickersOriginal { 18 | bool hasHazelnut = true; 19 | bool hasRice = false; 20 | bool hasAlmond = false; 21 | } 22 | 23 | abstract class SnickersCrisp { 24 | bool hasHazelnut = true; 25 | bool hasRice = true; 26 | bool hasAlmond = false; 27 | } 28 | 29 | class ChocolateBar { 30 | bool hasChocolate = true; 31 | } 32 | 33 | class CandyBar extends ChocolateBar with SnickersOriginal { 34 | List ingredients = []; 35 | 36 | CandyBar(){ 37 | if (hasChocolate){ 38 | ingredients.add('Chocolate'); 39 | } 40 | if (hasHazelnut){ 41 | ingredients.add('Hazelnut'); 42 | } 43 | if (hasRice){ 44 | ingredients.add('Hazelnut'); 45 | } 46 | if (hasAlmond){ 47 | ingredients.add('Almonds'); 48 | } 49 | } 50 | 51 | List getIngredients(){ 52 | return ingredients; 53 | } 54 | } 55 | 56 | void main() { 57 | var snickersOriginal = CandyBar(); 58 | print ('Ingredients:'); 59 | snickersOriginal.getIngredients().forEach((ingredient) => print(ingredient)); 60 | } 61 | ``` 62 | 63 | 64 | ## Example Output: 65 | 66 | ```dart 67 | Ingredients: 68 | Chocolate 69 | Hazelnut 70 | ``` 71 | -------------------------------------------------------------------------------- /ch12/ex12-4.md: -------------------------------------------------------------------------------- 1 | # 12.4 Adding Bottom navigation 2 | 3 | # Example 4 | 5 | ```dart 6 | import 'package:flutter/material.dart'; 7 | 8 | void main() { 9 | runApp(const MyApp()); 10 | } 11 | 12 | class MyApp extends StatelessWidget { 13 | const MyApp({Key? key}) : super(key: key); 14 | 15 | @override 16 | Widget build(BuildContext context) { 17 | return const MaterialApp( 18 | title: "Bottom Navigation Widget", home: MyBottomNavigationWidget()); 19 | } 20 | } 21 | 22 | final List _navigationPages = [ 23 | const Center(child: Text('Page: Home')), 24 | const Center(child: Text('Page: News')), 25 | const Center(child: Text('Demo: Favorites')), 26 | const Center(child: Text('Demo: List')), 27 | ]; 28 | 29 | class MyBottomNavigationWidget extends StatefulWidget { 30 | const MyBottomNavigationWidget({Key? key}) : super(key: key); 31 | 32 | @override 33 | _MyBottomNavigationWidget createState() => _MyBottomNavigationWidget(); 34 | } 35 | 36 | class _MyBottomNavigationWidget extends State { 37 | final appTitle = 'Bottom Navigation Widget'; 38 | int _itemSelected = 0; 39 | 40 | void _bottomBarNavigation(int index) { 41 | setState(() { 42 | _itemSelected = index; 43 | }); 44 | } 45 | 46 | @override 47 | Widget build(BuildContext context) { 48 | return Scaffold( 49 | appBar: AppBar( 50 | title: Text(appTitle), 51 | ), 52 | body: _navigationPages[_itemSelected], 53 | bottomNavigationBar: BottomNavigationBar( 54 | currentIndex: _itemSelected, 55 | onTap: _bottomBarNavigation, 56 | type: BottomNavigationBarType.fixed, 57 | items: const [ 58 | BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Home'), 59 | BottomNavigationBarItem(icon: Icon(Icons.info), label: 'News'), 60 | BottomNavigationBarItem( 61 | icon: Icon(Icons.favorite), label: 'Favorites'), 62 | BottomNavigationBarItem(icon: Icon(Icons.list), label: 'List'), 63 | ], 64 | ), 65 | ); 66 | } 67 | } 68 | 69 | ``` 70 | 71 | -------------------------------------------------------------------------------- /ch17/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Flutter Full stack examples 3 | 4 | Developing Full-Stack Applications for the Cloud 5 | 6 | ![Flutter & Dart Cookbook](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/images/flutter-dart-cookbook-sml.png "Flutter & Dart Cookbook") 7 | 8 | Companion repository for O'Reilly Flutter & Dart Full Stack Cookbook 9 | 10 | ## Starting with game development 11 | 12 | - [x] [17.1 Adding the Flame package to Flutter](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch17/ex17-1.md) 13 | - [x] [17.2 Using the Flame boilerplate](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch17/ex17-2.md) 14 | - [x] [17.3 Refactoring with Flame components](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch17/ex17-3.md) 15 | - [x] [17.4 Using the Flame graphic primitives](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch17/ex17-4.md) 16 | - [x] [17.5 Adding text rendering](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch17/ex17-5.md) 17 | - [x] [17.6 Adding sound effects to a Flame game](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch17/ex17-6.md) 18 | - [x] [17.7 Adding keyboard input](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch17/ex17-7.md) 19 | - [x] [17.8 Adding collision detection](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch17/ex17-8.md) 20 | - [x] [17.9 Adding input for user interactivity](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch17/ex17-9.md) 21 | 22 | ## Examples 23 | 24 | Where practical the examples will work on [Dartpad.dev](https://dartpad.dev) 25 | 26 | 1. [Flame Solar System](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/ch17/examples/lab01/README.md) 27 | 28 | A quick example showing how to use the Flame game engine to create a solar system model. 29 | 30 | ![Flame Solar System](https://github.com/rosera/flutter-and-dart-cookbook/blob/main/images/flame_solar_system.png "Flame Solar System") 31 | 32 | 2. Flame Pong 33 | 34 | A quick example showing how to use the Flame game engine to create a game of Pong. 35 | 36 | [TBC]() 37 | -------------------------------------------------------------------------------- /ch09/ex9-8.md: -------------------------------------------------------------------------------- 1 | # 9.8 Using a Row 2 | 3 | # Example 4 | 5 | ```dart 6 | import 'package:flutter/material.dart'; 7 | 8 | void main() => runApp(const MyApp()); 9 | 10 | class MyApp extends StatelessWidget { 11 | const MyApp({Key? key}) : super(key: key); 12 | 13 | static const String _title = 'Example'; 14 | 15 | @override 16 | Widget build(BuildContext context) { 17 | return const MaterialApp( 18 | title: _title, 19 | home: MyStatelessWidget(), 20 | ); 21 | } 22 | } 23 | 24 | class MyStatelessWidget extends StatelessWidget { 25 | const MyStatelessWidget({Key? key}) : super(key: key); 26 | 27 | @override 28 | Widget build(BuildContext context) { 29 | return Scaffold( 30 | appBar: AppBar(title: const Text('Row Example')), 31 | body: _buildRowWidget(), 32 | ); 33 | } 34 | 35 | Widget _buildRowWidget() { 36 | return Row( 37 | mainAxisAlignment: MainAxisAlignment.start, 38 | crossAxisAlignment: CrossAxisAlignment.end, 39 | children: [ 40 | Container( 41 | width: 5, 42 | color: Colors.transparent, 43 | ), 44 | Expanded( 45 | child: Container( 46 | height: 50, 47 | width: 200, 48 | color: Colors.red, 49 | child: const Center( 50 | child: Text("50"), 51 | ), 52 | ), 53 | ), 54 | Expanded( 55 | child: Container( 56 | height: 100, 57 | width: 200, 58 | color: Colors.green, 59 | child: const Center( 60 | child: Text("100"), 61 | ), 62 | ), 63 | ), 64 | Expanded( 65 | child: Container( 66 | height: 200, 67 | width: 200, 68 | color: Colors.orange, 69 | child: const Center( 70 | child: Text("200"), 71 | ), 72 | ), 73 | ), 74 | Container( 75 | width: 5, 76 | color: Colors.transparent, 77 | ), 78 | ]); 79 | } 80 | } 81 | 82 | ``` 83 | -------------------------------------------------------------------------------- /ch05/ex5-3.md: -------------------------------------------------------------------------------- 1 | # 5.3 Adding Class Inheritance 2 | 3 | # Example 4 | 5 | The Media class has three properties: title, type, and mediaTitle. 6 | The title property is a string that stores the title of the media. 7 | The type property is a string that stores the type of the media. 8 | The mediaTitle property is a getter and setter for the title property. 9 | 10 | The Book class extends the Media class and adds two properties: author and isbn. 11 | The author property is a string that stores the author of the book. 12 | The isbn property is a string that stores the ISBN of the book. 13 | 14 | The main() function creates two instances of the Media class: myMedia and myBook. 15 | The myMedia instance is assigned the title "Tron". 16 | The myBook instance is assigned the title "Jungle Book" and the author "R Kipling". 17 | 18 | The print() statements then print the title, author, and type of each media instance to the console. 19 | 20 | 21 | ```dart 22 | class Media { 23 | String title = ""; 24 | String type = ""; 25 | 26 | Media(){ type = "Class"; } 27 | 28 | void setMediaTitle(String mediaTitle){ title = mediaTitle; } 29 | 30 | String getMediaTitle(){ return title; } 31 | 32 | String getMediaType(){ return type; } 33 | } 34 | 35 | class Book extends Media { 36 | String author = ""; 37 | String isbn = ""; 38 | 39 | Book(){ type = "Subclass"; } 40 | 41 | void setBookTitle(String bookTitle){ title = bookTitle; } 42 | 43 | void setBookAuthor(String bookAuthor){ author = bookAuthor; } 44 | 45 | void setBookISBN(String bookISBN){ isbn = bookISBN; } 46 | 47 | String getBookTitle(){ return title; } 48 | 49 | String getBookAuthor(){ return author; } 50 | 51 | String getBookISBN(){ return isbn; } 52 | } 53 | 54 | void main() { 55 | var myMedia = Media(); 56 | 57 | myMedia.setMediaTitle('Tron'); 58 | print ('Title: ${myMedia.getMediaTitle()}'); 59 | print ('Type: ${myMedia.getMediaType()}'); 60 | 61 | 62 | var myBook = Book(); 63 | myBook.setBookTitle("Jungle Book"); 64 | myBook.setBookAuthor("R Kipling"); 65 | print ('Title: ${myBook.getMediaTitle()}'); 66 | print ('Author: ${myBook.getBookAuthor()}'); 67 | print ('Type: ${myBook.getMediaType()}'); 68 | } 69 | 70 | ``` 71 | 72 | ## Example Output: 73 | 74 | ```dart 75 | Title: Tron 76 | Type: Class 77 | Title: Jungle Book 78 | Author: R Kipling 79 | Type: Subclass 80 | ``` 81 | -------------------------------------------------------------------------------- /ch06/ex6-6.md: -------------------------------------------------------------------------------- 1 | # 6.6 Automated Widget Testing in Flutter 2 | 3 | ## Example Code: 4 | 5 | The code provided defines a test for de-facto Counter Flutter widget. 6 | The test ensures that the counter widget increments correctly. 7 | 8 | The test first imports the flutter and flutter_test packages. 9 | The flutter package provides the Flutter widgets, while the flutter_test package provides the testing framework. 10 | 11 | The test then imports the main.dart file, which contains the code for the Flutter widget. 12 | 13 | The test then defines a test called Counter increments smoke test. 14 | The test uses the WidgetTester class to interact with the widget tree and to assert that the desired results are achieved. 15 | 16 | The test first builds the widget tree and triggers a frame. 17 | This ensures that the widget tree is rendered to the screen. 18 | 19 | The test then asserts that the counter starts at 0. 20 | This is done by calling the find.text() method with the text "0" as the argument. 21 | The find.text() method returns a Finder object, which can be used to interact with the widget tree. 22 | 23 | The test then taps the + icon and triggers a frame. 24 | This ensures that the + icon is tapped and that the counter is incremented. 25 | 26 | The test then asserts that the counter has incremented. 27 | This is done by calling the find.text() method with the text "1" as the argument. 28 | The find.text() method returns a Finder object, which can be used to interact with the widget tree. 29 | 30 | It uses the WidgetTester class to interact with the widget tree and to assert that the desired results are achieved. 31 | 32 | 33 | ```dart 34 | import 'package:flutter/material.dart'; 35 | import 'package:flutter_test/flutter_test.dart'; 36 | import 'package:test_widget_app/main.dart'; 37 | 38 | void main() { 39 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 40 | // Build our app and trigger a frame. 41 | await tester.pumpWidget(const MyApp()); 42 | 43 | // Verify that our counter starts at 0. 44 | expect(find.text('0'), findsOneWidget); 45 | expect(find.text('1'), findsNothing); 46 | 47 | // Tap the '+' icon and trigger a frame. 48 | await tester.tap(find.byIcon(Icons.add)); 49 | await tester.pump(); 50 | 51 | // Verify that our counter has incremented. 52 | expect(find.text('0'), findsNothing); 53 | expect(find.text('1'), findsOneWidget); 54 | }); 55 | } 56 | ``` 57 | -------------------------------------------------------------------------------- /ch02/ex-enum.md: -------------------------------------------------------------------------------- 1 | # 2.5 Using an Enum 2 | 3 | ## Example Code: Enum 4 | 5 | The values property of an enum returns an array of all the values of the enum. 6 | In this case, the enum Day has three values: sun, mon, and tues. 7 | The enum keyword is used to create an enumerated type in Dart. 8 | Enumerated types are a way of creating a set of named constants. 9 | 10 | A breakdown of the code: 11 | 12 | * The first line declares an enum called Day with three values: sun, mon, and tues. 13 | * The second line prints the value of the values property of the Day enum to the console. 14 | 15 | 16 | ```dart 17 | enum Day { sun, mon, tues } 18 | 19 | void main() { 20 | print('$Day.values'); 21 | } 22 | 23 | ``` 24 | 25 | ## Example Output: 26 | 27 | The result of the print statement is shown below: 28 | ```dart 29 | [sun, mon, tues] 30 | ``` 31 | 32 | 33 | ## Example Code: Index zero 34 | 35 | The values property of an enum returns an array of all the values of the enum, starting from index 0. 36 | In this case, the enum Day has three values: sun, mon, and tues. 37 | The index 0 refers to the first value, which is sun. 38 | 39 | A breakdown of the code: 40 | 41 | * The first line declares an enum called Day with three values: sun, mon, and tues. 42 | * The second line prints the value of the values property of the Day enum at index 0 to the console. 43 | 44 | ```dart 45 | enum Day { sun, mon, tues } 46 | 47 | void main() { 48 | print('${Day.values[0]}'); 49 | } 50 | 51 | ``` 52 | 53 | 54 | ## Example Output: 55 | 56 | The result of the print statement is shown below: 57 | ```dart 58 | sun 59 | ``` 60 | 61 | 62 | ## Example Code: Values.byName 63 | 64 | The byName() method of the EnumByName extension on enums returns the enum value with the specified name. In this case, the name mon refers to the enum value Day.mon. 65 | 66 | The EnumByName extension is a built-in extension in Dart that allows you to access enum values by name. 67 | 68 | A breakdown of the code: 69 | 70 | * The first line declares an enum called Day with three values: sun, mon, and tues. 71 | * The second line prints the value of the byName() method of the values.byName on the Day enum with the name mon to the console. 72 | 73 | ```dart 74 | enum Day { sun, mon, tues } 75 | 76 | void main() { 77 | print(Day.values.byName('mon')); 78 | } 79 | ``` 80 | 81 | ## Example Output: 82 | 83 | The result of the print statement is shown below: 84 | ```dart 85 | mon 86 | ``` 87 | -------------------------------------------------------------------------------- /ch09/column-example.md: -------------------------------------------------------------------------------- 1 | # Column Example (Old) 2 | 3 | ## Example 4 | ``` 5 | import 'package:flutter/material.dart'; 6 | 7 | void main() => runApp(const MyApp()); 8 | 9 | class MyApp extends StatelessWidget { 10 | const MyApp({Key? key}) : super(key: key); 11 | 12 | static const String _title = 'Example'; 13 | 14 | @override 15 | Widget build(BuildContext context) { 16 | return const MaterialApp( 17 | title: _title, 18 | home: MyStatelessWidget(), 19 | ); 20 | } 21 | } 22 | 23 | class MyStatelessWidget extends StatelessWidget { 24 | const MyStatelessWidget({Key? key}) : super(key: key); 25 | 26 | @override 27 | Widget build(BuildContext context) { 28 | return Scaffold( 29 | appBar: AppBar(title: const Text('Column Example')), 30 | body: _buildColumnWidget(), 31 | ); 32 | } 33 | 34 | Widget _buildColumnWidget() { 35 | return SingleChildScrollView( 36 | child: Column( 37 | mainAxisAlignment: MainAxisAlignment.start, 38 | crossAxisAlignment: CrossAxisAlignment.start, 39 | children: const [ 40 | SizedBox( 41 | height: 50, 42 | child: Card( 43 | color: Colors.red, 44 | child: Center( 45 | child: Text("1. Watch YouTube", 46 | style: 47 | TextStyle(fontSize: 18, color: Colors.white))))), 48 | SizedBox( 49 | height: 50, 50 | child: Card( 51 | color: Colors.red, 52 | child: Center( 53 | child: Text("2. Fix the code", 54 | style: 55 | TextStyle(fontSize: 18, color: Colors.white))))), 56 | SizedBox( 57 | height: 50, 58 | child: Card( 59 | color: Colors.red, 60 | child: Center( 61 | child: Text("3. Update the code repo", 62 | style: 63 | TextStyle(fontSize: 18, color: Colors.white))))), 64 | SizedBox( 65 | height: 50, 66 | child: Card( 67 | color: Colors.red, 68 | child: Center( 69 | child: Text("4. Take a break", 70 | style: 71 | TextStyle(fontSize: 18, color: Colors.white))))), 72 | ])); 73 | } 74 | } 75 | 76 | ``` 77 | -------------------------------------------------------------------------------- /ch02/ex-while.md: -------------------------------------------------------------------------------- 1 | # 2.2 Using While/Do While 2 | 3 | 4 | ## Example Code: While loop 5 | 6 | The while loop iterates until the value of the variable isTrue is false. 7 | The body of the loop prints the message "Hello" to the console. 8 | 9 | The while loop is a control flow statement that allows you to execute a block of code repeatedly until a condition is met. 10 | The while loop has two parts: 11 | 12 | * The condition: This is evaluated before each iteration of the loop. If the condition is true, the body of the loop is executed. If the condition is false, the loop terminates. 13 | * The body: This is executed repeatedly until the condition is false. 14 | 15 | In this case, the condition checks if the value of isTrue is true. 16 | 17 | If it is, the body of the loop is executed. 18 | The body of the loop prints the message "Hello" to the console. 19 | The value of isTrue is then set to false. 20 | 21 | The loop will continue to iterate until the value of isTrue is false. 22 | Once the value of isTrue is false, the loop will terminate. 23 | 24 | 25 | ```dart 26 | void main() { 27 | 28 | bool isTrue = true; 29 | 30 | while (isTrue) { 31 | print ('Hello'); 32 | isTrue = false; 33 | } 34 | } 35 | 36 | ``` 37 | 38 | 39 | ## Example Output: 40 | 41 | The result of the print statement is shown below: 42 | ```dart 43 | Hello 44 | ``` 45 | 46 | ## Example Code: Do While loop 47 | 48 | The do while loop will always execute the body of the loop at least once, even if the condition is false. 49 | The body of the loop prints the message "Hello" to the console. 50 | 51 | The do while loop is a control flow statement that allows you to execute a block of code repeatedly until a condition is met. 52 | The do while loop has two parts: 53 | 54 | * The body: This is executed repeatedly until the condition is false. 55 | * The condition: This is evaluated after each iteration of the loop. If the condition is true, the body of the loop is executed again. If the condition is false, the loop terminates. 56 | 57 | In this case, the body of the loop is executed first. 58 | The body of the loop prints the message "Hello" to the console. 59 | 60 | The condition is then evaluated. Since the value of isTrue is false, the loop terminates. 61 | 62 | 63 | ```dart 64 | void main() { 65 | 66 | bool isTrue = false; 67 | 68 | do { 69 | print ('Hello'); 70 | } while (isTrue) ; 71 | } 72 | ``` 73 | 74 | 75 | ## Example Output: 76 | 77 | The result of the print statement is shown below: 78 | ```dart 79 | Hello 80 | ``` 81 | -------------------------------------------------------------------------------- /ch05/ex5-5.md: -------------------------------------------------------------------------------- 1 | # 5.5 Adding a Class Mixin 2 | 3 | 4 | ## Example Code: 5 | 6 | The code provided defines four classes: SnickersOriginal, SnickersCrisp, ChocolateBar, and CandyBar. 7 | 8 | The SnickersOriginal mixin has the properties hasHazelnut, hasRice, and hasAlmond, which are all set to true. 9 | The SnickersCrisp mixin has the properties hasHazelnut and hasRice, which are both set to true. 10 | The hasAlmond property is not defined in the SnickersCrisp mixin. 11 | The ChocolateBar class has the property hasChocolate, which is set to true. 12 | The CandyBar class extends the ChocolateBar class and mixes in the SnickersOriginal mixin. 13 | The CandyBar class has the property ingredients, which is a list of strings. 14 | The CandyBar class constructor adds the strings "Chocolate", "Hazelnut", and "Rice" to the ingredients property. The getIngredients() method returns the ingredients property. 15 | The main() function creates an instance of the CandyBar class and calls the getIngredients() method. 16 | The getIngredients() method returns the ingredients property, which is then printed to the console. 17 | 18 | The CandyBar class mixes in the SnickersOriginal mixin, so it inherits the properties hasHazelnut and hasRice from the mixin. The CandyBar class does not override the hasAlmond property, so the value of hasAlmond is still false. This is why the ingredients property does not contain the string "Almonds". 19 | 20 | ```dart 21 | mixin SnickersOriginal { 22 | bool hasHazelnut = true; 23 | bool hasRice = false; 24 | bool hasAlmond = false; 25 | } 26 | 27 | mixin SnickersCrisp { 28 | bool hasHazelnut = true; 29 | bool hasRice = true; 30 | bool hasAlmond = false; 31 | } 32 | 33 | class ChocolateBar { 34 | bool hasChocolate = true; 35 | } 36 | 37 | class CandyBar extends ChocolateBar with SnickersOriginal { 38 | List ingredients = []; 39 | 40 | CandyBar() { 41 | if (hasChocolate) { 42 | ingredients.add('Chocolate'); 43 | } 44 | if (hasHazelnut) { 45 | ingredients.add('Hazelnut'); 46 | } 47 | if (hasRice) { 48 | ingredients.add('Rice'); 49 | } 50 | if (hasAlmond) { 51 | ingredients.add('Almonds'); 52 | } 53 | } 54 | 55 | List getIngredients() { 56 | return ingredients; 57 | } 58 | } 59 | 60 | void main() { 61 | var snickersOriginal = CandyBar(); 62 | print('Ingredients:'); 63 | snickersOriginal.getIngredients().forEach((ingredient) => print(ingredient)); 64 | } 65 | ``` 66 | 67 | 68 | ## Example Output: 69 | 70 | ```dart 71 | Ingredients: 72 | Chocolate 73 | Hazelnut 74 | Rice 75 | ``` 76 | -------------------------------------------------------------------------------- /ch10/ex10-5.md: -------------------------------------------------------------------------------- 1 | # 10.5 Using a Layout Builder 2 | 3 | # Example 4 | 5 | ```dart 6 | import 'package:flutter/material.dart'; 7 | 8 | void main() => runApp(const MyApp()); 9 | 10 | class MyApp extends StatelessWidget { 11 | const MyApp({Key? key}) : super(key: key); 12 | 13 | static const String _title = 'LayoutBuilder'; 14 | 15 | @override 16 | Widget build(BuildContext context) { 17 | return const MaterialApp( 18 | title: _title, 19 | home: MyStatelessWidget(), 20 | ); 21 | } 22 | } 23 | 24 | class MyStatelessWidget extends StatelessWidget { 25 | const MyStatelessWidget({Key? key}) : super(key: key); 26 | 27 | @override 28 | Widget build(BuildContext context) { 29 | return Scaffold( 30 | appBar: AppBar(title: const Text('LayoutBuilder Example')), 31 | body: LayoutBuilder( 32 | builder: (BuildContext context, BoxConstraints constraints) { 33 | // Restrict based on Width 34 | if (constraints.maxWidth > 800) { 35 | return _buildTripleContainers(); 36 | } else 37 | if (constraints.maxWidth > 600 && constraints.maxWidth<=800) { 38 | return _buildDoubleContainers(); 39 | } else { 40 | return _buildSingleContainer(); 41 | } 42 | }, 43 | ), 44 | ); 45 | } 46 | 47 | Widget _buildSingleContainer() { 48 | return Center( 49 | child: Container( 50 | height: 400.0, 51 | width: 100.0, 52 | color: Colors.red, 53 | ), 54 | ); 55 | } 56 | 57 | Widget _buildDoubleContainers() { 58 | return Center( 59 | child: Row( 60 | mainAxisAlignment: MainAxisAlignment.spaceEvenly, 61 | children: [ 62 | Container( 63 | height: 400.0, 64 | width: 100.0, 65 | color: Colors.yellow, 66 | ), 67 | Container( 68 | height: 400.0, 69 | width: 100.0, 70 | color: Colors.yellow, 71 | ), 72 | 73 | ], 74 | ), 75 | ); 76 | } 77 | 78 | Widget _buildTripleContainers() { 79 | return Center( 80 | child: Row( 81 | mainAxisAlignment: MainAxisAlignment.spaceEvenly, 82 | children: [ 83 | Container( 84 | height: 400.0, 85 | width: 100.0, 86 | color: Colors.green, 87 | ), 88 | Container( 89 | height: 400.0, 90 | width: 100.0, 91 | color: Colors.green, 92 | ), 93 | Container( 94 | height: 400.0, 95 | width: 100.0, 96 | color: Colors.green, 97 | ), 98 | ], 99 | ), 100 | ); 101 | } 102 | } 103 | 104 | ``` 105 | -------------------------------------------------------------------------------- /ch03/ex3-3.md: -------------------------------------------------------------------------------- 1 | # 3.3 Using optional parameters 2 | 3 | ## Example Code: Custom Delay using a Future 4 | 5 | The printGreetingNamed() function takes two optional named parameters: personName and clientId. 6 | The default value for personName is "Stranger" and the default value for clientId is 999. 7 | 8 | The first time the printGreetingNamed() function is called, no arguments are passed. 9 | The default values for personName and clientId are used. 10 | 11 | The second time the printGreetingNamed() function is called, the argument personName is passed with the value "Rich". 12 | The default value for clientId is used. 13 | 14 | The third time the printGreetingNamed() function is called, the arguments personName and clientId are passed with the values "Mary" and 001, respectively. 15 | 16 | The printGreetingNamed() function checks if the value of the personName parameter contains the string "Stranger". 17 | If it does, the function prints the message "Employee: $clientId Stranger danger". If it does not, the function prints the message "Employee: $clientId $personName". 18 | 19 | ```dart 20 | void main() { 21 | printGreetingNamed(); 22 | printGreetingNamed(personName: "Rich"); 23 | printGreetingNamed(personName: "Mary", clientId: 001); 24 | } 25 | 26 | void printGreetingNamed({String personName = 'Stranger', 27 | int clientId = 999}){ 28 | if (personName.contains('Stranger')) { 29 | print('Employee: $clientId Stranger danger '); 30 | } else { 31 | print('Employee: $clientId $personName '); 32 | } 33 | } 34 | 35 | ``` 36 | 37 | ## Example Output: 38 | ```dart 39 | Employee: 999 Stranger danger 40 | Employee: 999 Rich 41 | Employee: 001 Mary 42 | ``` 43 | 44 | 45 | ## Example Code: Positional Parameters 46 | 47 | The printGreetingPositional() function takes two positional parameters: personName and personSurname. 48 | The parameter personSurname is optional. 49 | 50 | The first time the printGreetingPositional() function is called, the argument personName is passed with the value "Rich". 51 | The argument personSurname is not passed. 52 | 53 | The second time the printGreetingPositional() function is called, the arguments personName and personSurname are passed with the values "Rich" and "Rose", respectively. 54 | 55 | The printGreetingPositional() function prints the value of the personName parameter. 56 | If the value of the personSurname parameter is not null, the function prints the value of the personSurname parameter. 57 | 58 | 59 | ```dart 60 | void main() { 61 | printGreetingPositional("Rich"); 62 | printGreetingPositional("Rich", "Rose"); 63 | } 64 | 65 | void printGreetingPositional(String personName, [String? personSurname]){ 66 | print(personName); 67 | if (personSurname != null){ 68 | print(personSurname); 69 | } 70 | } 71 | ``` 72 | 73 | ## Example Output: 74 | ```dart 75 | Rich 76 | Rich Rose 77 | ``` 78 | 79 | -------------------------------------------------------------------------------- /ch02/ex-for.md: -------------------------------------------------------------------------------- 1 | # 2.3 Using a For statement 2 | 3 | # Example Code: For loop 4 | 5 | The for loop iterates over the numbers from 0 to maxIterations (10), and prints the current number to the console on each iteration. 6 | 7 | The for loop is a control flow statement that allows you to execute a block of code repeatedly. 8 | 9 | The for loop has three parts: 10 | 11 | * The initializer: This is executed once, before the loop starts. 12 | * The condition: This is evaluated before each iteration of the loop. If the condition is true, the body of the loop is executed. If the condition is false, the loop terminates. 13 | * The increment: This is executed after each iteration of the loop. It is used to update the value of the loop variable. 14 | 15 | In this case, the initializer assigns the value 0 to the loop variable i. 16 | The condition checks if i is less than maxIterations. 17 | If it is, the body of the loop is executed. 18 | The increment increments the value of i by 1. 19 | 20 | The body of the loop prints the value of i to the console. 21 | 22 | ```dart 23 | void main() { 24 | int maxIterations = 10; 25 | for (var i = 0; i < maxIterations; i++) { 26 | print ('Iteration: $i'); 27 | } 28 | } 29 | ``` 30 | 31 | 32 | ## Example Output: 33 | 34 | The result of the print statement is shown below: 35 | ```dart 36 | Iteration: 0 37 | Iteration: 1 38 | Iteration: 2 39 | Iteration: 3 40 | Iteration: 4 41 | Iteration: 5 42 | Iteration: 6 43 | Iteration: 7 44 | Iteration: 8 45 | Iteration: 9 46 | ``` 47 | 48 | # Example Code: For Each loop 49 | 50 | The forEach method iterates over the elements of the daysOfWeek list and calls the print() function on each element. 51 | 52 | The forEach method is a method that is defined on iterable objects in Dart. 53 | It takes a function as an argument, and calls that function on each element of the iterable object. 54 | 55 | In this case, the forEach method is called on the daysOfWeek list. 56 | The function that is passed to the forEach method is the anonymous function print. 57 | An anonymous function is then used to call the print function which will output the value of the current element to the console. 58 | 59 | ```dart 60 | void main() { 61 | List daysOfWeek = ['Sunday', 'Monday', 'Tuesday']; 62 | 63 | daysOfWeek.forEach((print)); 64 | } 65 | ``` 66 | 67 | ## Example Output: 68 | 69 | The result of the print statement is shown below: 70 | ```dart 71 | Sunday 72 | Monday 73 | Tuesday 74 | ``` 75 | 76 | __Note__: 77 | The forEach also allows explicit access to each element. For example the example below exposes the index and the item to be processed as values. If you need to perform an action on each item or reference the index, then use this recipe: 78 | 79 | ```dart 80 | void main() { 81 | List daysOfWeek = ['Sunday', 'Monday', 'Tuesday']; 82 | 83 | daysOfWeek.asMap().forEach((index, item) => print('$index $item')); 84 | } 85 | ``` 86 | -------------------------------------------------------------------------------- /ch12/ex12-1.md: -------------------------------------------------------------------------------- 1 | # 12.1 Adding Page navigation with routes 2 | 3 | # Example 4 | 5 | ```dart 6 | import 'package:flutter/material.dart'; 7 | 8 | void main() { 9 | runApp(MyApp()); 10 | } 11 | 12 | class MyApp extends StatelessWidget { 13 | MyApp({Key? key}) : super(key: key); 14 | 15 | final List items = [ 16 | 'January', 17 | 'February', 18 | 'March', 19 | 'April', 20 | 'May', 21 | 'June', 22 | 'July', 23 | 'August', 24 | 'September', 25 | 'October', 26 | 'November', 27 | 'December' 28 | ]; 29 | 30 | @override 31 | Widget build(BuildContext context) { 32 | const title = 'MyAwesome App'; 33 | 34 | return MaterialApp( 35 | title: title, 36 | home: Scaffold( 37 | appBar: AppBar( 38 | title: const Text(title), 39 | ), 40 | body: ListView.builder( 41 | itemCount: items.length, 42 | itemBuilder: (context, index) { 43 | return MyListView(items[index]); 44 | }, 45 | ), 46 | ), 47 | ); 48 | } 49 | } 50 | 51 | class MyListView extends StatelessWidget { 52 | const MyListView(this.title); 53 | 54 | final String title; 55 | 56 | @override 57 | Widget build(BuildContext context) { 58 | return ListTile( 59 | title: Text(title), 60 | onTap: () { 61 | Navigator.push( 62 | context, 63 | MaterialPageRoute( 64 | builder: (context) => MyDetails(title), 65 | ), 66 | ); 67 | }, 68 | ); 69 | } 70 | } 71 | 72 | 73 | class MyDetails extends StatelessWidget { 74 | 75 | const MyDetails(this.itemTitle); 76 | 77 | final String itemTitle; 78 | 79 | @override 80 | Widget build(BuildContext context) { 81 | const title = 'Details Page'; 82 | 83 | return Scaffold( 84 | appBar: AppBar( 85 | title: const Text(title), 86 | ), 87 | body: SafeArea( 88 | top: false, 89 | bottom: false, 90 | child: Padding( 91 | padding: const EdgeInsets.all(8.0), 92 | child: Column( 93 | children: [ 94 | SizedBox( 95 | height: 338.0, 96 | width: 800.0, 97 | child: Card( 98 | clipBehavior: Clip.antiAlias, 99 | child: Column( 100 | crossAxisAlignment: CrossAxisAlignment.start, 101 | children: [ 102 | // Divider(), 103 | Padding( 104 | padding: const EdgeInsets.all(10.0), 105 | child: Text(itemTitle), 106 | ) 107 | ], 108 | ), 109 | ), 110 | ), 111 | ], 112 | ))), 113 | ); 114 | } 115 | } 116 | 117 | ``` 118 | -------------------------------------------------------------------------------- /ch17/ex17-6.md: -------------------------------------------------------------------------------- 1 | # 17.6 Adding sound effects to a Flame Game 2 | 3 | 4 | # Example: dependencies 5 | 6 | 7 | ```dart 8 | dependencies: 9 | flame: ^1.2.0 10 | flame_audio: ^1.2.0 11 | . 12 | . 13 | . 14 | flutter: 15 | assets: 16 | - assets/audio/ball.wav 17 | 18 | ``` 19 | 20 | # Example: code 21 | 22 | 23 | ```dart 24 | import 'dart:async'; 25 | import 'package:flame/flame.dart'; 26 | import 'package:flame/game.dart'; 27 | import 'package:flame/components.dart'; 28 | import 'package:flame_audio/flame_audio.dart'; 29 | import 'package:flutter/material.dart'; 30 | 31 | void main() async { 32 | WidgetsFlutterBinding.ensureInitialized(); 33 | await Flame.device.setPortrait(); 34 | final shapeGame = ShapesExample(); 35 | 36 | runApp(GameWidget(game: shapeGame)); 37 | } 38 | 39 | class ShapesExample extends FlameGame { 40 | @override 41 | Future onLoad() async { 42 | super.onLoad(); 43 | 44 | add(RectComponent(size[0], size[1])); 45 | } 46 | 47 | // @override 48 | // void update(double dt) { 49 | // super.update(dt); 50 | // } 51 | 52 | // @override 53 | // void render(Canvas canvas) { 54 | // super.render(canvas); 55 | // } 56 | } 57 | 58 | // Add a [Color] Rect on screen 59 | class RectComponent extends Component { 60 | double screenWidthMax = 0; 61 | double screenHeightMax = 0; 62 | double xStartPosition = 0; 63 | double yStartPosition = 0; 64 | static double xRectWidth = 50; 65 | static double yRectHeight = 50; 66 | bool xDirection = true; 67 | 68 | final paint = Paint() 69 | ..color = Colors.white 70 | ..strokeWidth = 4; 71 | 72 | RectComponent(this.screenWidthMax, this.screenHeightMax); 73 | 74 | @override 75 | Future onLoad() async { 76 | super.onLoad(); 77 | 78 | // Set the start position of the Rect - center of the screen 79 | xStartPosition = (screenWidthMax) / 2; 80 | yStartPosition = (screenHeightMax) / 2; 81 | 82 | // Load and cache the audio 83 | await FlameAudio.audioCache.load('ball.wav'); 84 | } 85 | 86 | @override 87 | void update(double dt) { 88 | super.update(dt); 89 | 90 | if (xDirection == true) { 91 | xStartPosition += 5; 92 | if (xStartPosition >= (screenWidthMax - xRectWidth)) { 93 | xDirection = false; 94 | FlameAudio.play('ball.wav'); 95 | } 96 | } 97 | 98 | if (xDirection == false) { 99 | xStartPosition -= 5; 100 | if (xStartPosition <= (0)) { 101 | xDirection = true; 102 | FlameAudio.play('ball.wav'); 103 | } 104 | } 105 | } 106 | 107 | @override 108 | void render(Canvas canvas) { 109 | super.render(canvas); 110 | 111 | canvas.drawRect( 112 | Rect.fromLTWH( 113 | xStartPosition, 114 | yStartPosition, 115 | xRectWidth, 116 | yRectHeight), 117 | paint); 118 | } 119 | } 120 | 121 | ``` 122 | 123 | *add link to audio file* 124 | 125 | 126 | 127 | 128 | 129 | -------------------------------------------------------------------------------- /ch10/ex10-6.md: -------------------------------------------------------------------------------- 1 | # 10.6 Getting screen dimensions with Media Query 2 | 3 | # Example 4 | 5 | ```dart 6 | import 'package:flutter/material.dart'; 7 | 8 | void main() { 9 | runApp(const MyApp()); 10 | } 11 | 12 | class MyApp extends StatelessWidget { 13 | const MyApp({Key? key}) : super(key: key); 14 | @override 15 | Widget build(BuildContext context) { 16 | const title = 'MediaQuery demo'; 17 | return MaterialApp( 18 | title: title, 19 | home: Scaffold( 20 | appBar: AppBar( 21 | title: const Text(title), 22 | ), 23 | body: const MyMediaQueryWidget(), 24 | ), 25 | ); 26 | } 27 | } 28 | 29 | class MyMediaQueryWidget extends StatelessWidget { 30 | const MyMediaQueryWidget({Key? key}) : super(key: key); 31 | @override 32 | Widget build(BuildContext context) { 33 | var screenSize = MediaQuery.of(context).size; 34 | if (screenSize.width > 600) { 35 | // Two Column 36 | return Column( 37 | crossAxisAlignment: CrossAxisAlignment.start, 38 | children: [ 39 | const Text( 40 | 'You can Fit Two columns here!', 41 | style: TextStyle(fontSize: 30, color: Colors.grey), 42 | ), 43 | const SizedBox(height: 10.0), 44 | Text( 45 | 'Screen Width: ${MediaQuery.of(context).size.width}', 46 | style: const TextStyle(fontSize: 20, color: Colors.grey), 47 | ), 48 | Text( 49 | 'Screen Height: ${MediaQuery.of(context).size.height}', 50 | style: const TextStyle(fontSize: 20, color: Colors.grey), 51 | ), 52 | Text( 53 | 'Aspect Ratio: ${MediaQuery.of(context).size.aspectRatio}', 54 | style: const TextStyle(fontSize: 20, color: Colors.grey), 55 | ), 56 | Text( 57 | 'Orientation: ${MediaQuery.of(context).orientation}', 58 | style: const TextStyle(fontSize: 20, color: Colors.grey), 59 | ), 60 | ], 61 | ); 62 | } else { 63 | return Column( 64 | crossAxisAlignment: CrossAxisAlignment.start, 65 | children: [ 66 | const Text( 67 | 'You can Fit One column here!', 68 | style: TextStyle(fontSize: 30, color: Colors.grey), 69 | ), 70 | const SizedBox(height: 10.0), 71 | Text( 72 | 'Screen Width: ${MediaQuery.of(context).size.width}', 73 | style: const TextStyle(fontSize: 20, color: Colors.grey), 74 | ), 75 | Text( 76 | 'Screen Height: ${MediaQuery.of(context).size.height}', 77 | style: const TextStyle(fontSize: 20, color: Colors.grey), 78 | ), 79 | Text( 80 | 'Aspect Ratio: ${MediaQuery.of(context).size.aspectRatio}', 81 | style: const TextStyle(fontSize: 20, color: Colors.grey), 82 | ), 83 | Text( 84 | 'Orientation: ${MediaQuery.of(context).orientation}', 85 | style: const TextStyle(fontSize: 20, color: Colors.grey), 86 | ), 87 | ], 88 | ); 89 | } 90 | } 91 | } 92 | 93 | ``` 94 | -------------------------------------------------------------------------------- /ch12/ex12-3.md: -------------------------------------------------------------------------------- 1 | # 12.3 Working with Tabs 2 | 3 | # Example 4 | 5 | ```dart 6 | import 'package:flutter/material.dart'; 7 | 8 | void main() => runApp(MyApp()); 9 | 10 | class MyApp extends StatelessWidget { 11 | @override 12 | Widget build(BuildContext context) { 13 | return MaterialApp( 14 | title: 'Flutter and Dart Cookbook Demo', 15 | debugShowCheckedModeBanner: false, 16 | theme: ThemeData( 17 | tabBarTheme: const TabBarTheme( 18 | labelColor: Colors.white, 19 | labelStyle: TextStyle(color: Colors.grey), 20 | // color for text 21 | ), 22 | primarySwatch: Colors.blue, 23 | ), 24 | home: const MyHomePage(title: 'Flutter and Dart Cookbook'), 25 | ); 26 | } 27 | } 28 | 29 | class MyHomePage extends StatelessWidget { 30 | final String title; 31 | const MyHomePage({ 32 | Key? key, 33 | required this.title, 34 | }) : super(key: key); 35 | @override 36 | Widget build(BuildContext context) { 37 | return Scaffold( 38 | backgroundColor: Colors.black, 39 | body: DefaultTabController( 40 | length: 4, 41 | child: Scaffold( 42 | appBar: AppBar( 43 | title: const Text('MyAwesomeTabBar'), 44 | bottom: const TabBar( 45 | // indicatorColor: Colors.black, 46 | tabs: [ 47 | Tab( 48 | icon: Icon(Icons.home, color: Colors.white), 49 | child: Text('Home', 50 | style: TextStyle(fontWeight: FontWeight.bold)), 51 | ), 52 | Tab( 53 | icon: Icon(Icons.account_balance, color: Colors.white), 54 | child: Text('Account', 55 | style: TextStyle(fontWeight: FontWeight.bold)), 56 | ), 57 | Tab( 58 | icon: Icon(Icons.calculate, color: Colors.white), 59 | child: Text('Payments', 60 | style: TextStyle(fontWeight: FontWeight.bold)), 61 | ), 62 | Tab( 63 | icon: Icon(Icons.credit_score, color: Colors.white), 64 | child: Text('Card', 65 | style: TextStyle(fontWeight: FontWeight.bold)), 66 | ), 67 | ], 68 | ), 69 | ), 70 | body: const TabBarView( 71 | children: [ 72 | SizedBox( 73 | child: Center( 74 | child: Text('Home Page Tab 1'), 75 | ), 76 | ), 77 | SizedBox( 78 | child: Center( 79 | child: Text('Account Page Tab 2'), 80 | ), 81 | ), 82 | SizedBox( 83 | child: Center( 84 | child: Text('Payments Page Tab 3'), 85 | ), 86 | ), 87 | SizedBox( 88 | child: Center( 89 | child: Text('Card Page Tab 4'), 90 | ), 91 | ), 92 | ], 93 | ), 94 | ), 95 | ), 96 | ); 97 | } 98 | } 99 | 100 | 101 | ``` 102 | -------------------------------------------------------------------------------- /ch10/ex10-3.md: -------------------------------------------------------------------------------- 1 | # 10.3 Identifying the host platform 2 | 3 | 4 | # Example 5 | 6 | ```dart 7 | import 'package:flutter/material.dart'; 8 | import 'dart:io' show Platform; 9 | import 'package:flutter/foundation.dart' show kIsWeb; 10 | 11 | void main() { 12 | runApp(const MyApp()); 13 | } 14 | 15 | class MyApp extends StatelessWidget { 16 | const MyApp({Key? key}) : super(key: key); 17 | 18 | @override 19 | Widget build(BuildContext context) { 20 | const title = 'Platform demo'; 21 | 22 | return MaterialApp( 23 | title: title, 24 | home: Scaffold( 25 | appBar: AppBar( 26 | title: const Text(title), 27 | ), 28 | body: const MyPlatformWidget(), 29 | ), 30 | ); 31 | } 32 | } 33 | 34 | class MyPlatformWidget extends StatelessWidget { 35 | const MyPlatformWidget({Key? key}) : super(key: key); 36 | 37 | bool get isMobileDevice => !kIsWeb && (Platform.isIOS || Platform.isAndroid); 38 | bool get isDesktopDevice => 39 | !kIsWeb && (Platform.isMacOS || Platform.isWindows || Platform.isLinux); 40 | bool get isMobileDeviceOrWeb => kIsWeb || isMobileDevice; 41 | bool get isDesktopDeviceOrWeb => kIsWeb || isDesktopDevice; 42 | 43 | bool get isAndroid => !kIsWeb && Platform.isAndroid; 44 | bool get isFuchsia => !kIsWeb && Platform.isFuchsia; 45 | bool get isIOS => !kIsWeb && Platform.isIOS; 46 | bool get isLinux => !kIsWeb && Platform.isLinux; 47 | bool get isMacOS => !kIsWeb && Platform.isMacOS; 48 | bool get isWindows => !kIsWeb && Platform.isWindows; 49 | 50 | @override 51 | Widget build(BuildContext context) { 52 | return Column( 53 | children: [ 54 | const Text( 55 | 'Web: $kIsWeb', 56 | style: TextStyle(fontSize: 20, color: Colors.grey), 57 | ), 58 | Text( 59 | 'Android: $isAndroid', 60 | style: const TextStyle(fontSize: 20, color: Colors.grey), 61 | ), 62 | Text( 63 | 'Fuchsia: $isFuchsia', 64 | style: const TextStyle(fontSize: 20, color: Colors.grey), 65 | ), 66 | Text( 67 | 'IOS: $isIOS', 68 | style: const TextStyle(fontSize: 20, color: Colors.grey), 69 | ), 70 | Text( 71 | 'Linux: $isLinux', 72 | style: const TextStyle(fontSize: 20, color: Colors.grey), 73 | ), 74 | Text( 75 | 'MacOS: $isMacOS', 76 | style: const TextStyle(fontSize: 20, color: Colors.grey), 77 | ), 78 | Text( 79 | 'Windows: $isWindows', 80 | style: const TextStyle(fontSize: 20, color: Colors.grey), 81 | ), 82 | Text( 83 | 'isMobileDevice: $isMobileDevice', 84 | style: const TextStyle(fontSize: 20, color: Colors.grey), 85 | ), 86 | Text( 87 | 'isDesktopDevice: $isDesktopDevice', 88 | style: const TextStyle(fontSize: 20, color: Colors.grey), 89 | ), 90 | Text( 91 | 'isMobileDeviceOrWeb: $isMobileDeviceOrWeb', 92 | style: const TextStyle(fontSize: 20, color: Colors.grey), 93 | ), 94 | Text( 95 | 'isDesktopDeviceOrWeb: $isDesktopDeviceOrWeb', 96 | style: const TextStyle(fontSize: 20, color: Colors.grey), 97 | ), 98 | ], 99 | ); 100 | } 101 | } 102 | 103 | ``` 104 | 105 | -------------------------------------------------------------------------------- /ch17/ex17-4.md: -------------------------------------------------------------------------------- 1 | # 17.4 Using the Flame graphic primitives 2 | 3 | 4 | # Example 5 | 6 | ```dart 7 | import 'dart:async'; 8 | import 'package:flame/flame.dart'; 9 | import 'package:flame/game.dart'; 10 | import 'package:flame/components.dart'; 11 | import 'package:flutter/material.dart'; 12 | 13 | void main() async { 14 | WidgetsFlutterBinding.ensureInitialized(); 15 | await Flame.device.setPortrait(); 16 | final shapeGame = ShapesExample(); 17 | 18 | runApp(GameWidget(game: shapeGame)); 19 | } 20 | 21 | class ShapesExample extends FlameGame { 22 | @override 23 | Future onLoad() async { 24 | super.onLoad(); 25 | 26 | add(RectComponent(size[0], size[1])); 27 | add(LineComponent(size[0], size[1])); 28 | add(CircleComponent(size[0], size[1])); 29 | } 30 | 31 | @override 32 | void update(double dt) { 33 | super.update(dt); 34 | } 35 | 36 | @override 37 | void render(Canvas canvas) { 38 | super.render(canvas); 39 | } 40 | } 41 | 42 | // Add a [Color] Rect on screen 43 | class RectComponent extends Component { 44 | final double screenWidth; 45 | final double screenHeight; 46 | double xStartPosition = 0; 47 | double yStartPosition = 0; 48 | static double xRectWidth = 50; 49 | static double yRectHeight = 50; 50 | 51 | final paint = Paint() 52 | ..color = Colors.white 53 | ..strokeWidth = 4; 54 | 55 | RectComponent(this.screenWidth, this.screenHeight); 56 | 57 | @override 58 | void update(double dt) { 59 | super.update(dt); 60 | xStartPosition = screenWidth / 2; 61 | yStartPosition = screenHeight / 2; 62 | } 63 | 64 | @override 65 | void render(Canvas canvas) { 66 | super.render(canvas); 67 | 68 | // xStartPos, yStartPos, xRectWidth, yRectHeight 69 | canvas.drawRect( 70 | Rect.fromLTWH(xStartPosition, yStartPosition, xRectWidth, yRectHeight), 71 | paint); 72 | } 73 | } 74 | 75 | // Add a [Color] Line on screen 76 | class LineComponent extends Component { 77 | final double screenWidth; 78 | final double screenHeight; 79 | double xLineP1 = 50; 80 | double yLineP1 = 50; 81 | double xLineP2 = 250; 82 | double yLineP2 = 150; 83 | 84 | final paint = Paint() 85 | ..color = Colors.white 86 | ..strokeWidth = 4; 87 | 88 | LineComponent(this.screenWidth, this.screenHeight); 89 | 90 | // @override 91 | // void update(double dt) { 92 | // super.update(dt); 93 | // } 94 | 95 | @override 96 | void render(Canvas canvas) { 97 | super.render(canvas); 98 | 99 | Offset p1 = Offset(xLineP1, yLineP1); 100 | Offset p2 = Offset(xLineP2, yLineP2); 101 | final paint = Paint() 102 | ..color = Colors.red 103 | ..strokeWidth = 4; 104 | canvas.drawLine(p1, p2, paint); 105 | } 106 | } 107 | 108 | class CircleComponent extends Component { 109 | final double screenWidth; 110 | final double screenHeight; 111 | double xP1 = 450; 112 | double yP1 = 350; 113 | 114 | CircleComponent(this.screenWidth, this.screenHeight); 115 | 116 | // @override 117 | // void update(double dt) { 118 | // super.update(dt); 119 | // } 120 | 121 | @override 122 | void render(Canvas canvas) { 123 | Offset p1 = Offset(xP1, yP1); 124 | double radius = 50; 125 | final paint = Paint() 126 | ..color = Colors.yellow 127 | ..strokeWidth = 4; 128 | canvas.drawCircle(p1, radius, paint); 129 | } 130 | } 131 | 132 | ``` 133 | 134 | -------------------------------------------------------------------------------- /ch17/ex17-7.md: -------------------------------------------------------------------------------- 1 | # 17.7 Adding Keyboard input 2 | 3 | 4 | # Example 5 | 6 | ```dart 7 | import 'dart:async'; 8 | import 'package:flame/flame.dart'; 9 | import 'package:flame/game.dart'; 10 | import 'package:flame/input.dart'; // Keyboard 11 | import 'package:flutter/services.dart'; // Keyboard 12 | import 'package:flame/components.dart'; 13 | import 'package:flutter/material.dart'; 14 | 15 | 16 | void main() async { 17 | WidgetsFlutterBinding.ensureInitialized(); 18 | await Flame.device.setPortrait(); 19 | final shapeGame = ShapesExample(); 20 | 21 | runApp(GameWidget(game: shapeGame)); 22 | } 23 | 24 | // Global key direction 25 | double xDelta = 0; 26 | 27 | class ShapesExample extends FlameGame 28 | with KeyboardEvents, HasCollisionDetection { 29 | @override 30 | Future onLoad() async { 31 | super.onLoad(); 32 | 33 | add(RectComponent(size[0], size[1])); 34 | } 35 | 36 | // @override 37 | // void update(double dt) { 38 | // super.update(dt); 39 | // } 40 | 41 | // @override 42 | // void render(Canvas canvas) { 43 | // super.render(canvas); 44 | // } 45 | 46 | @override 47 | KeyEventResult onKeyEvent( 48 | RawKeyEvent event, Set keysPressed) { 49 | final isKeyDown = event is RawKeyDownEvent; 50 | 51 | // final isDirectionKey = keysPressed.contains(LogicalKeyboardKey.keyA); 52 | 53 | if (isKeyDown && event.logicalKey == LogicalKeyboardKey.keyA) { 54 | xDelta = isKeyDown ? -1 : 0; 55 | } 56 | 57 | if (isKeyDown && event.logicalKey == LogicalKeyboardKey.keyD) { 58 | xDelta = isKeyDown ? 1 : 0; 59 | } 60 | 61 | if (isKeyDown && event.logicalKey == LogicalKeyboardKey.keyW) { 62 | xDelta = isKeyDown ? -1 : 0; 63 | } 64 | 65 | if (isKeyDown && event.logicalKey == LogicalKeyboardKey.keyS) { 66 | xDelta = isKeyDown ? 1 : 0; 67 | } 68 | 69 | return super.onKeyEvent(event, keysPressed); 70 | } 71 | } 72 | 73 | // Add a [Color] Rect on screen 74 | class RectComponent extends PositionComponent { 75 | final double screenWidth; 76 | final double screenHeight; 77 | static double xRectWidth = 50; 78 | static double yRectHeight = 50; 79 | double xStartPosition = 0; 80 | double yStartPosition = 0; 81 | int rectDirection = 1; 82 | 83 | final paint = Paint() 84 | ..color = Colors.white 85 | ..strokeWidth = 4; 86 | 87 | RectComponent(this.screenWidth, this.screenHeight); 88 | @override 89 | Future onLoad() async { 90 | super.onLoad(); 91 | xStartPosition = screenWidth / 2; 92 | yStartPosition = screenHeight / 2; 93 | } 94 | 95 | @override 96 | void update(double dt) { 97 | super.update(dt); 98 | 99 | // Going Left 100 | if (xDelta == -1) { 101 | // Check the screen boundary 102 | if (xStartPosition >= 0) { 103 | xStartPosition -= 5; 104 | } 105 | // ignore: avoid_print 106 | print('Go Left'); 107 | xDelta = 0; 108 | } else if (xDelta == 1) { 109 | // Check the screen boundary 110 | if (xStartPosition <= screenWidth) { 111 | xStartPosition += 5; 112 | } 113 | // ignore: avoid_print 114 | print('Go Right'); 115 | xDelta = 0; 116 | } 117 | } 118 | 119 | @override 120 | void render(Canvas canvas) { 121 | super.render(canvas); 122 | 123 | // xStartPos, yStartPos, xRectWidth, yRectHeight 124 | canvas.drawRect( 125 | Rect.fromLTWH(xStartPosition, yStartPosition, xRectWidth, yRectHeight), 126 | paint); 127 | } 128 | } 129 | 130 | ``` 131 | -------------------------------------------------------------------------------- /ch13/ex13-2.md: -------------------------------------------------------------------------------- 1 | # 13.2 Local Data Management 2 | 3 | # Example 4 | 5 | ```dart 6 | import 'package:flutter/material.dart'; 7 | import 'dart:convert'; 8 | 9 | void main() { 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyData { 14 | final String items = 15 | '{"data": [ { "title": "January" },{ "title": "February" },{ "title": "March" } ] }'; 16 | } 17 | 18 | class DataSeries { 19 | final List dataModel; 20 | 21 | DataSeries({required this.dataModel}); 22 | 23 | factory DataSeries.fromJson(Map json) { 24 | var list = json['data'] as List; 25 | 26 | List dataList = 27 | list.map((dataModel) => DataItem.fromJson(dataModel)).toList(); 28 | 29 | return DataSeries(dataModel: dataList); 30 | } 31 | } 32 | 33 | class DataItem { 34 | final String title; 35 | 36 | DataItem({required this.title}); 37 | 38 | factory DataItem.fromJson(Map json) { 39 | return DataItem(title: json['title']); 40 | } 41 | } 42 | 43 | class MyApp extends StatelessWidget { 44 | // This widget is the root of your application. 45 | @override 46 | Widget build(BuildContext context) { 47 | return MaterialApp( 48 | title: 'Json Data Demo', 49 | theme: ThemeData( 50 | primarySwatch: Colors.blue, 51 | ), 52 | home: const MyHomePage( 53 | title: 'MyAwesome App', 54 | key: null, 55 | ), 56 | ); 57 | } 58 | } 59 | 60 | class MyHomePage extends StatefulWidget { 61 | const MyHomePage({Key? key, required this.title}) : super(key: key); 62 | 63 | final String title; 64 | 65 | @override 66 | // Old Style 67 | // _MyHomePageState createState() => _MyHomePageState(); 68 | // New Style 69 | State createState() => _MyHomePageState(); 70 | } 71 | 72 | Future _loadLocalData() async { 73 | final MyData data = MyData(); 74 | 75 | return data.items; 76 | } 77 | 78 | class _MyHomePageState extends State { 79 | Future fetchQuests() async { 80 | String jsonString = await _loadLocalData(); 81 | final jsonResponse = json.decode(jsonString); 82 | DataSeries dataSeries = DataSeries.fromJson(jsonResponse); 83 | print(dataSeries.dataModel[0].title); 84 | 85 | return dataSeries; 86 | } 87 | 88 | late Future dataSeries; 89 | 90 | @override 91 | void initState() { 92 | super.initState(); 93 | dataSeries = fetchQuests(); 94 | } 95 | 96 | @override 97 | Widget build(BuildContext context) { 98 | return Scaffold( 99 | appBar: AppBar( 100 | // Here we take the value from the MyHomePage object that was created by 101 | // the App.build method, and use it to set our appbar title. 102 | title: Text(widget.title), 103 | ), 104 | body: FutureBuilder( 105 | future: dataSeries, 106 | builder: (context, snapshot) { 107 | if (snapshot.hasData) { 108 | return ListView.builder( 109 | itemCount: snapshot.data!.dataModel.length, 110 | itemBuilder: (BuildContext context, int index) { 111 | return ListTile( 112 | title: Text(snapshot.data!.dataModel[index].title), 113 | ); 114 | }, 115 | ); 116 | } else if (snapshot.hasError) { 117 | return Text("Error: ${snapshot.error}"); 118 | } 119 | return const CircularProgressIndicator(); 120 | }), 121 | ); 122 | } 123 | } 124 | 125 | ``` 126 | -------------------------------------------------------------------------------- /ch13/ex13-3.md: -------------------------------------------------------------------------------- 1 | # 13.3 Assets Folder - Consume a JSON file 2 | 3 | 4 | # Example 5 | 6 | ```dart 7 | flutter: 8 | uses-material-design: true 9 | assets: 10 | - assets/example2.json 11 | 12 | 13 | ``` 14 | 15 | # Example: pubspec.yaml 16 | 17 | ```dart 18 | flutter: 19 | uses-material-design: true 20 | 21 | # To add assets to your application, add an assets section, like this: 22 | assets: 23 | assets/example.json 24 | 25 | 26 | ``` 27 | 28 | # Example: Code 29 | 30 | ```dart 31 | import 'package:flutter/material.dart'; 32 | import 'dart:convert'; 33 | 34 | void main() { 35 | runApp(MyApp()); 36 | } 37 | 38 | class DataSeries { 39 | final List dataModel; 40 | DataSeries({required this.dataModel}); 41 | factory DataSeries.fromJson(Map json) { 42 | var list = json['data'] as List; 43 | List dataList = 44 | list.map((dataModel) => DataItem.fromJson(dataModel)).toList(); 45 | return DataSeries(dataModel: dataList); 46 | } 47 | } 48 | 49 | class DataItem { 50 | final String title; 51 | DataItem({required this.title}); 52 | factory DataItem.fromJson(Map json) { 53 | return DataItem(title: json['title']); 54 | } 55 | } 56 | 57 | class MyApp extends StatelessWidget { 58 | // This widget is the root of your application. 59 | @override 60 | Widget build(BuildContext context) { 61 | return MaterialApp( 62 | title: 'JSON Future Demo', 63 | theme: ThemeData( 64 | primarySwatch: Colors.blue, 65 | ), 66 | home: const MyHomePage( 67 | title: 'JSON Future Demo', 68 | key: null, 69 | ), 70 | ); 71 | } 72 | } 73 | 74 | class MyHomePage extends StatefulWidget { 75 | const MyHomePage({Key? key, required this.title}) : super(key: key); 76 | final String title; 77 | @override 78 | State createState() => _MyHomePageState(); 79 | } 80 | 81 | Future _loadAssetData() async { 82 | final AssetBundle rootBundle = _initRootBundle(); 83 | return await rootBundle.loadString('assets/example2.json'); 84 | } 85 | class _MyHomePageState extends State { 86 | Future fetchData() async { 87 | String jsonString = await _loadAssetData(); 88 | 89 | final jsonResponse = json.decode(jsonString); 90 | DataSeries dataSeries = DataSeries.fromJson(jsonResponse); 91 | print(dataSeries.dataModel[0].title); 92 | return dataSeries; 93 | } 94 | 95 | late Future dataSeries; 96 | @override 97 | void initState() { 98 | super.initState(); 99 | dataSeries = fetchData(); 100 | } 101 | 102 | @override 103 | Widget build(BuildContext context) { 104 | return Scaffold( 105 | appBar: AppBar( 106 | title: Text(widget.title), 107 | ), 108 | body: FutureBuilder( 109 | future: dataSeries, 110 | builder: (context, snapshot) { 111 | if (snapshot.hasData) { 112 | return ListView.builder( 113 | itemCount: snapshot.data!.dataModel.length, 114 | itemBuilder: (BuildContext context, int index) { 115 | return ListTile( 116 | title: Text(snapshot.data!.dataModel[index].title), 117 | ); 118 | }, 119 | ); 120 | } else if (snapshot.hasError) { 121 | return Text("Error: ${snapshot.error}"); 122 | } 123 | return const CircularProgressIndicator(); 124 | }), 125 | ); 126 | } 127 | } 128 | 129 | ``` 130 | 131 | # Example: Rootbundle 132 | 133 | ```dart 134 | Future _loadAssetData() async { 135 | return await rootBundle.loadString('assets/example.json'); 136 | } 137 | 138 | ``` 139 | -------------------------------------------------------------------------------- /ch12/ex12-2.md: -------------------------------------------------------------------------------- 1 | # 12.2 Implementing an navigational Drawer 2 | 3 | # Example 4 | 5 | ```dart 6 | import 'package:flutter/material.dart'; 7 | 8 | void main() { 9 | runApp(const MyApp()); 10 | } 11 | 12 | class MyApp extends StatelessWidget { 13 | const MyApp({Key? key}) : super(key: key); 14 | @override 15 | Widget build(BuildContext context) { 16 | const title = 'Drawer demo'; 17 | return MaterialApp( 18 | title: title, 19 | home: Scaffold( 20 | body: DemoPageOne(), 21 | ), 22 | ); 23 | } 24 | } 25 | 26 | class DemoPageOne extends StatelessWidget { 27 | @override 28 | Widget build(BuildContext context) { 29 | return Scaffold( 30 | appBar: AppBar( 31 | title: const Text("Page One"), 32 | ), 33 | body: const Center( 34 | child: Text('Demo: Page One'), 35 | ), 36 | drawer: const MyDrawerWidget(), 37 | ); 38 | } 39 | } 40 | 41 | class DemoPageTwo extends StatelessWidget { 42 | @override 43 | Widget build(BuildContext context) { 44 | return Scaffold( 45 | appBar: AppBar( 46 | title: const Text("Page Two"), 47 | ), 48 | body: const Center( 49 | child: Text('Demo: Page Two'), 50 | ), 51 | drawer: const MyDrawerWidget(), 52 | ); 53 | } 54 | } 55 | 56 | class DemoPageThree extends StatelessWidget { 57 | @override 58 | Widget build(BuildContext context) { 59 | return Scaffold( 60 | appBar: AppBar( 61 | title: const Text("Page Three"), 62 | ), 63 | body: const Center( 64 | child: Text('Demo: Page Three'), 65 | ), 66 | drawer: const MyDrawerWidget(), 67 | ); 68 | } 69 | } 70 | 71 | class DemoPageFour extends StatelessWidget { 72 | @override 73 | Widget build(BuildContext context) { 74 | return Scaffold( 75 | appBar: AppBar( 76 | title: const Text("Page Four"), 77 | ), 78 | body: const Center( 79 | child: Text('Demo: Page Four'), 80 | ), 81 | endDrawer: const MyDrawerWidget(), 82 | ); 83 | } 84 | } 85 | 86 | class MyDrawerWidget extends StatelessWidget { 87 | const MyDrawerWidget({Key? key}) : super(key: key); 88 | @override 89 | Widget build(BuildContext context) { 90 | return Drawer( 91 | child: ListView( 92 | children: [ 93 | const DrawerHeader( 94 | child: Icon(Icons.home, size: 35), 95 | ), 96 | ListTile( 97 | leading: const Icon(Icons.home), 98 | title: const Text('Drawer Item #1'), 99 | onTap: () { 100 | Navigator.of(context).push( 101 | MaterialPageRoute(builder: (context) => DemoPageOne()), 102 | ); 103 | }, 104 | ), 105 | ListTile( 106 | leading: const Icon(Icons.info), 107 | title: const Text('Drawer Item #2'), 108 | onTap: () { 109 | Navigator.of(context).push( 110 | MaterialPageRoute(builder: (context) => DemoPageTwo()), 111 | ); 112 | }, 113 | ), 114 | ListTile( 115 | leading: const Icon(Icons.favorite), 116 | title: const Text('Drawer Item #3'), 117 | onTap: () { 118 | Navigator.of(context).push( 119 | MaterialPageRoute(builder: (context) => DemoPageThree()), 120 | ); 121 | }), 122 | ListTile( 123 | leading: const Icon(Icons.list), 124 | title: const Text('Drawer Item #4'), 125 | onTap: () { 126 | Navigator.of(context).push( 127 | MaterialPageRoute(builder: (context) => DemoPageFour()), 128 | ); 129 | }), 130 | ], 131 | ), 132 | ); 133 | } 134 | } 135 | 136 | 137 | ``` 138 | -------------------------------------------------------------------------------- /ch01/ex-print.md: -------------------------------------------------------------------------------- 1 | # 1.6 Using a Print statement 2 | 3 | ## Example Code 1: 4 | 5 | The print() function is used to print text to the console. 6 | In this case, the text that is printed is "Hello World!". 7 | 8 | The print() function is a built-in function in Dart. 9 | It can be used to print any type of data, including strings, numbers, and objects. 10 | 11 | ```dart 12 | void main() { 13 | 14 | print('Hello World!'); 15 | } 16 | 17 | ``` 18 | 19 | ## Example Output: 20 | 21 | The result of the print statement is shown below: 22 | 23 | ```dart 24 | Hello World! 25 | ``` 26 | 27 | ## Example Code 2: 28 | 29 | The variable intVariable is declared as an integer and is assigned the value of 10. 30 | The print() function will then print the value of intVariable, which is 10. 31 | 32 | The variable boolVariable is declared as a variable and is assigned the value of true. 33 | The print() function will then print the value of boolVariable, which is true. 34 | 35 | The second print() statement uses string interpolation to print the value of intVariable. 36 | String interpolation is a Dart feature that allows you to insert expressions into strings. 37 | 38 | ```dart 39 | void main() { 40 | 41 | int intVariable = 10; 42 | var boolVariable = true; 43 | 44 | print(intVariable); 45 | print('$intVariable'); 46 | print('The bool variable is $boolVariable'); 47 | } 48 | 49 | ``` 50 | 51 | 52 | ## Example Output: 53 | 54 | The result of the print statement is shown below: 55 | 56 | ```dart 57 | 10 58 | 10 59 | The bool variable is true 60 | ``` 61 | 62 | ## Example Code 3: 63 | 64 | The code creates a JSON value, decodes it, and then prints the results. 65 | The first line imports the dart:convert library, which contains functions for converting between JSON and Dart objects. 66 | The next few lines create a JSON value. 67 | The jsonEncode() function is used to encode a Dart object into a JSON string. 68 | The json.encode() function is a shorthand for jsonEncode(). 69 | 70 | The Map data structure is used to create JSON objects in Dart. 71 | The keys of a Map are strings, and the values can be of any type. 72 | 73 | The data variable is created with two key-value pairs. 74 | The key title is encoded to the string Star Wars and the key year is encoded to the integer 1979. 75 | 76 | The next line decodes the JSON value. 77 | The jsonDecode() function is used to decode a JSON string into a Dart object. 78 | The data.toString() function converts the data variable to a string. 79 | 80 | The items variable is created with the decoded JSON value. 81 | The next few lines print the results of the decoding. 82 | The print() function is used to print text to the console. 83 | 84 | The first print() statement prints the entire decoded JSON object. 85 | The second print() statement prints the value of the title key. 86 | The third print() statement uses string interpolation to print the value of the title key. 87 | String interpolation is a Dart feature that allows you to insert expressions into strings. 88 | 89 | The fourth print() statement also uses string interpolation to print the value of the title key. 90 | 91 | ```dart 92 | import 'dart:convert'; 93 | 94 | void main() { 95 | // Create JSON value 96 | Map data = { 97 | jsonEncode('title'): json.encode('Star Wars'), 98 | jsonEncode('year'): json.encode(1979) 99 | }; 100 | 101 | // Decode the JSON 102 | Map items = json.decode(data.toString()); 103 | 104 | print(items); 105 | print(items['title']); 106 | print("This is the title: $items['title']"); 107 | print('This is the title: ${items['title']}'); 108 | } 109 | ``` 110 | 111 | 112 | ## Example Output: 113 | 114 | The result of the print statement is shown below: 115 | 116 | ```dart 117 | {title: Star Wars, year: 1979} 118 | Star Wars 119 | This is the title: {title: Star Wars, year: 1979}['title'] 120 | This is the title: Star Wars 121 | ``` 122 | -------------------------------------------------------------------------------- /ch09/ex9-7.md: -------------------------------------------------------------------------------- 1 | # 9.7 Using a Column 2 | 3 | 4 | # Example 5 | 6 | ```dart 7 | import 'package:flutter/material.dart'; 8 | 9 | void main() => runApp(const MyApp()); 10 | 11 | class MyApp extends StatelessWidget { 12 | const MyApp({Key? key}) : super(key: key); 13 | static const String _title = 'Center Widget Demo'; 14 | @override 15 | Widget build(BuildContext context) { 16 | return const MaterialApp( 17 | title: _title, 18 | home: MyStatelessWidget(), 19 | ); 20 | } 21 | } 22 | 23 | class MyStatelessWidget extends StatelessWidget { 24 | const MyStatelessWidget({Key? key}) : super(key: key); 25 | @override 26 | Widget build(BuildContext context) { 27 | return Scaffold( 28 | appBar: AppBar(title: const Text('Center Example')), 29 | body: _buildCenterWidget(), 30 | ); 31 | } 32 | 33 | Widget _buildCenterWidget() { 34 | return Column( 35 | children: [ 36 | const SizedBox(height: 10.0), 37 | const Center( 38 | child: Text("Top Five Spoken Languages - 2022", 39 | style: TextStyle(fontSize: 30, color: Colors.grey))), 40 | const SizedBox(height: 20.0), 41 | SingleChildScrollView( 42 | scrollDirection: Axis.horizontal, 43 | child: 44 | Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ 45 | Row(children: [ 46 | const SizedBox( 47 | width: 100.0, 48 | child: Text("English"), 49 | ), 50 | Container( 51 | width: 600.0, 52 | color: Colors.green, 53 | child: const Center( 54 | child: Text("1.3 Billion", 55 | style: TextStyle(fontSize: 18, color: Colors.white))), 56 | ), 57 | ]), 58 | const SizedBox(height: 10.0), 59 | Row(children: [ 60 | const SizedBox( 61 | width: 100.0, 62 | child: Text("Mandarin"), 63 | ), 64 | Container( 65 | width: 550.0, 66 | color: Colors.orange, 67 | child: const Center( 68 | child: Text("1 Billion", 69 | style: TextStyle(fontSize: 18, color: Colors.white))), 70 | ), 71 | ]), 72 | const SizedBox(height: 10.0), 73 | Row(children: [ 74 | const SizedBox( 75 | width: 100.0, 76 | child: Text("Hindi"), 77 | ), 78 | Container( 79 | width: 300.0, 80 | color: Colors.pink, 81 | child: const Center( 82 | child: Text("600 Million", 83 | style: TextStyle(fontSize: 18, color: Colors.white))), 84 | ), 85 | ]), 86 | const SizedBox(height: 10.0), 87 | Row(children: [ 88 | const SizedBox( 89 | width: 100.0, 90 | child: Text("Spanish"), 91 | ), 92 | Container( 93 | width: 280.0, 94 | color: Colors.cyan, 95 | child: const Center( 96 | child: Text("540 Million", 97 | style: TextStyle(fontSize: 18, color: Colors.white))), 98 | ), 99 | ]), 100 | const SizedBox(height: 10.0), 101 | Row(children: [ 102 | const SizedBox( 103 | width: 100.0, 104 | child: Text("Arabic"), 105 | ), 106 | Container( 107 | width: 140.0, 108 | color: Colors.deepPurple, 109 | child: const Center( 110 | child: Text("270 Million", 111 | style: TextStyle(fontSize: 18, color: Colors.white))), 112 | ), 113 | ]), 114 | ]), 115 | ) 116 | ], 117 | ); 118 | } 119 | } 120 | 121 | 122 | ``` 123 | -------------------------------------------------------------------------------- /ch11/ex11-6.md: -------------------------------------------------------------------------------- 1 | # 11.6 Adding a SliverList 2 | 3 | ## Example 4 | 5 | ```dart 6 | import 'package:flutter/material.dart'; 7 | 8 | class CarItem { 9 | final String title; 10 | final String subtitle; 11 | final String url; 12 | CarItem({ 13 | required this.title, 14 | required this.subtitle, 15 | required this.url, 16 | }); 17 | } 18 | 19 | class ListDataItems { 20 | final List carItems = [ 21 | CarItem( 22 | title: '911 Cabriolet', 23 | subtitle: '911 Carrera Cabriolet Porsche', 24 | url: 'https://oreil.ly/m3OXC'), 25 | CarItem( 26 | title: '718 Spyder', 27 | subtitle: '718 Spyder Porsche', 28 | url: 'https://oreil.ly/hca-6'), 29 | CarItem( 30 | title: '718 Boxster T', 31 | subtitle: '718 Boxster T Porsche', 32 | url: 'https://oreil.ly/Ws4EX'), 33 | CarItem( 34 | title: 'Cayenne', 35 | subtitle: 'Cayenne S Porsche', 36 | url: 'https://oreil.ly/gwvnL'), 37 | CarItem( 38 | title: '911 Cabriolet', 39 | subtitle: '911 Carrera Cabriolet Porsche', 40 | url: 'https://oreil.ly/m3OXC'), 41 | CarItem( 42 | title: '718 Spyder', 43 | subtitle: '718 Spyder Porsche', 44 | url: 'https://oreil.ly/hca-6'), 45 | CarItem( 46 | title: '718 Boxster T', 47 | subtitle: '718 Boxster T Porsche', 48 | url: 'https://oreil.ly/Ws4EX'), 49 | CarItem( 50 | title: 'Cayenne', 51 | subtitle: 'Cayenne S Porsche', 52 | url: 'https://oreil.ly/gwvnL'), 53 | CarItem( 54 | title: '911 Cabriolet', 55 | subtitle: '911 Carrera Cabriolet Porsche', 56 | url: 'https://oreil.ly/m3OXC'), 57 | CarItem( 58 | title: '718 Spyder', 59 | subtitle: '718 Spyder Porsche', 60 | url: 'https://oreil.ly/hca-6'), 61 | CarItem( 62 | title: '718 Boxster T', 63 | subtitle: '718 Boxster T Porsche', 64 | url: 'https://oreil.ly/Ws4EX'), 65 | CarItem( 66 | title: 'Cayenne', 67 | subtitle: 'Cayenne S Porsche', 68 | url: 'https://oreil.ly/gwvnL'), 69 | ]; 70 | ListDataItems(); 71 | } 72 | 73 | void main() => runApp(MyApp()); 74 | 75 | class MyApp extends StatelessWidget { 76 | @override 77 | Widget build(BuildContext context) { 78 | return MaterialApp( 79 | title: 'SliverList Widget Demo', 80 | debugShowCheckedModeBanner: false, 81 | theme: ThemeData( 82 | primarySwatch: Colors.blue, 83 | ), 84 | home: const MyHomePage(title: 'Flutter and Dart Cookbook'), 85 | ); 86 | } 87 | } 88 | 89 | class MyHomePage extends StatelessWidget { 90 | final String title; 91 | const MyHomePage({ 92 | Key? key, 93 | required this.title, 94 | }) : super(key: key); 95 | @override 96 | Widget build(BuildContext context) { 97 | return Scaffold( 98 | backgroundColor: Colors.grey[300], 99 | body: CustomScrollView( 100 | slivers: [ 101 | const SliverAppBar( 102 | leading: Icon(Icons.menu), 103 | title: Text('MyAwesome App'), 104 | expandedHeight: 300, 105 | collapsedHeight: 150, 106 | floating: false, 107 | ), 108 | // Next, create a SliverList 109 | MySliverList(), 110 | ], // End 111 | ), 112 | ); 113 | } 114 | } 115 | 116 | class MySliverList extends StatelessWidget { 117 | MySliverList({Key? key}) : super(key: key); 118 | final ListDataItems item = ListDataItems(); 119 | @override 120 | Widget build(BuildContext context) { 121 | return // Next, create a SliverList 122 | SliverList( 123 | // Use a delegate to build items as they're scrolled on-screen. 124 | delegate: SliverChildBuilderDelegate( 125 | (context, index) => ListTile( 126 | leading: CircleAvatar( 127 | backgroundImage: NetworkImage(item.carItems[index].url), 128 | ), 129 | title: Text(item.carItems[index].title), 130 | subtitle: Text(item.carItems[index].subtitle), 131 | ), 132 | // Builds 1000 ListTiles 133 | childCount: item.carItems.length, 134 | ), 135 | ); 136 | } 137 | } 138 | ``` 139 | -------------------------------------------------------------------------------- /ch15/ex15-9.md: -------------------------------------------------------------------------------- 1 | # 15.9 Reading data from Cloud Firestore 2 | 3 | 4 | # Example: Add packages 5 | 6 | ```console 7 | flutter pub add firebase_core 8 | flutter pub add cloud_firestore 9 | 10 | ``` 11 | 12 | # Example: Firebase Essentials II 13 | 14 | ```dart 15 | import 'package:cloud_firestore/cloud_firestore.dart'; 16 | import 'package:firebase_core/firebase_core.dart'; 17 | import 'package:flutter/foundation.dart'; 18 | import 'package:flutter/material.dart'; 19 | import 'firebase_options.dart'; 20 | 21 | void main() async { 22 | await Firebase.initializeApp( 23 | options: DefaultFirebaseOptions.currentPlatform, 24 | ); 25 | if (kDebugMode) { 26 | try { 27 | FirebaseFirestore.instance.useFirestoreEmulator('localhost', 8080); 28 | } catch (e) { 29 | // ignore: avoid_print 30 | print(e); 31 | } 32 | } 33 | runApp(const MyApp()); 34 | } 35 | 36 | class MyApp extends StatelessWidget { 37 | const MyApp({Key? key}) : super(key: key); 38 | // This widget is the root of your application. 39 | @override 40 | Widget build(BuildContext context) { 41 | return MaterialApp( 42 | title: 'Firestore Demo', 43 | theme: ThemeData( 44 | primarySwatch: Colors.blue, 45 | ), 46 | home: const MyHomePage(title: 'Flutter Firestore Database: Read'), 47 | ); 48 | } 49 | } 50 | 51 | class MyHomePage extends StatefulWidget { 52 | const MyHomePage({Key? key, required this.title}) : super(key: key); 53 | final String title; 54 | @override 55 | State createState() => _MyHomePageState(); 56 | } 57 | 58 | class _MyHomePageState extends State { 59 | @override 60 | Widget build(BuildContext context) => Scaffold( 61 | appBar: AppBar( 62 | // Here we take the value from the MyHomePage object that was created by 63 | // the App.build method, and use it to set our AppBar title. 64 | title: Text(widget.title), 65 | ), 66 | body: StreamBuilder>( 67 | builder: (context, snapshot) { 68 | if (snapshot.hasError) { 69 | return const Text('Unable to read Cloud Firestore'); 70 | } else if (snapshot.hasData) { 71 | final dbteams = snapshot.data!; 72 | return ListView(children: dbteams.map(buildTeam).toList()); 73 | } else { 74 | return const Center( 75 | child: CircularProgressIndicator(), 76 | ); 77 | } 78 | }, 79 | stream: readTeams(), 80 | ), 81 | ); 82 | Widget buildTeam(Team team) => ListTile( 83 | leading: const CircleAvatar(child: Text('Prem')), 84 | title: Text(team.name), 85 | subtitle: Text(team.location), 86 | ); 87 | Future createTeam({required String name, required String location}) async { 88 | // Write to the Cloud Firestore database 89 | final docTeam = FirebaseFirestore.instance.collection('Teams').doc(); 90 | final teamJSON = { 91 | 'name': name, 92 | 'location': location, 93 | }; 94 | // Create the document and write data 95 | await docTeam.set(teamJSON); 96 | // Add: import 'package:flutter/foundation.dart'; 97 | // Production Debug statement 98 | if (kDebugMode) { 99 | print("Database Write!"); 100 | } 101 | } 102 | 103 | Stream> readTeams() => FirebaseFirestore.instance 104 | .collection('teams') 105 | .snapshots() 106 | .map((snapshot) => 107 | snapshot.docs.map((doc) => Team.fromJson(doc.data())).toList()); 108 | } 109 | 110 | class Team { 111 | // String id; 112 | final String name; 113 | final String location; 114 | Team({ 115 | // this.id = '', 116 | required this.name, 117 | required this.location, 118 | }); 119 | Map toJson() => { 120 | // 'id': id, 121 | 'name': name, 122 | 'location': location, 123 | }; 124 | static Team fromJson(Map json) => Team( 125 | // id: json['id'], 126 | name: json['name'], 127 | location: json['location']); 128 | } 129 | ``` 130 | 131 | ## Example: Emulator 132 | 133 | ```dart 134 | if (kDebugMode) { 135 | try { 136 | FirebaseFirestore.instance.useFirestoreEmulator('localhost', 8080); 137 | } catch (e) { 138 | print(e); 139 | } 140 | } 141 | 142 | ``` 143 | -------------------------------------------------------------------------------- /ch07/ex7-5.md: -------------------------------------------------------------------------------- 1 | # 7.5 Refactoring Flutter Widgets 2 | 3 | 4 | # Example Code: Original 5 | 6 | 7 | The code provided defines a Flutter application with an image widget. 8 | 9 | The MyApp class is a stateless widget. 10 | It defines the title of the application and the home screen. 11 | The home screen is a Scaffold widget with an AppBar and a body. 12 | The body is a Container widget with an Image.network widget as its child. 13 | The Image.network widget loads the image from the specified URL. 14 | 15 | ```dart 16 | import 'package:flutter/material.dart'; 17 | void main() { 18 | runApp(const MyApp()); 19 | } 20 | class MyApp extends StatelessWidget { 21 | const MyApp({Key? key}) : super(key: key); 22 | 23 | @override 24 | Widget build(BuildContext context) { 25 | const title = 'Image Widget'; 26 | return MaterialApp( 27 | title: title, 28 | home: Scaffold( 29 | appBar: AppBar( 30 | title: const Text(title), 31 | ), 32 | body: Container( 33 | width: 200, 34 | height: 180, 35 | color: Colors.black, 36 | child: Column( 37 | children: [ 38 | Image.network('https://oreil.ly/O4PEn'), 39 | const Text( 40 | 'itemTitle', 41 | style: TextStyle(fontSize: 20, color: Colors.white), 42 | ), 43 | const Text( 44 | 'itemSubTitle', 45 | style: TextStyle(fontSize: 16, color: Colors.grey), 46 | ), 47 | ], 48 | ), 49 | ), 50 | ), 51 | ); 52 | } 53 | } 54 | ``` 55 | 56 | 57 | 58 | # Example Code: Refactored 59 | 60 | The code provided defines a Flutter application with an image widget and a container widget. 61 | 62 | The DataItem class defines a data item with three properties: title, subtitle, and url. 63 | The DataView class defines a data view with a single property: item. 64 | The MyContainerWidget class is a stateless widget that contains an image widget and two text widgets. 65 | The image widget is loaded from the URL specified in the item.url property of the DataView class. 66 | The text widgets display the item.title and item.subtitle properties of the DataView class. 67 | 68 | ```dart 69 | import 'package:flutter/material.dart'; 70 | 71 | void main() { 72 | runApp(const MyApp()); 73 | } 74 | 75 | class MyApp extends StatelessWidget { 76 | const MyApp({Key? key}) : super(key: key); 77 | 78 | @override 79 | Widget build(BuildContext context) { 80 | const title = 'Image Widget'; 81 | 82 | return MaterialApp( 83 | title: title, 84 | home: Scaffold( 85 | appBar: AppBar( 86 | title: const Text(title), 87 | ), 88 | body: MyContainerWidget(), 89 | ), 90 | ); 91 | } 92 | } 93 | 94 | class DataItem { 95 | final String title; 96 | final String subtitle; 97 | final String url; 98 | 99 | const DataItem({ 100 | required this.title, 101 | required this.subtitle, 102 | required this.url, 103 | }); 104 | } 105 | 106 | class DataView { 107 | final DataItem item = const DataItem( 108 | title: 'Hello', 109 | subtitle: 'subtitle', 110 | url: 'https://oreil.ly/O4PEn'); 111 | } 112 | 113 | class MyContainerWidget extends StatelessWidget { 114 | MyContainerWidget({Key? key}) : super(key: key); 115 | 116 | final DataView data = DataView(); 117 | 118 | @override 119 | Widget build(BuildContext context) { 120 | return Container( 121 | width: 200, 122 | height: 180, 123 | color: Colors.black, 124 | child: Column( 125 | children: [ 126 | Image.network(data.item.url), 127 | Text( 128 | data.item.title, 129 | style: const TextStyle(fontSize: 20, color: Colors.white), 130 | ), 131 | Text( 132 | data.item.subtitle, 133 | style: const TextStyle(fontSize: 16, color: Colors.grey), 134 | ), 135 | ], 136 | ), 137 | ); 138 | } 139 | } 140 | 141 | ``` 142 | 143 | -------------------------------------------------------------------------------- /ch12/ex12-6.md: -------------------------------------------------------------------------------- 1 | # 12.6 Adding Page Navigation with Routes (Declarative) 2 | 3 | ```dart 4 | import 'package:flutter/material.dart'; 5 | 6 | void main() => runApp(const MyApp()); 7 | 8 | class MyApp extends StatelessWidget { 9 | const MyApp({super.key}); 10 | @override 11 | Widget build(BuildContext context) { 12 | return MaterialApp( 13 | title: 'Flutter Code Sample for Navigator', 14 | // MaterialApp contains our top-level Navigator 15 | initialRoute: '/signup', 16 | routes: { 17 | '/': (BuildContext context) => const HomePage(), 18 | '/signup': (BuildContext context) => const SignUpPage(), 19 | }, 20 | ); 21 | } 22 | } 23 | 24 | class HomePage extends StatelessWidget { 25 | const HomePage({super.key}); 26 | @override 27 | Widget build(BuildContext context) { 28 | return DefaultTextStyle( 29 | style: Theme.of(context).textTheme.headline4!, 30 | child: Container( 31 | color: Colors.white, 32 | alignment: Alignment.center, 33 | child: const Text('Home Page'), 34 | ), 35 | ); 36 | } 37 | } 38 | 39 | class SignUpPage extends StatelessWidget { 40 | const SignUpPage({super.key}); 41 | @override 42 | Widget build(BuildContext context) { 43 | // SignUpPage builds its own Navigator, which ends up being a nested 44 | // Navigator in our app. 45 | return Navigator( 46 | initialRoute: 'signup/personal_info', 47 | onGenerateRoute: (RouteSettings settings) { 48 | WidgetBuilder builder; 49 | switch (settings.name) { 50 | case 'signup/personal_info': 51 | // Assume CollectPersonalInfoPage collects personal info and then 52 | // navigates to 'signup/choose_credentials'. 53 | builder = (BuildContext context) => const CollectPersonalInfoPage(); 54 | break; 55 | case 'signup/choose_credentials': 56 | // Assume ChooseCredentialsPage collects new credentials and then 57 | // invokes 'onSignupComplete()'. 58 | builder = (BuildContext _) => ChooseCredentialsPage( 59 | onSignupComplete: () { 60 | // Referencing Navigator.of(context) from here refers to the 61 | // top-level Navigator because SignUpPage is above the 62 | // nested Navigator that it created. Therefore, this pop() 63 | // will pop the entire "sign-up" journey and return to the 64 | // "" route, AKA HomePage. 65 | Navigator.of(context).pop(); 66 | }, 67 | ); 68 | break; 69 | default: 70 | throw Exception('Invalid route: ${settings.name}'); 71 | } 72 | return MaterialPageRoute(builder: builder, settings: settings); 73 | }, 74 | ); 75 | } 76 | } 77 | 78 | class ChooseCredentialsPage extends StatelessWidget { 79 | const ChooseCredentialsPage({ 80 | super.key, 81 | required this.onSignupComplete, 82 | }); 83 | final VoidCallback onSignupComplete; 84 | @override 85 | Widget build(BuildContext context) { 86 | return GestureDetector( 87 | onTap: onSignupComplete, 88 | child: DefaultTextStyle( 89 | style: Theme.of(context).textTheme.headline4!, 90 | child: Container( 91 | color: Colors.pinkAccent, 92 | alignment: Alignment.center, 93 | child: const Text('Choose Credentials Page'), 94 | ), 95 | ), 96 | ); 97 | } 98 | } 99 | 100 | class CollectPersonalInfoPage extends StatelessWidget { 101 | const CollectPersonalInfoPage({super.key}); 102 | @override 103 | Widget build(BuildContext context) { 104 | return DefaultTextStyle( 105 | style: Theme.of(context).textTheme.headline4!, 106 | child: Container( 107 | color: Colors.white, 108 | child: Column( 109 | crossAxisAlignment: CrossAxisAlignment.start, 110 | children: [ 111 | const Text( 112 | "Name: Max, Address: Fury Road", 113 | style: TextStyle(fontSize: 20, color: Colors.black87), 114 | ), 115 | const SizedBox(height: 10.0), 116 | GestureDetector( 117 | onTap: () { 118 | // This moves from the personal info page to the credentials page, 119 | // replacing this page with that one. 120 | Navigator.of(context) 121 | .pushReplacementNamed('signup/choose_credentials'); 122 | }, 123 | child: const SizedBox( 124 | child: Text( 125 | 'Link: Page', 126 | style: TextStyle( 127 | fontSize: 20, 128 | color: Colors.blue, 129 | decoration: TextDecoration.underline), 130 | ), 131 | ), 132 | ), 133 | ], 134 | ), 135 | ), 136 | ); 137 | } 138 | } 139 | 140 | ``` 141 | -------------------------------------------------------------------------------- /ch15/ex15-6.md: -------------------------------------------------------------------------------- 1 | # 15.6 Adding Firebase Authentication to Flutter 2 | 3 | 4 | # Example: Authentication Image 5 | 6 | *add link for image* 7 | 8 | # Example: Authentication code 9 | 10 | ```dart 11 | 12 | import 'dart:html'; 13 | import 'package:flutter/material.dart'; 14 | import 'package:flutter/foundation.dart'; 15 | import 'package:firebase_auth/firebase_auth.dart'; 16 | import 'package:firebase_core/firebase_core.dart'; 17 | import 'firebase_options.dart'; 18 | 19 | void main() async { 20 | await Firebase.initializeApp( 21 | options: DefaultFirebaseOptions.currentPlatform, 22 | ); 23 | if (kDebugMode) { 24 | try { 25 | await FirebaseAuth.instance.useAuthEmulator('localhost', 9099); 26 | } catch (e) { 27 | print(e); 28 | } 29 | } 30 | runApp(const MyApp()); 31 | } 32 | 33 | class MyApp extends StatelessWidget { 34 | const MyApp({Key? key}) : super(key: key); 35 | @override 36 | Widget build(BuildContext context) { 37 | return const MaterialApp( 38 | debugShowCheckedModeBanner: false, 39 | home: MainPage(), 40 | ); 41 | } 42 | } 43 | 44 | class MainPage extends StatelessWidget { 45 | const MainPage({Key? key}) : super(key: key); 46 | @override 47 | Widget build(BuildContext context) { 48 | return Scaffold( 49 | body: StreamBuilder( 50 | stream: FirebaseAuth.instance.authStateChanges(), 51 | builder: (context, snapshot) { 52 | if (snapshot.hasData) { 53 | return const HomePage(); 54 | } else { 55 | return const LoginPage(); 56 | } 57 | })); 58 | } 59 | } 60 | 61 | class HomePage extends StatelessWidget { 62 | const HomePage({Key? key}) : super(key: key); 63 | // Perform Email/Password Login 64 | Future signOut() async { 65 | await FirebaseAuth.instance.signOut(); 66 | } 67 | 68 | @override 69 | Widget build(BuildContext context) { 70 | return Scaffold( 71 | body: Column( 72 | children: [ 73 | Text('User + ${FirebaseAuth.instance.currentUser?.email}'), 74 | const SizedBox(height: 10.0), 75 | Padding( 76 | padding: const EdgeInsets.symmetric(horizontal: 25.0), 77 | child: GestureDetector( 78 | onTap: signOut, 79 | child: Container( 80 | padding: const EdgeInsets.all(20), 81 | decoration: BoxDecoration( 82 | color: Colors.blue, 83 | borderRadius: BorderRadius.circular(12), 84 | ), 85 | child: const Center( 86 | child: Text('Sign Out'), 87 | ), 88 | ), 89 | )) 90 | ], 91 | ), 92 | ); 93 | } 94 | } 95 | 96 | class LoginPage extends StatefulWidget { 97 | const LoginPage({Key? key}) : super(key: key); 98 | @override 99 | State createState() => _LoginPageState(); 100 | } 101 | 102 | class _LoginPageState extends State { 103 | // Add Controllers for Text Fields 104 | final _userEmailController = TextEditingController(); 105 | final _userPasswordController = TextEditingController(); 106 | // Perform Email/Password Login 107 | Future signIn() async { 108 | await FirebaseAuth.instance.signInWithEmailAndPassword( 109 | email: _userEmailController.text.trim(), 110 | password: _userPasswordController.text.trim()); 111 | } 112 | 113 | @override 114 | void dispose() { 115 | _userEmailController.dispose(); 116 | _userPasswordController.dispose(); 117 | super.dispose(); 118 | } 119 | 120 | @override 121 | Widget build(BuildContext context) { 122 | return Scaffold( 123 | backgroundColor: Colors.grey[300], 124 | body: SafeArea( 125 | child: Center( 126 | child: SingleChildScrollView( 127 | child: Column( 128 | mainAxisAlignment: MainAxisAlignment.center, 129 | children: [ 130 | const Text('Header'), 131 | const SizedBox(height: 10), 132 | Padding( 133 | padding: const EdgeInsets.symmetric(horizontal: 25.0), 134 | child: TextField( 135 | controller: _userEmailController, 136 | decoration: const InputDecoration(hintText: 'Email'), 137 | )), 138 | const SizedBox( 139 | height: 10, 140 | ), 141 | Padding( 142 | padding: const EdgeInsets.symmetric(horizontal: 25.0), 143 | child: TextField( 144 | controller: _userPasswordController, 145 | obscureText: true, 146 | decoration: const InputDecoration(hintText: 'Password'), 147 | )), 148 | const SizedBox( 149 | height: 10, 150 | ), 151 | Padding( 152 | padding: const EdgeInsets.symmetric(horizontal: 25.0), 153 | child: GestureDetector( 154 | onTap: signIn, 155 | child: Container( 156 | padding: const EdgeInsets.all(20), 157 | decoration: BoxDecoration( 158 | color: Colors.blue, 159 | borderRadius: BorderRadius.circular(12), 160 | ), 161 | child: const Center( 162 | child: Text('Sign In'), 163 | ), 164 | ), 165 | )), 166 | ], 167 | )), 168 | ))); 169 | } 170 | } 171 | 172 | ``` 173 | 174 | ## Example: Emulator Code 175 | 176 | ```dart 177 | if (kDebugMode) { 178 | try { 179 | await FirebaseAuth.instance.useAuthEmulator('localhost', 9099); 180 | } catch (e) { 181 | print(e); 182 | } 183 | ``` 184 | 185 | -------------------------------------------------------------------------------- /ch17/ex17-8.md: -------------------------------------------------------------------------------- 1 | # 17.8 Adding Collision Detection 2 | 3 | 4 | # Example: Collision detection 5 | 6 | ```dart 7 | import 'dart:async'; 8 | import 'package:flame/collisions.dart'; 9 | import 'package:flame/flame.dart'; 10 | import 'package:flame/game.dart'; 11 | import 'package:flame/components.dart'; 12 | import 'package:flutter/material.dart'; 13 | 14 | void main() async { 15 | WidgetsFlutterBinding.ensureInitialized(); 16 | await Flame.device.setPortrait(); 17 | final shapeGame = ShapesExample(); 18 | 19 | runApp(GameWidget(game: shapeGame)); 20 | } 21 | 22 | class ShapesExample extends FlameGame with HasCollisionDetection { 23 | @override 24 | Future onLoad() async { 25 | super.onLoad(); 26 | 27 | add(RectComponent(size[0], size[1])); 28 | } 29 | 30 | // @override 31 | // void update(double dt) { 32 | // super.update(dt); 33 | // } 34 | 35 | // @override 36 | // void render(Canvas canvas) { 37 | // super.render(canvas); 38 | // } 39 | } 40 | 41 | // Add a [Color] Rect on screen 42 | class RectComponent extends PositionComponent with CollisionCallbacks { 43 | double screenWidthMax = 0; 44 | double screenHeightMax = 0; 45 | 46 | double xStartPosition = 0; 47 | double yStartPosition = 0; 48 | static double xRectWidth = 50; 49 | static double yRectHeight = 50; 50 | int rectDirection = 1; 51 | 52 | final paint = Paint() 53 | ..color = Colors.white 54 | ..strokeWidth = 4; 55 | 56 | RectComponent(this.screenWidthMax, this.screenHeightMax); 57 | 58 | @override 59 | Future onLoad() async { 60 | super.onLoad(); 61 | // Set the start position of the Rect - center of the screen 62 | xStartPosition = (screenWidthMax) / 2; 63 | yStartPosition = (screenHeightMax) / 2; 64 | 65 | add(RectangleHitbox()); 66 | } 67 | 68 | @override 69 | void onCollision(Set intersectionPoints, PositionComponent other) { 70 | super.onCollision(intersectionPoints, other); 71 | 72 | if (other is ScreenHitbox) { 73 | switch (rectDirection) { 74 | case 0: 75 | rectDirection = 1; 76 | break; 77 | case 1: 78 | rectDirection = 0; 79 | break; 80 | default: 81 | break; 82 | } 83 | } 84 | } 85 | 86 | @override 87 | void update(double dt) { 88 | super.update(dt); 89 | if (rectDirection == 1) { 90 | xStartPosition += 5; 91 | if (xStartPosition >= (screenWidthMax - xRectWidth)) { 92 | rectDirection = 0; 93 | } 94 | } 95 | 96 | if (rectDirection == 0) { 97 | xStartPosition -= 5; 98 | if (xStartPosition <= (0)) { 99 | rectDirection = 1; 100 | } 101 | } 102 | } 103 | 104 | @override 105 | void render(Canvas canvas) { 106 | super.render(canvas); 107 | 108 | // xStartPos, yStartPos, xRectWidth, yRectHeight 109 | canvas.drawRect( 110 | Rect.fromLTWH(xStartPosition, yStartPosition, xRectWidth, yRectHeight), 111 | paint); 112 | } 113 | } 114 | ```i 115 | 116 | # Example: Test 117 | 118 | ```dart 119 | import 'dart:async'; 120 | import 'package:flame/collisions.dart'; 121 | import 'package:flame/flame.dart'; 122 | import 'package:flame/game.dart'; 123 | import 'package:flame/components.dart'; 124 | import 'package:flutter/material.dart'; 125 | 126 | void main() async { 127 | WidgetsFlutterBinding.ensureInitialized(); 128 | await Flame.device.setPortrait(); 129 | final shapeGame = ShapesExample(); 130 | 131 | runApp(GameWidget(game: shapeGame)); 132 | } 133 | 134 | class ShapesExample extends FlameGame with HasCollisionDetection { 135 | @override 136 | Future onLoad() async { 137 | add(GridComponent(size[0], size[1])); 138 | add(RectComponent(size[0], size[1])); 139 | super.onLoad(); 140 | } 141 | 142 | // @override 143 | // void update(double dt) { 144 | // super.update(dt); 145 | // } 146 | 147 | // @override 148 | // void render(Canvas canvas) { 149 | // super.render(canvas); 150 | // } 151 | } 152 | 153 | class GridComponent extends PositionComponent with CollisionCallbacks { 154 | double screenWidthMax = 0; 155 | double screenHeightMax = 0; 156 | double xPos = 0; 157 | double yPos = 0; 158 | 159 | final paint = Paint() 160 | ..color = Colors.grey 161 | ..strokeWidth = 1; 162 | 163 | GridComponent(this.screenWidthMax, this.screenHeightMax); 164 | 165 | @override 166 | Future onLoad() async { 167 | super.onLoad(); 168 | xPos = (screenWidthMax / 2) - 100; 169 | yPos = (screenHeightMax / 2); 170 | 171 | // add(RectangleHitbox()); 172 | add(RectangleHitbox.relative(Vector2(xPos, yPos), 173 | parentSize: Vector2(50, 50))); 174 | add(ScreenHitbox()); 175 | } 176 | 177 | @override 178 | void onCollision(Set intersectionPoints, PositionComponent other) { 179 | // print('Grid Edge detected - onCollision'); 180 | 181 | if (other is ScreenHitbox) { 182 | print('ScreenHitbox: other onCollision'); 183 | } else if (other is RectComponent) { 184 | print('RectangleHitbox: other onCollision'); 185 | } else { 186 | print('Other onCollision: $other'); 187 | } 188 | super.onCollision(intersectionPoints, other); 189 | } 190 | 191 | // @override 192 | // void onCollisionStart( 193 | // Set intersectionPoints, PositionComponent other) { 194 | // // ignore: avoid_print 195 | // print('Grid Edge detected - onCollisionStart'); 196 | // super.onCollisionStart(intersectionPoints, other); 197 | // } 198 | 199 | @override 200 | void render(Canvas canvas) { 201 | super.render(canvas); 202 | canvas.drawRect(Rect.fromLTWH(xPos, yPos, 50, 50), paint); 203 | } 204 | } 205 | 206 | // Add a [Color] Rect on screen 207 | class RectComponent extends PositionComponent with CollisionCallbacks { 208 | double screenWidthMax = 0; 209 | double screenHeightMax = 0; 210 | 211 | double xStartPosition = 0; 212 | double yStartPosition = 0; 213 | static double xRectWidth = 50; 214 | static double yRectHeight = 50; 215 | int rectDirection = 0; 216 | double elapsedTime = 0.0; 217 | 218 | final paint = Paint() 219 | ..color = Colors.white 220 | ..strokeWidth = 4; 221 | 222 | RectComponent(this.screenWidthMax, this.screenHeightMax); 223 | 224 | @override 225 | Future onLoad() async { 226 | super.onLoad(); 227 | // Set the start position of the Rect - center of the screen 228 | xStartPosition = (screenWidthMax) / 2; 229 | yStartPosition = (screenHeightMax) / 2; 230 | 231 | // add(RectangleHitbox()); 232 | add(RectangleHitbox.relative(Vector2(xStartPosition, yStartPosition), 233 | parentSize: Vector2(50, 50))); 234 | add(ScreenHitbox()); 235 | } 236 | 237 | @override 238 | void onCollision(Set intersectionPoints, PositionComponent other) { 239 | // print('Rect Edge detected - onCollision'); 240 | 241 | if (other is ScreenHitbox) { 242 | // ignore: avoid_print 243 | print('detected collision'); 244 | } else if (other is GridComponent) { 245 | // ignore: avoid_print 246 | print('Rectangle: onCollision'); 247 | } else { 248 | print('Other onCollision: $other'); 249 | } 250 | 251 | super.onCollision(intersectionPoints, other); 252 | } 253 | 254 | // @override 255 | // void onCollisionStart( 256 | // Set intersectionPoints, PositionComponent other) { 257 | // // ignore: avoid_print 258 | // print('Rect Edge detected - onCollisionStart'); 259 | // super.onCollisionStart(intersectionPoints, other); 260 | // } 261 | 262 | @override 263 | void update(double dt) { 264 | super.update(dt); 265 | 266 | elapsedTime += dt; 267 | 268 | if (elapsedTime > 1.0) { 269 | if (rectDirection == 1) { 270 | xStartPosition += 5; 271 | // if (xStartPosition >= (screenWidthMax - xRectWidth)) { 272 | // rectDirection = 0; 273 | // } 274 | } 275 | 276 | if (rectDirection == 0) { 277 | xStartPosition -= 5; 278 | // if (xStartPosition <= (0)) { 279 | // rectDirection = 1; 280 | // } 281 | } 282 | 283 | elapsedTime = 0.0; 284 | } 285 | } 286 | 287 | @override 288 | void render(Canvas canvas) { 289 | super.render(canvas); 290 | 291 | // xStartPos, yStartPos, xRectWidth, yRectHeight 292 | canvas.drawRect( 293 | Rect.fromLTWH(xStartPosition, yStartPosition, xRectWidth, yRectHeight), 294 | paint); 295 | } 296 | } 297 | 298 | 299 | ``` 300 | --------------------------------------------------------------------------------