Skip to content

Implicitly animated widgets' transitions occur after FAnimatedTheme's transition #670

@Pante

Description

@Pante

Describe the bug
This affects FTextField and other components, including the majority of Material, that rely on implicitly animated widgets, i.e. AnimatedDefaultTextStyle and AnimaterContainer.

These affected widgets' transitions will occur AFTER rather than during FAnimatedTheme's transition. This is a known longstanding issue with Flutter. See flutter/flutter#3325.

Screen.Recording.2025-08-25.at.4.44.35.PM.mov

There isn't much we can do on our side in the short-term. Our long-term goal is to migrate FTextField from internally using Material's TextField to RawTextField if and when that becomes available. EditableText is far too low level and requires fair too much effort to replace TextField with while retaining UX parity.

To Reproduce

  1. Use the following code snippet:
class Application extends StatefulWidget {
  const Application({super.key});

  @override
  State<Application> createState() => _ApplicationState();
}

class _ApplicationState extends State<Application> with SingleTickerProviderStateMixin {
  int themeIndex = 0;

  @override
  Widget build(BuildContext context) {
    final currentTheme = themes[themeIndex].$2;
    return MaterialApp(
      locale: const Locale('en', 'US'),
      localizationsDelegates: FLocalizations.localizationsDelegates,
      supportedLocales: FLocalizations.supportedLocales,
      theme: themeIndex.isEven ? ThemeData.light() : ThemeData.dark(),
      builder: (context, child) => FAnimatedTheme(data: currentTheme, child: child!),
      home: Builder(
        builder: (context) {
          return Scaffold(
            body: ThemeDemo(
              themeIndex: themeIndex,
              onNextTheme: () => setState(() => themeIndex = (themeIndex + 1) % 14),
            ),
          );
        },
      ),
    );
  }
}

class ThemeDemo extends StatelessWidget {
  final int themeIndex;
  final VoidCallback onNextTheme;

  const ThemeDemo({required this.themeIndex, required this.onNextTheme, super.key});

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(16.0),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        spacing: 5,
        children: [
          FCard(
            child: Column(
              spacing: 16,
              children: [
                FTextField(label: const Text('Lorem Ipsum'), hint: 'Enter some text...'),
              ],
            ),
          ),
          FButton(onPress: onNextTheme, prefix: const Icon(FIcons.arrowRight), child: const Text('Next')),
        ],
      ),
    );
  }
}
  1. Press the "Next" button.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions