Category: Flutter

Flutter: How to remove the debug banner during development

By default, Flutter shows a debug banner on the top right corner of an app, that indicates that the app was build in debug mode.

In Flutter, you can remove the debug banner by setting the debugShowCheckedModeBanner property of the MaterialApp widget to false. For example:

MaterialApp(
  debugShowCheckedModeBanner: false,
  // ...
)

This will remove the banner at the top right corner that indicates the app is in debug mode.

This banner is only visible in debug mode. When you compile your app in release mode, this banner is not visible at all.

 

Flutter: how to create a better MaterialColor from Color

In Flutter, MaterialColor is a class that defines a color palette to be used within a Material Design app. It creates a set of shades for a given primary color, which can be used in various components of the UI, such as buttons, text fields, and navigation bars. MaterialColor objects can be created from a single color value and then generate shades based on a specified brightness factor. This allows for a consistent and harmonious color scheme throughout the app.

To create a MaterialColor from a Color, you can use the MaterialColor class in Dart. The MaterialColor constructor takes two arguments:

  • The value of the color in RGB.
  • A map of shades of the color with keys representing the shade level and values representing the Color of that shade.

Let’s say we want to create a MaterialColor from the RGB color 176 / 255 / 38:

To use an implementation, let’s create a static method in a MaterialColorGenerator class and call:

Color color = Color.fromARGB(255, 176, 255, 38);
MaterialColor material = MaterialColorGenerator.from(color);

Now there are different ways to define the shades. Most tutorials propose to change the opacity for each shade, which will result in such a code:

import 'package:flutter/material.dart';

class MaterialColorGenerator{
  static MaterialColor from(Color color) {
    return MaterialColor(color.value, <int, Color>{
      50: color.withOpacity(0.1),
      100: color.withOpacity(0.2),
      200: color.withOpacity(0.3),
      300: color.withOpacity(0.4),
      400: color.withOpacity(0.5),
      500: color.withOpacity(0.6),
      600: color.withOpacity(0.7),
      700: color.withOpacity(0.8),
      800: color.withOpacity(0.9),
      900: color.withOpacity(1.0),
    });
  }
}

Let’s take our color example and look at the result:

Color values from shade50 (top) to shade900 (bottom).

This is a good result for lighter colors, but results in very similar colors for the “darker” shades. To create some real color variations, it’s better to adjust the color values itself by using:

import 'package:flutter/material.dart';

class MaterialColorGenerator{
  static MaterialColor from(Color color) {
    List strengths = <double>[.05];
    final swatch = <int, Color>{};
    final int r = color.red, g = color.green, b = color.blue;

    for (int i = 1; i < 10; i++) {
      strengths.add(0.1 * i);
    }
    for (var strength in strengths) {
      final double ds = 0.5 - strength;
      swatch[(strength * 1000).round()] = Color.fromRGBO(
        r + ((ds < 0 ? r : (255 - r)) * ds).round(),
        g + ((ds < 0 ? g : (255 - g)) * ds).round(),
        b + ((ds < 0 ? b : (255 - b)) * ds).round(),
        1,
      );
    }
    return MaterialColor(color.value, swatch);
  }
}

Let’s take our color example and look at the result:

Color values from shade50 (top) to shade900 (bottom).

Now the result is good for “darker” shades (> 500), but there is less variation for the “lighter” colors. Let’s find a version that combines both of the advantages:

import 'dart:math';
import 'package:flutter/material.dart';

class MaterialColorGenerator{
  static MaterialColor from(Color color) {
    return MaterialColor(color.value, {
      50: tintColor(color, 0.9),
      100: tintColor(color, 0.8),
      200: tintColor(color, 0.6),
      300: tintColor(color, 0.4),
      400: tintColor(color, 0.2),
      500: color,
      600: shadeColor(color, 0.1),
      700: shadeColor(color, 0.2),
      800: shadeColor(color, 0.3),
      900: shadeColor(color, 0.4),
    });
  }

  static int tintValue(int value, double factor) =>
      max(0, min((value + ((255 - value) * factor)).round(), 255));

  static Color tintColor(Color color, double factor) => Color.fromRGBO(
      tintValue(color.red, factor),
      tintValue(color.green, factor),
      tintValue(color.blue, factor),
      1);

  static int shadeValue(int value, double factor) =>
      max(0, min(value - (value * factor).round(), 255));

  static Color shadeColor(Color color, double factor) => Color.fromRGBO(
      shadeValue(color.red, factor),
      shadeValue(color.green, factor),
      shadeValue(color.blue, factor),
      1);
}

Let’s take our color example and look at the result:

Color values from shade50 (top) to shade900 (bottom).

This is a much better result, which corelates with the color palettes of the Material Design. This implementation is also used by the material_color_generator package.

Foto von Zden?k Machá?ek auf Unsplash.

 

Flutter: how to sort a list of objects by one of its properties

In Flutter (Dart), you can use the sort method on a list of objects, along with a custom comparator function, to sort the list by the alphabetical order of one of its properties.

Here’s an example of how you can sort a list of objects (let’s say they’re called Person) by their name property:

List<Person> people = [
  Person(name: "Bob"),
  Person(name: "Charlie"),
  Person(name: "Alice"),
];

people.sort((a, b) => a.name.compareTo(b.name));

In this example, the sort method takes a comparator function as its argument. The comparator function compares two Person objects and returns a negative, zero, or positive value, depending on whether the first object should be sorted before, in the same position as, or after the second object. In this case, it compares the name property of each object using the compareTo method and sorts them alphabetically.

Another way to sort by one property is to use the sortBy method from the ‘dart:collection’ package:

import 'dart:collection';

people.sortBy((person) => person.name);

This will sort the list of people based on the name property.

Flutter: slowing down animation for debugging

The library that is responsible for different scheduling is flutter/scheduler. This also includes animations. To use the library, simply import package:flutter/scheduler.dart – in this case, timeDilation is all that you need.

Now you can set the variable timeDilation to a custom double. The value 1.0 is the default animation speed. Setting it to 2.0 will slow down all animations by a factor of two.

import 'package:flutter/scheduler.dart' show timeDilation;

// ...

timeDilation = 2.0; // Slow down animations by factor two

As timeDilation is a global variable, you can set it anywhere in the code, e.g. in main():

import 'package:flutter/scheduler.dart' show timeDilation;

void main() {
  timeDilation = 3.0;
  runApp(new MyApp());
}

Photo by LOGAN WEAVER | @LGNWVR on Unsplash

Flutter: red text and yellow lines in Text widget

When using a text widget, there are some configurations where the text turns red and gets yellow lines. In my case, it looks like in the following image.

The reason for this is a lack of style parameters from the parent widget. The red text shows that there is no color information available. The yellow lines show that text decoration is missing.

In my case, I have a simple text widget in a Row:

Container(
  // ...
  child: Row(
    children: [
      // ...
      Text('External device'),
    ],
  ),
);

To solve the issue, there are different possibilities.

Provide a DefaultTextStyle

DefaultTextStyle(
  style: Theme.of(context).textTheme.bodyText1,
  child: Text('External device'),
),

Use Material

Material(
  color: Colors.transparent,
  child: Text('External device'),
),

Use style parameter of Text

Text(
  'External device',
  style: TextStyle(
    decoration: TextDecoration.none,
    color: Colors.black,
  ),
),

In this case, decoration will remove the yellow lines and color will remove the red text color.

Use Scaffold

A solution discussed in different threads might also be using a Scaffold for the parent widget. But this did not work in case.

Scaffold(
  body: Container(
    // ...
    child: ...
);

GitLab CI + Flutter: pub: command not found

In one of my projects, I used a GitLab environment to perform Flutter tests. For this, I setup my .gitlab-ci.yaml to use a Flutter docker image of cirrusci/flutter for code quality check or tests. The file looks like this:

code_quality:
  stage: test
  image: "cirrusci/flutter:stable"
  tags:
    - docker
  before_script:
    - pub global activate dart_code_metrics
    - export PATH="$PATH":"$HOME/.pub-cache/bin"
  script:
    - metrics lib -r codeclimate  > gl-code-quality-report.json
      
# [...]

test:
  stage: test
  image: "cirrusci/flutter:stable"
  tags:
    - docker
  before_script:
    - pub global activate junitreport
    - export PATH="$PATH":"$HOME/.pub-cache/bin"
  script:
    - flutter test --machine --coverage | tojunit -o report.xml
    - lcov --summary coverage/lcov.info
    - genhtml coverage/lcov.info --output=coverage

# [...]

Up to version 2.10.* of the Flutter docker image, this worked fine. But starting with version 3.0.0, there seems to be some changes in the binaries or their paths. The scripts failed with an error:

/usr/bin/bash: line 123: pub: command not found

To fix this error, the pub commands need to be adjusted and set to flutter pub:

# [...]

  before_script:
    - flutter pub global activate dart_code_metrics

# [...]

  before_script:
    - flutter pub global activate junitreport

# [...]

This fixed the issue and all tests finished successfully.

Build and Release a Flutter App

Updating the app’s version number

To update the version number, navigate to the pubspec.yaml file and update the following line with the current version string:

version: 1.0.0+1

After the change, run:

flutter pub get

Build and release the iOS app

A detailled description of the whole process is described at docs.flutter.dev.

To release the iOS app, you use Flutter to build a xcarchive file. This build archive can be published the same way you would do it with Xcode by using the archive manager and one of the different Distribution options.

Build the iOS app:

flutter build ipa

The generated xcarchive file is saved to your app directory under:

/build/ios/archive/MyApp.xcarchive

Build and release the Android app

A detailled description of the whole process is described at docs.flutter.dev.

To release the Android app, you use Flutter to build a app bundle aab file. This file can be distributed by using Google Play Console or any other store.

Build the Android app:

flutter build appbundle

The generated aab app bundle file is saved to your app directory under:

/build/app/outputs/bundle/release/MyApp.aab

Photo by Artur Shamsutdinov on Unsplash

Flutter: rounded corners for images

There are different possibilities to create a rounded corner of images:

BoxDecoration

To create a rounded corner image in Flutter, you can use the Container widget and set the decoration property to a BoxDecoration with a borderRadius that defines the rounded corners. Here’s an example:

Container(
  height: 100.0,
  width: 100.0,
  decoration: BoxDecoration(
    image: DecorationImage(
      fit: BoxFit.cover, 
      image: NetworkImage('https://example.com/image.jpg'),
    ),
    borderRadius: BorderRadius.circular(10.0),
  ),
),

In this example, the width and height properties of the Container define the size of the image, the DecorationImage property defines the image source and how it should be scaled to fit the container and the borderRadius property is used to create the rounded corners with a Radius.circular(10).

ClipRRect

You can also use ClipRRect widget to create rounded corner Image in flutter.

ClipRRect(
  borderRadius: BorderRadius.circular(10.0),
  child: Image.network(
    'https://example.com/image.jpg',
    height: 100.0,
    width: 100.0,
    fit: BoxFit.cover,
  ),
),

You can adjust the radius value as per your need.

Photo by Chaitanya Tvs on Unsplash