Text loses style during hero animation in Flutter
Asked Answered
S

4

5

As you can see from the gif and from the code below I have a container and a text widget, both wrapped in a hero widget.

When the container is clicked the second page opens. I would like to have a hero animation for both widgets.

The animations of the container works great. The text however seems to lose the style while the transition is happening.

Any idea on how to fix it?

Tranition

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const HomeScreen(),
      routes: {
        HomeScreen.routName: (context) => const HomeScreen(),
        SecondSceen.routeName: (context) => const SecondSceen(),
      },
    );
  }
}

class HomeScreen extends StatelessWidget {
  static const routName = '/home-screen';

  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(children: [
        Align(
          alignment: Alignment.bottomCenter,
          child: InkWell(
            onTap: () => Navigator.of(context).pushNamed(SecondSceen.routeName),
            child: Hero(
              tag: 'box',
              child: Container(
                color: Colors.amber,
                width: MediaQuery.of(context).size.width * 0.8,
                height: 210,
              ),
            ),
          ),
        ),
        Align(
          alignment: Alignment.bottomCenter,
          child: SizedBox(
            width: MediaQuery.of(context).size.width * 0.8,
            height: 210,
            child: Padding(
              padding: const EdgeInsets.fromLTRB(16, 16, 8, 16),
              child: Column(
                children: const [
                  Hero(
                    tag: 'text',
                    child: Text(
                      "MY HEADER",
                      style:
                          TextStyle(fontSize: 28, fontWeight: FontWeight.bold),
                    ),
                  ),
                ],
              ),
            ),
          ),
        ),
      ]),
    );
  }
}

class SecondSceen extends StatelessWidget {
  static const routeName = '/note-screen';

  const SecondSceen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      extendBodyBehindAppBar: true,
      appBar: AppBar(
        backgroundColor: Colors.transparent,
        shadowColor: Colors.transparent,
        foregroundColor: Colors.black,
        centerTitle: true,
        title: const Hero(
          tag: 'text',
          child: Text(
            "MY HEADER",
            style: TextStyle(fontSize: 28, fontWeight: FontWeight.bold),
          ),
        ),
      ),
      body: Stack(children: [
        Hero(
          tag: 'box',
          child: Container(
            color: Colors.amber,
          ),
        ),
      ]),
    );
  }
}
Stonefly answered 23/11, 2022 at 16:42 Comment(0)
E
9

Instead of using individual TextStyle objects, use some style coming from the context. This way even during the animation, the styles will be based on the Theme of your MaterialApp.

For both Text widgets, instead of:

style: TextStyle(fontSize: 28, fontWeight: FontWeight.bold),

try:

style: Theme.of(context).textTheme.headline6, // or some other style

(You will need to remove const keywords because these are no longer constants.)

You can easily customize any built in style using copyWith, for example:

style: Theme.of(context).textTheme.headline6!.copyWith(
  fontSize: 28,
  fontWeight: FontWeight.bold),

In general it is a good practice in my opinion to use Theme styles.

Eras answered 23/11, 2022 at 18:4 Comment(7)
And what if we use the Google fonts library ?Decadence
You can set the fontFamily to the desired font after it is properly added to your project (assets folder, pubspec.yaml).Eras
I am using Google font and its showing red color text when moving from screen A to BDecadence
And did you set the fontFamily in the Theme?Eras
yes this is my instance of textStyle: static TextStyle bodyBoldStyle = GoogleFonts.urbanist(fontSize: 14.sp, fontWeight: FontWeight.bold); and this is how I am using it: Text("message", style: AppTextTheme. bodyBoldStyle)Decadence
Try to define the fontFamily globally in the Theme or add custom styles definition to the Theme and use Theme.of(context)... when setting style. See here.Eras
got it let me try this.Decadence
S
4

Just adding a Material as the child to Hero as shown below.

Hero(
  tag:'box',
  child: Material(// wrap with Material
    type: MaterialType.transparency, // likely needed
      child: Container(... // content

Happy Coding!!

Strategy answered 5/6 at 14:3 Comment(0)
H
2

It is a known Flutter issue. Someone posted a solution here. Good for anyone who may have the same question in the future: https://github.com/flutter/flutter/issues/30647#issuecomment-480980280

  Widget _flightShuttleBuilder(
    BuildContext flightContext,
    Animation<double> animation,
    HeroFlightDirection flightDirection,
    BuildContext fromHeroContext,
    BuildContext toHeroContext,
  ) {
    return DefaultTextStyle(
      style: DefaultTextStyle.of(toHeroContext).style,
      child: toHeroContext.widget,
    );
  }
  ...

Widget build(BuildContext context) {
  return Scaffold(
    ...
        child: Hero(
          tag: 'text',
          flightShuttleBuilder: _flightShuttleBuilder,
          child: Text('Text'),
        ),
Hanoverian answered 15/12, 2023 at 20:5 Comment(0)
P
0
DefaultTextStyle(
                    style: AppTextStyle.subtitle1.copyWith(
                      fontWeight: AppFontWeight.medium,
                      color: AppColors.textColor,
                    ),
                    maxLines: 1,
                    overflow: TextOverflow.ellipsis,
                    child: Text(
                      isCurrentUser ? currentUserState.username : userModel.username,
                    ),
                  ),
Paresis answered 7/10 at 18:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.