Practical Flutter Extensions for Real-World Development

Practical Flutter Extensions for Real-World Development

You have already read many articles on “What are extensions in Flutter.

Here, I am providing you with a list of useful extensions that I use in my projects.

I have categorized all extensions based on types.

BuildContext extensions:

  1. showSnackbar — Show a snackbar with a message.
import 'package:flutter/material.dart';

extension ShowSnackbar on BuildContext {
  void showSnackbar(String message) {
    ScaffoldMessenger.of(this).showSnackBar(
      SnackBar(
        content: Text(message),
      ),
    );
  }
}

Usage:

context.showSnackbar("Hello from Snackbar!");

2. navigateToRoute — Navigate to a named route.

import 'package:flutter/material.dart';

extension NavigateToRoute on BuildContext {
  void navigateToRoute(String routeName) {
    Navigator.of(this).pushNamed(routeName);
  }
}

Usage:

context.navigateToRoute("/details");

3. popToRoot — Pop all routes and return to the root route.

import 'package:flutter/material.dart';

extension PopToRoot on BuildContext {
  void popToRoot() {
    Navigator.of(this).popUntil((route) => route.isFirst);
  }
}

Usage:

context.popToRoot();

4. hideKeyboard — Hide the keyboard if it’s currently displayed.

import 'package:flutter/material.dart';

extension HideKeyboard on BuildContext {
  void hideKeyboard() {
    FocusScope.of(this).unfocus();
  }
}

Usage:

context.hideKeyboard();

5. getTheme — Get the current theme data from the Theme widget ancestor.

import 'package:flutter/material.dart';

extension GetTheme on BuildContext {
  ThemeData getTheme() {
    return Theme.of(this);
  }
}

Usage:

ThemeData theme = context.getTheme();

6. getMediaQuery — Access the media query data.

import 'package:flutter/material.dart';

extension GetMediaQuery on BuildContext {
  MediaQueryData getMediaQuery() {
    return MediaQuery.of(this);
  }
}

Usage:

MediaQueryData mediaQuery = context.getMediaQuery();

String extensions:

  1. isEmail — Check if a string is a valid email address.
extension EmailValidation on String {
  bool get isEmail {
    final emailRegExp = RegExp(r'^[\w-]+(\.[\w-]+)*@([\w-]+\.)+[a-zA-Z]{2,7}$');
    return emailRegExp.hasMatch(this);
  }
}

Usage:

String email = "example@email.com";
print(email.isEmail); // true

2. isNumeric — Check if a string represents a numeric value.

extension NumericCheck on String {
  bool get isNumeric {
    if (this == null) {
      return false;
    }
    return double.tryParse(this) != null;
  }
}

Usage:

String number = "123.45";
print(number.isNumeric); // true

3. capitalize — Capitalize the first letter of a string.

extension CapitalizeFirstLetter on String {
  String get capitalize {
    if (isEmpty) {
      return this;
    }
    return '${this[0].toUpperCase()}${substring(1)}';
  }
}

Usage:

String text = "hello world";
print(text.capitalize); // "Hello world"

4. truncate — Truncate a string to a specified length.

extension TruncateString on String {
  String truncate(int maxLength) {
    return (length > maxLength) ? '${substring(0, maxLength)}...' : this;
  }
}

Usage:

String longText = "This is a long text that needs to be truncated.";
print(longText.truncate(20)); // "This is a long text..."

5. containsIgnoreCase — Check if a string contains another string (case-insensitive).

extension ContainsIgnoreCase on String {
  bool containsIgnoreCase(String other) {
    return this.toLowerCase().contains(other.toLowerCase());
  }
}

Usage:

String text = "Hello, Flutter!";
print(text.containsIgnoreCase("flutter")); // true

6. removeWhitespace — Remove all whitespace characters from a string.

extension RemoveWhitespace on String {
  String get removeWhitespace {
    return replaceAll(RegExp(r'\s+'), '');
  }
}

Usage:

String text = "  Remove   Whitespace  ";
print(text.removeWhitespace); // "RemoveWhitespace"

7. isPalindrome — Check if a string is a palindrome.

extension PalindromeCheck on String {
  bool get isPalindrome {
    String cleanText = this.replaceAll(RegExp(r'[^a-zA-Z0-9]'), '').toLowerCase();
    String reversedText = cleanText.split('').reversed.join('');
    return cleanText == reversedText;
  }
}

Usage:

String palindrome = "A man, a plan, a canal, Panama";
print(palindrome.isPalindrome); // true

