Digital Transformation and Complex Layouts Made Easy with Flutter

by Dec 6, 2019#CrossPlatform

f

Digital Transformation with Flutter

The Flutter framework from Google aims to assist developers in tackling this challenge by letting them develop one user interface from a single code base that can be used to make natively compiled applications for not just mobile, but web and desktop as well. Flutter isn’t just a cross-platform solution; in some cases, it is easier to make a user interface in Flutter than it is to make it even on one native platform. Combined with Android Studio and Dart, Flutter offers a variety of development features that make iteration of design faster and more straightforward than it ever has been natively.  This is part of what makes the Flutter framework a great solution for digital business transformation.

Flutter allows the developer to edit the design code while the app is running. Every time the developer saves, the mobile app can refresh using something Google calls Stateful Hot Reload. Relating graphical elements to each other often called constraints in iOS and Android development, has also been simplified for the developer. As I demonstrate with the following example, screens that could require many constraints contained in an almost unreadable XML file on iOS can be simplified to a few lines of code in Dart using Flutter.

Nested Colors Example

One of the enormous advantages Flutter user interface development has over iOS is in creating heavily nested layouts. Usually, developers want to avoid this as much as possible, but often it is necessary to make complex and beautiful layouts. To demonstrate the differences between creating layouts in Flutter versus natively, I have built a single screen app in both iOS and Flutter. The app displays 7 buttons of different colors that are nested inside each other. Here is the final look of the app using Flutter:

Now more than ever before, businesses need to be a part of the mobile space. For customers, it is no longer acceptable for a company not to have undergone some form of digital transformation. People want quick and easy access to everything from their bank account to the lock on their front door. Whether they are at home, work, or vacation, people have come to expect every service to be available from their mobile device. This can be a challenge for businesses and developers because the demand for services is constant, and the mobile space often requires rapid change.

One of the frequently encountered hurdles is the demand for fluid, beautiful, and practical design. A user interface may need to be updated often to achieve this. When mobile started, designs were simple and applications often only had a single screen, but now mobile apps are expected to do so much more. Interfaces can become quite complex to develop even when they are simple to use.

Digital Transformation with Flutter example app preview

Creating the iOS Project for Nested Colors

Let’s make this layout on iOS using storyboard and constraints. Note that in the future, a better implementation could probably be with the new SwiftUI, but for this example, let’s go ahead and use the most common approach for iOS. First, make a new iOS application using Xcode’s “Single View App” template. I’ve named my project “Nested Colors.”

In the ViewController.m we are going to add a little bit of code to make our navigation bar look the way we want it to:

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    UINavigationBar *loNavigationBar = self.navigationController.navigationBar;
    loNavigationBar.barTintColor = [UIColor blackColor];
    loNavigationBar.titleTextAttributes = @{NSForegroundColorAttributeName : [UIColor whiteColor]};
    [self setTitle:@"Nested Colors"];
    [self.navigationController setNavigationBarHidden:NO];
}

All we are doing is making the navigation bar black with the white text “Nested Colors”.  Now open the Main.storyboard.  Since the storyboard won’t let us nest UIButtons we will use UIViews. 

Nested Views Layout

You may have noticed in the image of the final app that the width of the red, orange, yellow, green, dark green and blue on either side of the purple are the same. Each color has the same visible width on the left and right as well as the same visible height on the top and bottom. The last color, the purple, fills in enough of the blue, so the blue has the same visible width and height as its superviews.

It turns out we don’t exactly have the tools to achieve this easily in Storyboard. This isn’t by accident though, since as I mentioned before, typically you don’t want to have too many nested views. Nested views have a negative impact on performance and are discouraged on both iOS and Android. In this case, I think the best tool we have is a type of width constraint called Proportional Width Constraint.

Adding the Colors

Add the first colored UIView to the ViewController Scene and name it “Red”.  Pick a red color you like and add the following constraints:

  1. Red Top to SafeArea Top = 10
  2. SafeArea Bottom to Red Bottom = 10
  3. Red Center Horizontally

Next, to add the width, create a constraint between the superview “View” and “Red” to have Equal Widths.  Then open up the constraint settings and change the multiplier to 0.94.  If it doesn’t look right, make sure the first item is the “Red” view in the constraint.

iOS constraints for Red view

