#udacity #flutterstudyjam #nyc
Flutter Study Jam
September 10, 2018
Build Mobile Native Apps With Flutter
Sep10 - Oct 1
What is Material Design? You might remember it as something like this. A well thought-through system of UI components, but one that made all apps have the same generic look and feel.
Google recognized this, and put a TON of user research into this. Here’s what they came up with (video).
Your app can (and should) look and feel unique.
Material Theme Editor: Sketch plugin to experiment with color, shape, and typography.
Color Tool: Browser tool to pick a palette of colors that is Hierarchical, Legible, and Expressive, even for users with low vision.
This is all great for Flutter users because Flutter loves Material Design, and vice versa.
Flutter comes with a huge set of material design widgets to keep you from having to reinvent the wheel, including 900 icons that you can use in buttons and elsewhere.
Material widgets can look and feel different on iOS and Android. Here, you can see the AppBar widget looks different on both platforms. This is because there is code inside that widget that checks the current platform. Your widgets can do the same, or they can look exactly the same on both; it’s up to you.
Here’s how to check the current platform in your Flutter app. In this example, we use a switch statement to return the appropriate busy spinner for the given platform.
Here’s how to perform conditional rendering based on whether your device is in portrait or landscape. Your widget will automatically be rebuilt when the phone is rotated. In this example, we are returning a GridView in landscape and a ListView in portrait. You can also you a widget called OrientationBuilder to make this slightly easier.
Finally, you don’t need to use the Material widgets at all in your app. For example you can use the Cupertino widgets which look just like native iOS’ UIKit. Or you can just roll your own 100% custom widgets.
Text fields are one of the most important means that users will use to interact with your app. Here are some of the different styles you can create out of the box in Flutter.
Here’s how to create a text field in Flutter. Notice the use of composition over inheritance. The style property is set to a TextStyle widget, and the decoration property is set to an InputDecoration object.
To get data from the text field, we use the onChanged event handler. In this example, we print the current value of the text field to the console.
You can also do much more such as validation, updating the value of the text field programmatically, and grouping multiple fields using a Form widget.
Watch out for pixel overflow! When working with multiple text fields, make sure your app will render correctly on smaller devices once the keyboard appears. Do this by putting your fields into a scrollable view, such as a ListView or SingleChildScrollView.
Flutter gives you access to raw touch events, but also offers a widget called a GestureDetector that provides a higher level of abstraction.
You can wrap any widget with a GestureDetector widget to enable user interaction. In this simple example, we wrap a Text widget with a GestureDetector so it prints to the console whenever it is touched. In Flutter, it is extremely easy to add user interactivity to any widget.
At some point you will want to add external resources to app, whether it be outside code, or custom fonts and images. Outside code is usually provided in the form of a package.
A package is a library of functions that can be shared easily. There are plenty of open-source packages available online, but you can also make your own.
Packages that interface with the native platform API’s are called plugins.
To add a package, simply update your pubspec.yaml at the root of your Flutter app.
What’s really cool is that even you import a large package, only the code that you actually use will be compiled into your binary. (Tree shaking)
Look for packages on pub.dartlang.org before you reinvent the wheel!
To add custom images and fonts to your app, also reference them in the pubspec.yaml file.
You will then be able to reference them by name inside your app.
The assets can also be shared with the underlying native platform.
Flutter can load resolution-appropriate images for the current device pixel ratio.
In this example, I created a custom icon font using an online tool called Fontello. That way they scale perfectly and I don’t have to worry about exporting them at various resolutions.
I can hardly think of an app nowadays that does not communicate with a backend API of some sort. Since accessing the network is a time-consuming operation, and since Dart is single-threaded, it needs to be asynchronous so that our app can continue to run without freezing.
Dart uses Futures to represent asynchronous operations.
When you invoke an asynchronous function, the function immediately returns an uncompleted Future object.
Later, when the operation is finished, the Future object completes with the final value or with an error.
Here we are invoking the getUrl method on the HttpClient class, which returns a Future.
We can then set then and catchError handlers to handle the results of the Future.
However, one killer feature of Dart (as of version 1.9) is that you can use the async and await keywords to do this with much simpler code; code that looks synchronous. Here is the same code as before, but written without using any callbacks. Note that any function that calls await must have the async keyword. To catch errors, simply wrap the code in a try/catch block.
If there is no try/catch block, then the exception will bubble up. Here is how to catch the exception at the root of your app. Instead of just calling runApp with your root widget, call the runZoned function and provide an onError handler. In there you can log the exception to your analytics platform.