8. words — Split a string into a list of words.

extension WordsSplitter on String {
  List<String> get words {
    return split(RegExp(r'\s+'));
  }
}

Usage:

String text = "Split this text into words";
print(text.words); // ["Split", "this", "text", "into", "words"]

9. replaceAllIgnoreCase — Replace all occurrences of a substring (case-insensitive).

extension ReplaceAllIgnoreCase on String {
  String replaceAllIgnoreCase(String from, String to) {
    return replaceAll(RegExp(from, caseSensitive: false), to);
  }
}

Usage:

String text = "Hello, world! Hello, Flutter!";
print(text.replaceAllIgnoreCase("hello", "hi")); // "Hi, world! Hi, Flutter!"

10. isAlphanumeric — Check if a string contains only alphanumeric characters.

extension AlphanumericCheck on String {
  bool get isAlphanumeric {
    return RegExp(r'^[a-zA-Z0-9]+$').hasMatch(this);
  }
}

Usage:

String alphanumeric = "Hello123";
print(alphanumeric.isAlphanumeric); // true

Int extensions:

  1. isPrime — Check if an integer is a prime number.
extension PrimeCheck on int {
  bool get isPrime {
    if (this <= 1) return false;
    if (this <= 3) return true;
    if (this % 2 == 0 || this % 3 == 0) return false;
    int i = 5;
    while (i * i <= this) {
      if (this % i == 0 || this % (i + 2) == 0) return false;
      i += 6;
    }
    return true;
  }
}

Usage:

int number = 17;
print(number.isPrime); // true

2. factorial — Calculate the factorial of an integer.

extension Factorial on int {
  int get factorial {
    if (this == 0) return 1;
    int result = 1;
    for (int i = 1; i <= this; i++) {
      result *= i;
    }
    return result;
  }
}

Usage:

int n = 5;
print(n.factorial); // 120

3. toBinary and toHex — Convert an integer to a binary or hexadecimal string.

extension IntToBinaryHex on int {
  String get toBinary => this.toRadixString(2);
  String get toHex => this.toRadixString(16);
}

Usage:

int number = 42;
print(number.toBinary); // "101010"
print(number.toHex); // "2a"

4. divisors — Get a list of divisors of an integer.

extension Divisors on int {
  List<int> get divisors {
    List<int> result = [];
    for (int i = 1; i <= this; i++) {
      if (this % i == 0) {
        result.add(i);
      }
    }
    return result;
  }
}

Usage:

int number = 12;
print(number.divisors); // [1, 2, 3, 4, 6, 12]

5. isPerfect — Check if an integer is a perfect number.

extension PerfectNumberCheck on int {
  bool get isPerfect {
    List<int> divisors = this.divisors;
    int sum = divisors.fold(0, (a, b) => a + b) - this;
    return sum == this;
  }
}

Usage:

int perfectNumber = 28;
print(perfectNumber.isPerfect); // true

6. isPowerOfTwo — Check if an integer is a power of two.

extension PowerOfTwoCheck on int {
  bool get isPowerOfTwo {
    return (this != 0) && ((this & (this - 1)) == 0);
  }
}

Usage :

int number = 16;
print(number.isPowerOfTwo); // true

7. nearestPowerOfTwo — Find the nearest power of two greater than or equal to the integer.

extension NearestPowerOfTwo on int {
  int get nearestPowerOfTwo {
    int result = 1;
    while (result < this) {
      result *= 2;
    }
    return result;
  }
}

Usage:

int number = 12;
print(number.nearestPowerOfTwo); // 16

8. toOrdinal — Convert an integer to its ordinal form (e.g., 1st, 2nd, 3rd).

extension ToOrdinal on int {
  String get toOrdinal {
    if (this % 100 >= 11 && this % 100 <= 13) {
      return '${this}th';
    }
    switch (this % 10) {
      case 1:
        return '${this}st';
      case 2:
        return '${this}nd';
      case 3:
        return '${this}rd';
      default:
        return '${this}th';
    }
  }
}

Usage:

int number = 23;
print(number.toOrdinal); // "23rd"

9. digitsSum — Calculate the sum of the digits of an integer.

extension DigitsSum on int {
  int get digitsSum {
    int sum = 0;
    int number = this.abs();
    while (number > 0) {
      sum += number % 10;
      number ~/= 10;
    }
    return sum;
  }
}

Usage:

int number = 12345;
print(number.digitsSum); // 15

10. toWords — Convert an integer to its word representation.

