Flutter: Difference between revisions

From bibbleWiki
Jump to navigation Jump to search
Line 331: Line 331:
</syntaxhighlight>
</syntaxhighlight>
=Interactivity=
=Interactivity=
==Introduction==
Classes that inherit "StatefulWidget" are immutable. The State is mutable.
Using Stateful Widgets
*Create a class that extends Stateful Widget that return state
*Create a state class, with properties that may change
*Implement Build
*Call setState() method to make changes
<syntaxhighlight lang="dart">
<syntaxhighlight lang="dart">
class HelloYou extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _HelloYouState();
}
class _HelloYouState extends State<HelloYou> {
  String name = '';
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Hello"),
        backgroundColor: Colors.blueAccent,
      ),
      body: Container(
        padding: EdgeInsets.all(15),
        child: Column(
          children: <Widget>[
            TextField(
              decoration: InputDecoration(hintText: "Please insert your name"),
              onChanged: (String text) => {
                setState(() => {name = text})
              },
            ),
            Text('Hello' + name + "!")
          ],
        ),
      ),
    );
  }
}
</syntaxhighlight>
</syntaxhighlight>
==And... and onSumbmitted==
It is worthwhile noting that the arrow functions work the same as the ones in javascript except alternatively you can miss out the arrow. The onChange could be written
<syntaxhighlight lang="dart">
..
              onChanged: (String text) {
                setState(() {name = text})
              },
..
</syntaxhighlight>
Note the onSubmitted works the same as onChanged except it waits for the Enter button before being fired

Revision as of 11:23, 15 December 2020

Introduction

Why Flutter created in 2017

  • Compiles to native, JIT and Ahead of Time
  • Fast Development
  • Single Code Base
  • Uses Dart

Resources is https://github.com/simoales/flutter

Installation

Flutter

You can switch versions of flutter using the channel option where there are options of master, dev, beta etc. See https://github.com/flutter/flutter/wiki/Flutter-build-release-channels

sudo snap install flutter --classic
sudo snap install flutter-gallery
flutter channel dev
flutter upgrade
flutter config --enable-linux-desktop

You will need to specify the path to android studio

flutter config --android-studio-dir="/opt/android-studio-4.1/android-studio"

Android Studio

For Android Studio the flutter SDK will be in /home/(username)/snap/flutter/common/flutter

Flutter doctor

You can run flutter doctor to see if all went well. This is what I got

flutter doctor
[] Flutter (Channel dev, 1.25.0-8.0.pre, on Linux, locale en_NZ.UTF-8)
[] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
[] Linux toolchain - develop for Linux desktop
[!] Android Studio (not installed)
[] VS Code (version 1.52.0)
[] Connected device (1 available)

Creating a Project

In VS Code run flutter doctor and then flutter new project. Project names must be in lower case. e.g. hello_flutter. This opens a new VS Code with the project. The import contains the widgets to use and the rest just configures the widgets on the screen. I.E. Text is like a <Text /> tag in react or angular.

import 'package:flutter/material.dart';

void main() {
  runApp(Center(
    child: Text("Fred Was Ere",
        textDirection: TextDirection.ltr,
        style: TextStyle(backgroundColor: Colors.blue)),
  ));
}

When familar we can create a project with the flutter cli

flutter create app_widgets

A Bigger Example

So a bigger example might be

import 'package:flutter/material.dart';

void main() {
  runApp(MaterialApp(
    title: "My lovely App",
    home: Scaffold(
      appBar: AppBar(
        title: Text("App Bar Title"),
      ),
      body: Material(
        color: Colors.deepPurple,
        child: Center(
          child: Text(
            "Fred Was Ere",
            textDirection: TextDirection.ltr,
            style: TextStyle(color: Colors.white, fontSize: 36.0),
          ),
        ),
      ),
    ),
  ));
}

Classes

Things are getting a big large so we need to break the code down. We do this by writing our own classes. We can derive a class from StatelessWidget to do this.

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "My lovely App",
      home: Scaffold(
        appBar: AppBar(
          title: Text("App Bar Title"),
        ),
        body: Material(
          color: Colors.deepPurple,
          child: Center(
            child: Text(
              "Fred Was Ere",
              textDirection: TextDirection.ltr,
              style: TextStyle(color: Colors.white, fontSize: 36.0),
            ),
          ),
        ),
      ),
    );
  }
}

Fat Arrow

Dart supports the fat arrow approach so we can so

import './screens/home.dart';

void main() {
  runApp(MyWidget());
}

Can become

import './screens/home.dart';

void main() => runApp(MyWidget());

Adding Logic

No surprises here. We can add functions within the class declaration.

import 'package:flutter/material.dart';

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Material(
      color: Colors.deepPurple,
      child: Center(
        child: Text(
          sayHello(),
          textDirection: TextDirection.ltr,
          style: TextStyle(color: Colors.white, fontSize: 36.0),
        ),
      ),
    );
  }

  String sayHello() {
    var hello;
    DateTime now = DateTime.now();
    if (now.hour < 12) {
      hello = "Good Morning";
    } else if (now.hour < 18) {
      hello = "Good Afternoon";
    } else {
      hello = "Good Evening";
    }
    return hello;
  }
}

