Get Flapping with
Abraham Williams
Pearl Latteier
Senior Developers at Bendyworks
Google Developer Experts
Organizers of GDG Madison
slides.today
Cross Platform
Mobile Apps!
Ionic
React Native
NativeScript
Flutter
Ionic
Ionic
Write HTML/JS/CSS
Ionic
Write HTML/JS/CSS
Display in WebView
Ionic
Write HTML/JS/CSS
Display in WebView
Cordova or Capacitor wrapper
React Native
React Native
Write React
React Native
Write React
OEM Widgets
React Native
Write React
OEM Widgets
JS bridge connects to native APIs
NativeScript
NativeScript
Write JS, TypeScript, Angular, or Vue
NativeScript
Write JS, TypeScript, Angular, or Vue
OEM Widgets
NativeScript
Write JS, TypeScript, Angular, or Vue
OEM Widgets
Native APIs injected into JS VM
Flutter
Flutter
Write Dart
Flutter
Write Dart
Compiles to native code
Flutter
Write Dart
Compiles to native code
Flutter widgets
Dart
Static typing
Catch bugs early
Just-in-time
compilation
Hot-reloading for fast dev
Ahead-of-time
compilation
Fast, predictable native code
No templating language
All Dart, all the time
Skia
Graphics engine
Widgets and rendering live in your app
download size
vs. customizable UI
DEMO TIME
Widgets
Everything’s a widget!
Layout widgets
flutter.io/widgets
Style widgets
flutter.io/widgets
Animation widgets
flutter.io/widgets
Scaffold
AppBar
Text
Color
IconButton
Container
BoxDecoration
LinearGradient
Center
DogList
HomePage Widget
A Basic Widget
Stateless Widget
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
title: 'Good Dogs',
theme: ThemeData(brightness: Brightness.dark),
home: MyHomePage(title: 'Good Dogs'),
);
}
}
Stateless Widget
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
title: 'Good Dogs',
theme: ThemeData(brightness: Brightness.dark),
home: MyHomePage(title: 'Good Dogs'),
);
}
}
Stateless Widget
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
title: 'Good Dogs',
theme: ThemeData(brightness: Brightness.dark),
home: MyHomePage(title: 'Good Dogs'),
);
}
}
Stateless Widget
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
title: 'Good Dogs',
theme: ThemeData(brightness: Brightness.dark),
home: MyHomePage(title: 'Good Dogs'),
);
}
}
Stateless Widget
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
title: 'Good Dogs',
theme: ThemeData(brightness: Brightness.dark),
home: MyHomePage(title: 'Good Dogs'),
);
}
}
Stateless Widget
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
title: 'Good Dogs',
theme: ThemeData(brightness: Brightness.dark),
home: MyHomePage(title: 'Good Dogs'),
);
}
}
A Stateful Widget
Stateful Widget
class MyHomePage extends StatefulWidget {
_MyHomePageState createState() => _MyHomePageState();
}
Stateful Widget
class _HomePageState extends State<HomePage> {
int counter = 0;
void increment() {
setState(() { this.counter++ });
}
Widget build(BuildContext context) {
return Button(child: Text('Click me'));
}
}
State is long-lived
Widgets get reborn
Animation
Built-in Animation
Custom Animation with Tween
Mikkel Ravn, “Zero to One with Flutter”, Medium
Testing
Built-In Testing Tools
import 'package:test/test.dart'
import 'package:flutter_test/flutter_test.dart'
import 'package:flutter_driver/driver_extension.dart'
Testing
testWidgets('Displays app bar', (WidgetTester tester) async {
MyHomePage homePage = MyHomePage(title: 'Test Dogs');
await tester.pumpWidget(MaterialApp(home: homePage));
Finder titleFinder = find.text('Test Dogs');
expect(titleFinder, findsOneWidget);
});
Testing
testWidgets('Displays app bar', (WidgetTester tester) async {
MyHomePage homePage = MyHomePage(title: 'Test Dogs');
await tester.pumpWidget(MaterialApp(home: homePage));
Finder titleFinder = find.text('Test Dogs');
expect(titleFinder, findsOneWidget);
});
Testing
testWidgets('Displays app bar', (WidgetTester tester) async {
MyHomePage homePage = MyHomePage(title: 'Test Dogs');
await tester.pumpWidget(MaterialApp(home: homePage));
Finder titleFinder = find.text('Test Dogs');
expect(titleFinder, findsOneWidget);
});
Resources
More Flutter at Mobile Era
Take off with Flutter
Jon Grythe Stødle
Thursday 1st November, 13:00 - 14:00
Lancing
Flutter in Action: How to build cross-platform app with Dart
Vitalii Bobrov
Thursday 1st November, 14:00 - 15:00
Lancing
We design and build software that stands the test of time, specializing in Ruby on Rails, JavaScript, Clojure, and Ionic.
Craft a project with us at bendyworks.com
Find today’s slides at slides.today
Pearl Latteier
pearl@bendyworks.com
twitter.com/pblatteier
github.com/pearlbea
Abraham Williams
abraham@bendyworks.com
twitter.com/abraham
github.com/abraham