Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Launching into cross-platform development with ...

Launching into cross-platform development with Flutter

A small introduction into cross-platform development using Flutter, a framework launched by Google to develop mobile applications that run both on android and iOS. We will see the basic usage of this framework and the pros and cons of adopting it, from an Android developer’s point of view. The presentation covers some of the main concepts of Flutter, like UI components and widgets or how to add user interaction to your app.

After this presentation you will get a main idea on how Flutter works and how you can use it to develop your own android and iOS applications very easily. Hopefully, you will start using it to make your cross-platform mobile applications development faster and easier.

Catalin Radoiu

October 03, 2018
Tweet

Other Decks in Programming

Transcript

  1. Overview • What is Flutter and why should you use

    it? • How to get started • Flutter widgets and responsive design • Platform specific code • Adding interactivity to your app
  2. Why Flutter? • Easy to learn • Flexible and performant

    UI • One codebase, two applications • Clear documentation • Hot reload
  3. Getting started • Getting the Flutter SDK • Platform setup

    (iOS, Android) • Configure the editor • Test the SDK
  4. import 'package:flutter/material.dart'; void main() => runApp(new MyApp()); class MyApp extends

    StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) { return new MaterialApp( title: 'Flutter Demo', theme: new ThemeData( // This is the theme of your application. // // Try running your application with "flutter run". You'll see the // application has a blue toolbar. Then, without quitting the app, try // changing the primarySwatch below to Colors.green and then invoke // "hot reload" (press "r" in the console where you ran "flutter run", // or press Run > Flutter Hot Reload in IntelliJ). Notice that the // counter didn't reset back to zero; the application is not restarted. primarySwatch: Colors.blue, ), home: new MyHomePage(title: 'Flutter Demo Home Page'), ); } } class MyHomePage extends StatefulWidget { MyHomePage({Key key, this.title}) : super(key: key); .........
  5. Common widgets • Column = vertical view group • Row

    = horizontal view group • Expanded • Text • Container • Stack • Padding • Center
  6. Widget _createTitleSection() { return Row( children: <Widget>[ new Expanded( child:

    Column( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Text( "Oeschinen Lake Campground", style: TextStyle(fontSize: 14.0, fontWeight: FontWeight.bold), ), Text( "Kandersteg, Switzerland", style: TextStyle(fontSize: 14.0), ) ], ), ), Icon(Icons.star, color: Colors.red), new Padding( padding: const EdgeInsets.only(right: 8.0), child: Text("41"), ) ], ); }
  7. Widget _createButtonSection() { return Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: <Widget>[ _createActionButtonWidget(

    "CALL", Icons.call, Colors.lightBlue, Colors.lightBlue), _createActionButtonWidget( "ROUTE", Icons.near_me, Colors.lightBlue, Colors.lightBlue), _createActionButtonWidget( "SHARE", Icons.share, Colors.lightBlue, Colors.lightBlue) ], ); } Widget _createActionButtonWidget( String actionName, IconData icon, Color iconColor, Color textColor) { return Column( children: <Widget>[ Icon(icon, color: iconColor), new Padding( padding: const EdgeInsets.only(top: 8.0), child: Text( actionName, style: TextStyle(color: textColor), ), ) ], ); }
  8. @override Widget build(BuildContext context) { return Scaffold( body: Column( children:

    <Widget>[ Image.asset('images/lake.jpg', width: 600.0, height: 240.0, fit: BoxFit.cover), new Padding( padding: const EdgeInsets.all(16.0), child: _createTitleSection(), ), new Padding( padding: const EdgeInsets.only(top: 16.0, bottom: 16.0), child: _createButtonSection(), ), new Padding( padding: const EdgeInsets.all(16.0), child: Text( "Lake Oeschinen lies at the foot of the Blüemlisalp in the Bernese Alps. Situated 1,578 meters above sea level, it is one of the larger Alpine Lakes. A gondola ride from Kandersteg, followed by a half- hour walk through pastures and pine forest, leads you to the lake, which warms to 20 degrees Celsius in the summer. Activities enjoyed here include rowing, and riding the summer toboggan run."), ) ], )); }
  9. import 'package:flutter/material.dart'; class StatefulWidgetExample extends StatefulWidget { @override State<StatefulWidget> createState()

    => _StatefulWidgetExampleState(); } class _StatefulWidgetExampleState extends State<StatefulWidgetExample> { Color color = Colors.green; @override Widget build(BuildContext context) { return Center( child: FlatButton( child: Center(child: Text("Press to change color")), color: color, onPressed: () { setState(() { color = _generateRandomColor(); }); }, ), ); } }
  10. class MyHomePage extends StatefulWidget { MyHomePage({Key key, this.title}) : super(key:

    key); final String title; @override _MyHomePageState createState() => new _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { int _counter = 0; void _incrementCounter() { setState(() { _counter++; }); } @override Widget build(BuildContext context) { return new Scaffold( appBar: new AppBar( title: new Text(widget.title), ), body: new Center( child: new Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ new Text( 'You have pushed the button this many times:', ), new Text( '$_counter', style: Theme.of(context).textTheme.display1, ), ], ), ), floatingActionButton: new FloatingActionButton( onPressed: _incrementCounter, tooltip: 'Increment', child: new Icon(Icons.add), ), ); } }
  11. class Incrementer extends StatefulWidget{ final _IncrementerState _incrementerState = _IncrementerState(); @override

    State<StatefulWidget> createState() => _incrementerState; void incrementCounter(){ _incrementerState._incrementCounter(); } } class _IncrementerState extends State<Incrementer>{ int _counter = 0; void _incrementCounter(){ setState(() { _counter++; }); } @override Widget build(BuildContext context) { return Text( '$_counter', style: Theme.of(context).textTheme.display1, ); } }
  12. class MyHomePage extends StatelessWidget { final String title; const MyHomePage({Key

    key, this.title}) : super(key: key); @override Widget build(BuildContext context) { Incrementer incrementer = Incrementer(); return new Scaffold( appBar: new AppBar( title: new Text(title), ), body: new Center( child: new Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ new Text( 'You have pushed the button this many times:', ), Incrementer(), ], ), ), floatingActionButton: new FloatingActionButton( onPressed: () => incrementer.incrementCounter(), tooltip: 'Increment', child: new Icon(Icons.add), ), ); } }
  13. Widget _buildCategoriesList(BuildContext context, categoriesList) { if (MediaQuery.of(context).orientation == Orientation.portrait) {

    return ListView.builder( itemCount: categoriesList.length, itemBuilder: (BuildContext context, int index) { return MyCategory( icon: categoriesList[index].icon, color: Color(categoriesList[index].colorCode), text: categoriesList[index].name, ); }); } else { return GridView.count( crossAxisCount: 2, childAspectRatio: 3.0, children: buildCategoriesWidgets(categoriesList), ); } }
  14. @override Widget build(BuildContext context) { if (Theme.of(context).platform == TargetPlatform.android) {

    return Scaffold( appBar: AppBar(title: Text("Sample app")), bottomNavigationBar: _createMaterialTabBar(), ); } else { return CupertinoTabScaffold( tabBar: _createCupertinoTabBar(), tabBuilder: (BuildContext context, int index) { return _createCupertinoTabView(); }, ); } }
  15. Gestures • onTapDown • onTap • onDoubleTap • onLongPress •

    onVerticalDragStart • onHorizontalDragUpdate
  16. Key learnings • Easy to use • Well documented •

    Continuously growing community • Single codebase for both platforms • Native solution more performant