Basic Widgets and Concepts

The basic widgets and Concepts are

  • Container
  • Text
  • Row & Column
  • Image
  • RaisedButton
  • AlertDialog
  • Box Constraints
  • Size, Margin and Padding

Containers

They are as they sound. It is worth noting the width and height are controlled by the parent. Look at https://flutter.io/layout. To bypass the constraint of the parent you need to wrap your widget in a widget which supports this. E.g. Center widget.

import 'package:flutter/material.dart';

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
        child: Container(
      width: 192.0,
      height: 96.0,
      alignment: Alignment.center,
      color: Colors.deepOrangeAccent,
      child: Text(
        "Pizza",
        textDirection: TextDirection.ltr,
      ),
    ));
  }
}

Margins And Padding

Margins and Paddings use the EdgeInsets.All and EdgeInsets.Only constructor. So to set a margin we can do.

...
        child: Container(
      width: 192.0,
      height: 96.0,
      margin: EdgeInsets.only(left:50.0),
      padding: EdgeInsets.All(10.0),
...

Fonts

Copy the fonts to a directory. The file pubspec.yaml contains the configurations.

  fonts:
    - family: Oxygen
      fonts:
        - asset: fonts/Oxygen-Regular.ttf
        - asset: fonts/Oxygen-Bold.ttf
          weight: 700
        - asset: fonts/Oxygen-Light.ttf
          weight: 300

Now we can use the font with the Text Widget

...
      child: Text(
        "Pizza",
        textDirection: TextDirection.ltr,
        style: TextStyle(
          fontFamily: 'Oxygen',
          fontWeight: FontWeight.w300,
        ),
...

Rows and Columns

These seem to work the same as flex box.

...
        child: Row(
          children: <Widget>[
            Text(
              "Margherita",
              textDirection: TextDirection.ltr,
              style: TextStyle(
                fontFamily: 'Oxygen',
                fontWeight: FontWeight.w300,
              ),
            ),
            Text(
              "Tomato, Mozzarella, Basil",
              textDirection: TextDirection.ltr,
              style: TextStyle(
                fontFamily: 'Oxygen',
                fontWeight: FontWeight.w300,
              ),
            ),
          ],
        ),
...

The result is items which overflow the row because the text exceeds the width of the phone.

caption
caption

Expanded

Wrapping in Expanded means that the row will wrap like flexbox wrapping.

caption
caption
            Expanded(
              child: Text(
                "Tomato, Mozzarella, Basil",
                textDirection: TextDirection.ltr,
                style: TextStyle(
                  fontSize: 30,
                  fontFamily: 'Oxygen',
                  fontWeight: FontWeight.w300,
                ),
              ),
            ),

Images

To Create an image we can use an asset and like the fonts this is specified in the pubspec.yaml

...
flutter:

  # The following line ensures that the Material Icons font is
  # included with your application, so that you can use the icons in
  # the material Icons class.
  uses-material-design: true

  # To add assets to your application, add an assets section, like this:
  assets:
    - images/pizza.png
...

To use the image we can create a class to hold it and wrap it in a container.

class PizzaImageWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    AssetImage pizzaAsset = AssetImage('images/pizza.png');
    Image image = Image(image: pizzaAsset, width: 400, height: 400);
    return Container(child: image);
  }
}

Raised Button, Alert and Event Handler

There are now surprises and this is just an example for reference. Not the use of the onPressed function which calls the alert creation function.

class OrderButton extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    var button = Container(
      margin: EdgeInsets.only(top: 10),
      child: RaisedButton(
        child: Text("Order your Pizza"),
        color: Colors.lightGreen,
        elevation: 5.0,
        onPressed: () {
          order(context);
        },
      ),
    );
    return button;
  }

  void order(BuildContext context) {
    var alert = AlertDialog(
      title: Text("Order Completed"),
      content: Text("Thanks"),
    );
    showDialog(context: context, builder: (BuildContext context) => alert);
  }
}

Interactivity

Introduction

Classes that inherit "StatefulWidget" are immutable. The State is mutable. Using Stateful Widgets

  • Create a class that extends Stateful Widget that return state
  • Create a state class, with properties that may change
  • Implement Build
  • Call setState() method to make changes
class HelloYou extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _HelloYouState();
}

class _HelloYouState extends State<HelloYou> {
  String name = '';
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Hello"),
        backgroundColor: Colors.blueAccent,
      ),
      body: Container(
        padding: EdgeInsets.all(15),
        child: Column(
          children: <Widget>[
            TextField(
              decoration: InputDecoration(hintText: "Please insert your name"),
              onChanged: (String text) => {
                setState(() => {name = text})
              },
            ),
            Text('Hello' + name + "!")
          ],
        ),
      ),
    );
  }
}

And... and onSumbmitted

It is worthwhile noting that the arrow functions work the same as the ones in javascript except alternatively you can miss out the arrow. The onChange could be written

..
              onChanged: (String text) {
                setState(() {name = text})
              },
..

Note the onSubmitted works the same as onChanged except it waits for the Enter button before being fired