Let’s add the rest of the colors.  Since the width is proportional, we cannot simply set every view to have a multiplier of 0.94 of the width of its superview.  You can try this out to see what happens.  Instead, we will have to set a unique multiplier for every view.  I’ve come up with some multipliers that roughly achieve our layout goals for this example.  Here are all the constraints once I’ve added all the colors:

All iOS constraints for example

The iOS Solution

iOS example app preview

We can finally run the app and see our nested colors design.  It isn’t perfect and it took 34 constraints, but at least it’s done right?  Though what if you needed to remove the dark green?  Or add a pink after the purple?  Or simply make the visible width or height of each color bigger or smaller?  These sorts of changes wouldn’t be massive, but it would certainly take more work than it should. 

Even worse, if another developer was editing the content of the “Red” view while we were editing the layout, we would have a painful merge.  Take a look at the XML file for this storyboard.  You will notice all the views are represented by IDs instead of by the easy to read names we gave them.  This means when editing Storyboards, it is best if only one developer is working on the file at a time to avoid merging. If a project requires a lot of user interface development, this can easily become a bottleneck.

Flutter Digital Transformation Solution

Now that we have implemented our example on iOS lets make it using Flutter.  Instead of developing our design with a Storyboard, we are going to make our entire interface in Dart.  Not only will the Flutter app run on iOS, but it will also run on Android from the same Dart code.

When you make a new Flutter project in Android Studio you’ll get the code for an example project in the main.dart.  We aren’t going to need anything from the sample so go ahead and replace it with our Flutter code for Nested Colors.

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Nested Colors',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Nested Colors'),
          backgroundColor: Colors.black,
        ),
        body: SafeArea(
          child: Center(
            child: new ColorButton(color: Colors.red,
              child: new ColorButton(color: Colors.orange,
                child: new ColorButton(color: Colors.yellow,
                  child: new ColorButton(color: Colors.green,
                    child: new ColorButton(color: Colors.teal,
                      child: new ColorButton(color: Colors.blue,
                        child: new ColorButton(color: Colors.purple
                        ),
                      ),
                    ),
                  ),
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }
}

class ColorButton extends StatelessWidget {
  ColorButton({
    Key key,
    @required this.color,
    this.child,
  }) : super(key: key);

  final MaterialColor color;
  final Widget child;

  @override
  Widget build(BuildContext context) {
    return Container(
      width: double.infinity,
      height: double.infinity,
      child: Padding(
        padding: EdgeInsets.all(10.0),
        child: FlatButton(
          color: this.color,
          child: this.child,
          onPressed: () {
            print('User pressed the '$color' button!');
          },
        ),
      ),
    );
  }
}

That’s it. If I run the app, I can see our Nested Colors app design. This time the buttons have an onPress action that logs the color of the button we pressed. The button press even has a decent default animation from the FlatButton Widget.

Even better is that if I wanted to add or remove a color from the nested stack, it would only require changing one line of code.  Moreover, if I wanted to change the width, I would only have to change it in one place. In Flutter, everything is a Widget, even the app itself. We were able to reuse a custom Widget named “ColorButton” for every view in the stack.

This is a straightforward example, but you can see that constraints work differently in Flutter. Also since the layout is written in Dart, you can easily make complex layouts. Imagine that instead of using colors that is always the same, if I had instead passed a “ColorModel” reference to the “ColorButton.” I could listen for changes to the ColorModel belonging to the ColorButton. That means if the innermost button (the purple button) had its color changed to pink, I could easily ask Flutter to redraw that view without redrawing the entire tree of nested views. With Flutter, complex nested views don’t have to mean poor performance.

When to Choose Flutter

Flutter is a wonderful option for mobile applications with elaborate designs that run cross-platform. However, it isn’t always the best solution. For some features like Bluetooth, you would create something called platform channels and then write the native solutions for Android and iOS separately. If your Bluetooth app didn’t have a sophisticated design and was only going to run on iOS, it might make more sense to develop a native application in Swift or Objective-C. 

For businesses looking to use the cloud or interact with their customers on mobile for the first time, Flutter has a lot of potential. Many businesses don’t need apps with features that would require native code and platform channels. Also, every day as Flutter grows, more plugins become available from both the Google Flutter Team and the Flutter developer community that provide easy cross-platform access to features. (Flutter Packages) This example only scratches the surface of the powerful user interface development tool that Flutter can be for the digital transformation of any business.

About Us: Krasamo is a mobile app development company focused on the Internet-of-Things and Digital Transformation.

Click here to learn more about our mobile development services.