extension IntToWords on int {
  String get toWords {
    final List<String> units = [
      '', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'
    ];
    final List<String> teens = [
      'ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen'
    ];
    final List<String> tens = [
      '', '', 'twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety'
    ];

    String convertToWords(int number) {
      if (number < 10) {
        return units[number];
      } else if (number < 20) {
        return teens[number - 10];
      } else if (number < 100) {
        return '${tens[number ~/ 10]} ${units[number % 10]}'.trim();
      } else if (number < 1000) {
        return '${units[number ~/ 100]} hundred ${convertToWords(number % 100)}'.trim();
      }
      return 'Number out of range';
    }

    return convertToWords(this);
  }
}

Usage:

int number = 123;
print(number.toWords); // "one hundred twenty three"

List extensions:

  1. groupBy — Group a list of objects by a specified key.
extension GroupBy<T, K> on List<T> {
  Map<K, List<T>> groupBy(K Function(T) keySelector) {
    final result = <K, List<T>>{};
    for (var item in this) {
      final key = keySelector(item);
      result[key] ??= [];
      result[key].add(item);
    }
    return result;
  }
}

Usage:

class Person {
  final String name;
  final int age;
  Person(this.name, this.age);
}

List<Person> people = [Person('Alice', 25), Person('Bob', 30), Person('Alice', 28)];
final grouped = people.groupBy((person) => person.name);
print(grouped);
// Output: {Alice: [Person{name: Alice, age: 25}, Person{name: Alice, age: 28}], Bob: [Person{name: Bob, age: 30}]}

2. average — Calculate the average of a list of numeric values.

extension AverageList<T extends num> on List<T> {
  double get average {
    if (isEmpty) return null;
    final sum = this.fold(0, (a, b) => a + b);
    return sum / length;
  }
}

Usage:

List<double> values = [1.0, 2.5, 3.0, 4.5];
double avg = values.average;
print(avg); // 2.75

3. rotate — Rotate the elements of a list to the right by a specified number of positions.

extension RotateList<T> on List<T> {
  List<T> rotate(int positions) {
    final n = this.length;
    final List<T> result = List<T>.filled(n, null, growable: false);
    for (var i = 0; i < n; i++) {
      result[(i + positions) % n] = this[i];
    }
    return result;
  }
}

Usage:

List<int> numbers = [1, 2, 3, 4, 5];
List<int> rotated = numbers.rotate(2);
print(rotated); // [4, 5, 1, 2, 3] (rotated 2 positions to the right)

4. distinctBy — Remove duplicates from a list based on a specified key.

extension DistinctBy<T, K> on List<T> {
  List<T> distinctBy(K Function(T) keySelector) {
    final Set<K> seenKeys = {};
    final List<T> result = [];
    for (var item in this) {
      final key = keySelector(item);
      if (!seenKeys.contains(key)) {
        seenKeys.add(key);
        result.add(item);
      }
    }
    return result;
  }
}

Usage:

class Fruit {
  final String name;
  final String color;
  Fruit(this.name, this.color);
}

List<Fruit> fruits = [Fruit('Apple', 'Red'), Fruit('Banana', 'Yellow'), Fruit('Apple', 'Green')];
final distinctFruits = fruits.distinctBy((fruit) => fruit.name);
print(distinctFruits);
// Output: [Fruit{name: Apple, color: Red}, Fruit{name: Banana, color: Yellow}]

5. interleave — Interleave the elements of two lists.

extension InterleaveLists<T> on List<T> {
  List<T> interleave(List<T> other) {
    final List<T> result = [];
    final minLength = math.min(this.length, other.length);
    for (var i = 0; i < minLength; i++) {
      result.add(this[i]);
      result.add(other[i]);
    }
    result.addAll(this.sublist(minLength));
    result.addAll(other.sublist(minLength));
    return result;
  }
}

Usage:

List<int> list1 = [1, 3, 5];
List<int> list2 = [2, 4, 6];
List<int> interleaved = list1.interleave(list2);
print(interleaved); // [1, 2, 3, 4, 5, 6]

6. flatten — Flatten a list of lists into a single list.

extension FlattenLists<T> on List<List<T>> {
  List<T> flatten() {
    return this.fold([], (result, list) => result..addAll(list));
  }
}

Usage:

List<List<int>> nestedList = [[1, 2], [3, 4], [5, 6]];
List<int> flatList = nestedList.flatten();
print(flatList); // [1, 2, 3, 4, 5, 6]

Follow me for more:

Portfolio
LinkedIn