Skip to content

Instantly share code, notes, and snippets.

@nouvist
Last active May 25, 2024 18:42
Show Gist options
  • Save nouvist/9a8633df9cc7e64cff366113cc421c2d to your computer and use it in GitHub Desktop.
Save nouvist/9a8633df9cc7e64cff366113cc421c2d to your computer and use it in GitHub Desktop.
Flutter Extensions

🎯 Epic Dart/Flutter Extensions Snippets

In JavaScript, messing with the native objects' prototypes is a bad idea. It can cause problems with third-party libraries that rely on it. But Dart have extension just like how C# does. It allows you to add new methods to existing classes without creating new derivatives nor modifying the original classes (like changing the prototype in JS). This is totally fine in Dart and C# and not a bad practice at all. I've made some Dart extensions snippets for myself and I want to share it here.

Extra Double methods

extension DoubleExtension on double {
  double clampLower(double value) => max(this, value);
  double clampUpper(double value) => min(this, value);

  double normalize(double lowerBound, double upperBound) =>
      (this - lowerBound) / (upperBound - lowerBound);

  double lerp(double lowerBound, double upperBound) =>
      this * (upperBound - lowerBound) + lowerBound;

  double complementary() => 1 - this;
}

Extra Clamp for Int too

extension IntExtension on int {
  int clampLower(int value) => max(this, value);
  int clampUpper(int value) => min(this, value);
}

Easy GlobalKey Offset and Size

extension GlobalKeyExtension on GlobalKey {
  RenderBox? findRenderBox() {
    return currentContext?.findRenderObject() as RenderBox;
  }

  Size? calculateWidgetSize() {
    return findRenderBox()?.size;
  }

  Offset? calculateWidgetOffset([RenderObject? ancestor]) {
    final vec = findRenderBox()?.getTransformTo(ancestor).getTranslation();
    if (vec == null) return null;
    return Offset(vec.x, vec.y);
  }
}

Orientation boolean

extension OrientationExtension on Orientation {
  bool get isPortrait => this == Orientation.portrait;
  bool get isLandscape => this == Orientation.landscape;

  Orientation get opposite =>
      isPortrait ? Orientation.landscape : Orientation.portrait;
}

Brightness boolean

extension BrightnessExtension on Brightness {
  bool get isLight => this == Brightness.light;
  bool get isDark => this == Brightness.dark;
  
  Brightness get opposite => isLight ? Brightness.dark : Brightness.light;
}

TargetPlatform boolean

extension TargetPlatformExtension on TargetPlatform {
  bool get isAndroid => this == TargetPlatform.android;
  bool get isIOS => this == TargetPlatform.iOS;
  bool get isMobile => isAndroid || isIOS;
  bool get isDesktop => !isMobile;
}

Images

extension UiImage on ui.Image {
  Future<img.Image?> toEncodableImage() async {
    final byteData = await toByteData();
    if (byteData == null) return null;

    return img.Image.fromBytes(
      width: width,
      height: height,
      order: img.ChannelOrder.rgba,
      bytes: byteData.buffer,
    );
  }
}

extension ImgImage on img.Image {
  Future<ui.Image> toUiImage() async {
    final codec = await ui.instantiateImageCodec(img.encodePng(this));
    final info = await codec.getNextFrame();
    return info.image;
  }
}

TimeOfDay

extension TimeOfDayExtension on TimeOfDay {
  int get _comparator => hour * 60 + minute;

  bool isBefore(TimeOfDay compareTo) {
    return _comparator < compareTo._comparator;
  }

  bool isAfter(TimeOfDay compareTo) {
    return _comparator > compareTo._comparator;
  }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment