Skip to content

fontVariations property is not animatable within AnimatedDefaultTextStyle #105120

@epentesi

Description

@epentesi

Steps to Reproduce

  1. Switch Flutter framework to master channel (3.1.0-0.0.pre.1037, at the moment)
  2. Add the variable font Roboto Flex TTF file to your project (download page: https://fonts.google.com/specimen/Roboto+Flex)
/
│
└── fonts/
    └── RobotoFlex-VariableFont_GRAD,XTRA,YOPQ,YTAS,YTDE,YTFI,YTLC,YTUC,opsz,slnt,wdth,wght.ttf
  1. Update pubspec.yaml file
  fonts:
    - family: 'Roboto Flex'
      fonts:
        - asset: 'fonts/RobotoFlex-VariableFont_GRAD,XTRA,YOPQ,YTAS,YTDE,YTFI,YTLC,YTUC,opsz,slnt,wdth,wght.ttf'
  1. Execute flutter run on the code sample
  2. Click on Color or Font size button and see how the changes for the sample text above (þΩ) of those properties take place over a period of time (2 seconds)
  3. Click now on Weight (wght) or Width (wdth) or Slant (slnt) (some of font axes of Roboto Flex) and see how the changes for the text (þΩ) take place immediately

Expected results:
When a FontVariation value changes for the fontVariations property, that change should take place over a period of time.

Actual results:
The fontVariations changes take place immediately.

Code sample
import 'dart:math';
import 'dart:ui';

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 MyHomePage(title: 'Animated Default Text Style'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  String _console = '—';

  double getRandomValue(List<double> range) {
    double value = range[0] + Random().nextDouble() * (range[1] - range[0]);
    return value;
  }

  final List<Color> _textColorList = [
    Colors.grey,
    Colors.red,
    Colors.green,
    Colors.blue,
    Colors.yellow,
    Colors.purple,
    Colors.indigo,
    Colors.orange,
  ];
  Color _textColor = Colors.black;
  final List<double> _fontSizeRange = [36.0, 190];
  double _fontSize = 190.0;
  final List<double> _weightRange = [100.0, 1000];
  double _weight = 1000.0;
  final List<double> _widthRange = [25.0, 151];
  double _width = 151.0;
  final List<double> _slantRange = [-10.0, 0.0];
  double _slant = 0.0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      backgroundColor: Colors.grey.shade50,
      body: SafeArea(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const SizedBox(
              height: 32.0,
            ),
            Text(
              _console,
              style: const TextStyle(
                fontFamily: 'Menlo',
                fontFamilyFallback: ['monospace'],
              ),
            ),
            Expanded(
              child: Center(
                child: AnimatedDefaultTextStyle(
                  duration: const Duration(seconds: 2),
                  curve: Curves.elasticOut,
                  textAlign: TextAlign.center,
                  style: TextStyle(
                    fontFamily: 'Roboto Flex',
                    color: _textColor,
                    fontSize: _fontSize,
                    fontVariations: [
                      FontVariation('wght', _weight),
                      FontVariation('wdth', _width),
                      FontVariation('slnt', _slant),
                    ],
                  ),
                  child: const Text(
                    'þΩ',
                  ),
                ),
              ),
            ),
            const SizedBox(
              height: 64.0,
            ),
            const Divider(
              thickness: 4,
            ),
            const Text('Animatable properties'),
            Wrap(
              spacing: 16.0,
              alignment: WrapAlignment.center,
              children: [
                ElevatedButton(
                    onPressed: () {
                      setState(() {
                        _textColor = _textColorList[
                            Random().nextInt(_textColorList.length)];
                        _console =
                            'Color: ${_textColor.value.toRadixString(16).toUpperCase()}';
                      });
                    },
                    child: const Text('Color')),
                ElevatedButton(
                    onPressed: () {
                      setState(() {
                        _fontSize = getRandomValue(_fontSizeRange);
                        _console = 'Font size: ${_fontSize.toStringAsFixed(1)}';
                      });
                    },
                    child: const Text('Font size')),
              ],
            ),
            const Divider(
              thickness: 4,
            ),
            const Text('Font variations (non animatable properties)'),
            Wrap(
              spacing: 16.0,
              alignment: WrapAlignment.center,
              children: [
                ElevatedButton(
                    onPressed: () {
                      setState(() {
                        _weight = getRandomValue(_weightRange);
                        _console = 'Weight: ${_weight.toStringAsFixed(1)}';
                      });
                    },
                    child: const Text('Weight (wght)')),
                ElevatedButton(
                    onPressed: () {
                      setState(() {
                        _width = getRandomValue(_widthRange);
                        _console = 'Width: ${_width.toStringAsFixed(1)}';
                      });
                    },
                    child: const Text('Width (wdth)')),
                ElevatedButton(
                    onPressed: () {
                      setState(() {
                        _slant = getRandomValue(_slantRange);
                        _console = 'Slant: ${_slant.toStringAsFixed(1)}';
                      });
                    },
                    child: const Text('Slant (slnt)')),
              ],
            ),
          ],
        ),
      ),
    );
  }
}
Demo video
NonAnimatableFontVariations.mp4

Metadata

Metadata

Assignees

Labels

P3Issues that are less important to the Flutter projecta: animationAnimation APIsfound in release: 3.1Found to occur in 3.1frameworkflutter/packages/flutter repository. See also f: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onr: fixedIssue is closed as already fixed in a newer versionteam-frameworkOwned by Framework teamtriaged-frameworkTriaged by Framework team

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions