Flutter

718 readers
1 users here now

Flutter and the related logo are trademarks of Google LLC. We are not endorsed by or affiliated with Google LLC

founded 2 years ago
MODERATORS
1
4
submitted 1 week ago* (last edited 1 week ago) by enjoyingfoss to c/flutter
 
 

I'm trying to implement the OpenContainer transition for go_router in Flutter. It seems like no matter what I do, the end result is choppy. :/

I'm using the native Transition widgets as well as the relatively new SnapshotWidget, but to no avail. Should I maybe use a custom painter? Would that improve performance?

Please take a look at the code below and let me know if you see any ways that I could improve performance.


Here's my attempt at an OpenContainer transition for go_router:

import 'package:flutter/material.dart';
import 'package:your_project_name_xxx/ui_models/container_transition_extra.dart';

class ContainerTransition extends StatefulWidget {
  final ContainerTransitionExtra extra;
  final Animation<double> animation;
  final Widget? sourceWidget;
  final Widget targetWidget;

  const ContainerTransition({
    super.key,
    required this.extra,
    required this.animation,
    required this.sourceWidget,
    required this.targetWidget,
  });

  @override
  State<ContainerTransition> createState() => _ContainerTransitionState();
}

class _ContainerTransitionState extends State<ContainerTransition> {
  static final _toTween = Tween<double>(begin: 0, end: 1);
  static final _fromTween = Tween<double>(begin: 1, end: 0);

  late SnapshotController _snapshotController;
  late CurvedAnimation _curvedAnimation;
  late CurvedAnimation _sourceAnimation;
  late CurvedAnimation _targetAnimation;

  late RelativeRect? _sourcePosition;
  late Animation<double> _scrimOpacityAnimation;
  late Animation<double> _sourceOpacityAnimation;
  late Animation<double> _targetOpacityAnimation;
  late Animation<BorderRadius?> _containerRadiusAnimation;
  late Animation<RelativeRect> _containerPositionAnimation;

  @override
  void initState() {
    super.initState();
    _sourcePosition = widget.extra.tween.begin;
    _snapshotController = SnapshotController(allowSnapshotting: true);
    _curvedAnimation = CurvedAnimation(
      parent: widget.animation,
      curve: Curves.easeInOut,
    );
    _curvedAnimation.addStatusListener((status) {
      if (status.isAnimating) {
        _snapshotController.allowSnapshotting = true;
      } else if (status.isCompleted || status.isDismissed) {
        _snapshotController.allowSnapshotting = false;
      }
    });
    _sourceAnimation = CurvedAnimation(
      parent: _curvedAnimation,
      curve: Interval(0, 1 / 3),
    );
    _targetAnimation = CurvedAnimation(
      parent: _curvedAnimation,
      curve: Interval(1 / 3, 1),
    );
    _scrimOpacityAnimation = _toTween.animate(_sourceAnimation);
    _sourceOpacityAnimation = _fromTween.animate(_sourceAnimation);
    _targetOpacityAnimation = _toTween.animate(_targetAnimation);
    _containerRadiusAnimation = BorderRadiusTween(
            begin: BorderRadius.circular(widget.extra.containerRadius),
            end: BorderRadius.zero)
        .animate(_curvedAnimation);
    _containerPositionAnimation = _curvedAnimation.drive(widget.extra.tween);
  }

  @override
  void dispose() {
    _snapshotController.dispose();
    _sourceAnimation.dispose();
    _targetAnimation.dispose();
    _curvedAnimation.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        Positioned.fill(
          child: FadeTransition(
            opacity: _scrimOpacityAnimation,
            child: ColoredBox(color: widget.extra.scrimColor),
          ),
        ),
        PositionedTransition(
          rect: _containerPositionAnimation,
          child: DecoratedBox(
            decoration: BoxDecoration(
              borderRadius: _containerRadiusAnimation.value,
              color: widget.extra.containerColor,
            ),
            child: FadeTransition(
              opacity: _targetOpacityAnimation,
              child: widget.targetWidget,
            ),
          ),
        ),
        if (_sourcePosition != null)
          Positioned.fromRelativeRect(
            rect: _sourcePosition!,
            child: FadeTransition(
              opacity: _sourceOpacityAnimation,
              child: widget.sourceWidget,
            ),
          ),
      ],
    );
  }
}

Here's how I'm building the route:

Page<T> buildContainerRoute<T>(
    BuildContext context,
    GoRouterState state,
    Ref ref,
    Widget child,
  ) {
    final containerExtra = state.extra;

    if (containerExtra is ContainerTransitionExtra) {
      final registryTag = containerExtra.sourceBuilderTag;
      final registryBuilder =
          registryTag != null ? SourceBuilderRegistry().get(registryTag) : null;
      if (registryBuilder != null) {
        if (registryBuilder.wasUsedAlready) {
          SourceBuilderRegistry().unregister(registryTag!);
        } else {
          SourceBuilderRegistry().markAsUsed(registryTag!);
        }
      }
      return CustomTransitionPage<T>(
        key: state.pageKey,
        child: child,
        transitionDuration: Durations.medium2,
        reverseTransitionDuration: Durations.medium1,
        transitionsBuilder: (context, animation, secondaryAnimation, child) {
          return ContainerTransition(
            animation: animation,
            extra: containerExtra,
            sourceWidget:
                Center(child: registryBuilder?.registryItem.call(context)),
            targetWidget: ClipRect(
              child: OverflowBox(
                alignment: Alignment.topCenter,
                maxWidth: containerExtra.cachedMaxWidth,
                maxHeight: containerExtra.cachedMaxHeight,
                child: child,
              ),
            ),
          );
        },
      );
    } else {
      if (!kIsWeb && Platform.isAndroid) {
        return MaterialPage(key: state.pageKey, child: child);
      } else {
        return CupertinoPage(key: state.pageKey, child: child);
      }
    }
  }
2
3
 
 

Hey Flutter devs! I'm excited to announce the release of Hive CE v2.11.0-pre, introducing a new interface called IsolatedHive—a safe way to use Hive across multiple isolates.

What's New:

  • IsolatedHive Interface: Enables safe Hive usage across isolates by maintaining its own dedicated isolate for database operations. It utilizes an IsolateNameServer behind the scenes to locate the Hive isolate.
  • Flutter Integration: Simply call IsolatedHive.initFlutter from hive_ce_flutter to automatically set things up to use Flutter's built-in IsolateNameServer.
  • Generated Extensions: The latest hive_ce_generator now provides the same easy-to-use registerAdapters extension on IsolatedHive.

Why Use IsolatedHive?

You might already be using isolates without realizing it! Common Flutter scenarios benefiting from isolate-safe Hive:

  • Desktop apps with multiple windows
  • Background task handling (flutter_workmanager, background_fetch, etc.)
  • Push notification processing

Note: Hive now prominently warns you if it detects unsafe isolate usage.

🎥 Multi-window Demo:

Video: https://files.catbox.moe/stb5gs.mov

Repo: https://github.com/Rexios80/hive_ce_multiwindow

Performance Considerations:

While IsolatedHive adds overhead due to isolate communication and isn't quite as fast as regular Hive CE, it's significantly faster and leaner than Hive v4:

Operations Hive CE Time IsolatedHive Time Hive CE Size Hive v4 Time Hive v4 Size
10 0.00 s 0.00 s 0.00 MB 0.00 s 1.00 MB
100 0.00 s 0.01 s 0.01 MB 0.01 s 1.00 MB
1000 0.02 s 0.03 s 0.11 MB 0.06 s 1.00 MB
10000 0.13 s 0.25 s 1.10 MB 0.64 s 5.00 MB
100000 1.40 s 2.64 s 10.97 MB 7.26 s 30.00 MB
1000000 19.94 s 41.50 s 109.67 MB 84.87 s 290.00 MB

Stability & Testing:

This pre-release is as stable as possible without real-world external testing—your feedback is invaluable!

Check it out, give it a spin, and share your experience:

Happy coding! 🐝✨

4
 
 

Hi everyone!

I've just released a new Dart package: isolate_channel. It provides a simple and familiar API for handling communication between Dart isolates, directly inspired by Flutter's MethodChannel and EventChannel APIs used for native plugin communication.

If you've ever found Dart isolate communication cumbersome or unintuitive, isolate_channel streamlines this process, making it feel as straightforward and familiar as working with Flutter plugin channels.

I built this package to prepare for upcoming isolate support in Hive CE, and it made that work a lot easier!

Check it out here: isolate_channel

I'd love your feedback or contributions!

5
 
 

cross-posted from: https://lemm.ee/post/56160274

I install Android Studio via flatpak, and this can cause flutter doctor to not be able to determine the version or to not recognize the installation at all. I've managed a hacky fix for this by running a few commands that I run as a simple script that I'm sharing here. If you use this, just close Android Stuido after it is opened; it seems to just need to be opened once in order to be recognized by flutter doctor.

#!/bin/bash

flutter config --android-studio-dir=/var/lib/flatpak/app/com.google.AndroidStudio/current/active/files/extra/android-studio

/var/lib/flatpak/app/com.google.AndroidStudio/current/active/files/extra/android-studio/bin/studio

flutter config --android-studio-dir=""

flutter doctor
6
8
submitted 2 months ago* (last edited 2 months ago) by [email protected] to c/flutter
7
 
 

After considering the opportunity cost — in particular, the features we could be shipping to the community instead — we’ve made the difficult decision to stop our work on macros.

8
11
submitted 2 months ago* (last edited 2 months ago) by [email protected] to c/flutter
9
1
submitted 3 months ago* (last edited 3 months ago) by canopas_software to c/flutter
 
 

Crafted with love and powered by Flutter, GroupTrack ensures your family stays connected and secure.

With a sleek design and solid architecture, GroupTrack keeps your loved ones close effortlessly — no matter the distance.

Features You'll Love:

  • Create & Join Spaces
  • Live Location Tracking & Sharing
  • Place Notifications & Real-Time Chat

Available now on Play Store! 👇

https://play.google.com/store/apps/details?id=com.canopas.yourspace

Upcoming Security Enhancements

We’re stepping up our game to prioritize your privacy with:

✔ Signal Protocol for secure data transmission

✔ AES-256 Client-Side Encryption

✔ Zero-Knowledge Architecture for utmost privacy

✔ Unique Encryption Keys per user and space

Let’s keep your loved ones close, connected, and safe! ❤️

We value your feedback and ideas to make it even better!

Explore the Project!! 👇

https://github.com/canopas/group-track-flutter

10
 
 

Hey Flutter Devs!!

Say hello to Cloud Gallery—your new favorite way to manage photos and videos!

The open-source Flutter app offers seamless Google Drive and Dropbox integration, ensuring your memories stay safe, organized, and always within your reach.

Key Features 🌟

  • Sync Across Platforms with Automatic Backups
  • Effortless File Transfers and Organized Storage
  • Cross-Device and Cross-Platform Compatibility
  • Secure and User-Friendly Experience

Available now on both Android and iOS!

We’d love to hear your thoughts and ideas to improve Cloud Gallery!

Explore the Project!! https://github.com/canopas/cloud-gallery

11
3
submitted 3 months ago* (last edited 3 months ago) by [email protected] to c/flutter
 
 

Hi! I'm a flutter developer and I've recently switched from Ubuntu to Bluefin (based on Fedora Silverblue) I was trying to install flutter and all the dependencies it asks for when running flutter doctor and while for clang++, cmake and ninja I have been able to install them with Homebrew (brew install llvm cmake ninja) and the warning went away, flutter seems not to detect GTK 3.0 development libraries when installed through homebrew (brew install gtk+3)

After having looked a little bit online, I've seen that the problem is probably that it's searching the libraries in the wrong place and in fact even when I run pkg-config --modversion gtk+-3.0 I see the library as missing. Therefore, I tried setting the PKG_CONFIG_PATH env variable to the folder where brew installed my libraries (/home/linuxbrew/.linuxbrew/opt/gtk+3/lib/pkgconfig) and after that the output of the pkg-config program above is the one expected. However, this doesn't seem to fix the issue with flutter doctor... why? where should I specify this path for flutter to notice it then?

EDIT: I found out that I was almost right! The PKG_CONFIG_PATH env variable is what flutter looks at to find GTK-3 libraries, but should be set to /home/linuxbrew/.linuxbrew/lib/pkgconfig (if pkg-config has been installed through brew as I did) and then everything will work properly.

12
 
 

Hello Flutter community! I am proud to announce that I have released the largest update to Hive Community Edition yet. Version 2.8.0 adds support for the new GenerateAdapters annotaiton which greatly improves the code generation experience. With the GenerateAdapters annotation, you only specify the classes you want to generate adapters for. No more manually annotating every type and field and keeping track of their IDs.

I also developed a migration tool to help transition from the old annotations. This migration tool makes sure your model classes do not have commmon issues that would result in data integreity issues and then generates the necessary files.

You can see the documentation for the update here: https://pub.dev/packages/hive_ce#store-objects

13
 
 

Maybe we should have switched to C#, @flutter, or @slint, instead of porting from #Qt5 to #Qt6.

@qt

#Programming #CPlusPlus #Sigh

14
 
 

Hello! I'm the maintainer of Hive Community Edition.

I am proposing to introduce a new annotaiton called @GenerateAdapters. This allows you to generate TypeAdapters for types without explicitly annotating any types or fields. This is much easier to maintian and also allows generating adapters for types outside the current package.

For example:

@GenerateAdapters([
  AdapterSpec<ClassSpec1>(),
  AdapterSpec<ClassSpec2>(),
  AdapterSpec<EnumSpec>(),
])
void _() {}

This will generate type adapters for all the types specified. The main difference between using @GenerateAdapters and explicit annotations is that type IDs and field indexes are determined automatically. This information is then stored in a hive_schema.yaml file which informs future generations which type IDs and field indexes are in use.

My main concern is introducing this feature in a way that allows any future changes to be non-breaking. I believe I have eliminated most of the risk by basing the annotation off of mockito. At the moment there aren't actually any fields in the AdapterSpec class, but adding any in the future will not be a breaking change.

I would really appreciate any feedback the Hive community has on this. If you want to try out the @GenerateAdapters annotation to see how it works in your project, add the following to your pubspec:

dependency_overrides:
  hive_ce:
    git:
      url: https://github.com/IO-Design-Team/hive_ce
      ref: ec6e8d7dfc81a4adb3a9ae9eca0e78bc104116d8
      path: hive
  hive_ce_generator:
    git:
      url: https://github.com/IO-Design-Team/hive_ce
      ref: ec6e8d7dfc81a4adb3a9ae9eca0e78bc104116d8
      path: hive_generator

See the new documentation here

Note that this is a breaking change for the generator, as hive_registrar.g.dart has moved to hive/hive_registrar.g.dart to not clutter the lib folder. I have created a migration guide here

15
 
 

I have just released my latest app!
IdentiFace PRO: a free and open source multiplatform face recognition app!

Check it out: https://wp.me/p6raR-h3

@flutter

16
17
18
 
 

I just released firebase_js_interop which allows you to compose Firebase Cloud Functions in the Dart language. Along with my firebase_rules package it is now possible to create an entire Firebase project with only type-safe Dart code! There are a lot of components missing, but writing the interop code is tedious, not hard. With third-party contributions we should be able to get close to full interop quickly.

19
 
 

The pubstats.dev page keeps track of historical pub.dev data. I just made it so that it can also show the rank of a package on pub.dev based on its popularity score. For example dio is rank 20 right now.

If you haven't seen pubstats.dev before here are some other features:

  • Like count and popularity score tracked over time for all packages on pub.dev
  • Historical tracking of a lot of package metadata such as version and dependents
  • Compare like count and popularity graphs across multiple packages (ex https://beta.pubstats.dev/#/packages/dio,http)
  • If you sign in you can set up alerts for package info changes. Very useful for making sure you have maximum pub points! There are only Discord webhook alerts for now since that's what I use personally, but if you'd like to see more options feel free to contribute on GitHub.

As an added bonus, https://beta.pubstats.dev uses the new WASM renderer. Thanks to the Flutter team for helping me make that possible! There is some weirdness with Google OAuth still with WASM (see this issue), but everything else works. If you want to set up Discord notifications you might want to use the stable https://pubstats.dev for now.

20
21
 
 

Since Hive v2 has been abandoned and v3/v4 are nowhere to be seen I decided to hard fork Hive into Hive Community Edition (hive_ce, hive_ce_fluter, hive_ce_generator). Originally hive_ce was just going to be in maintenance mode to keep up to date with the evolving Flutter/Dart ecosystem (mainly Flutter WASM support right now), but there are some things that bothered me too much to ignore.

First of all... Hive v2 didn't support Sets. Why? I don't know but hive_ce does. Hive boxes natively support the Set type and the generator supports classes with Set fields.

One of the main pain points with TypeAdapters was remembering to register them all. Well forget no longer because hive_ce_generator generates an extension method on Hive to register them all in one go:

import 'package:your_package/hive_registrar.g.dart';

void main() {
  final path = Directory.current.path;
  Hive
    ..init(path)
    ..registerAdapters();
}
22
 
 

It has been a year since I decided to start learning Flutter [https://programming.dev/post/186393](Original Post), and it has been an amazing experience. Throughout this year, I managed to land an internship as a Flutter developer, get a decent job as a Flutter developer, and graduate with a computer science degree. So for anyone who is hesitating to start learning Flutter out of fear of the job market, I can tell you not to worry, there are a lot of jobs available. Some good resources to start with are the official Flutter documentation (which is incredible), as well as the official Flutter YouTube channel.

Finally, thanks to everyone who helped me when I was starting with Flutter, and good luck to all those who are just getting started.

23
 
 

My phone (Samsung A14) is low-end, and lags while using an app made with Flutter.

24
25
view more: next ›