正如您从 gif 和下面的代码中看到的,我有一个容器和一个文本小部件,它们都包装在一个英雄小部件中。
单击容器时,将打开第二页。我想要两个小部件都有一个英雄动画。
容器的动画效果很棒。然而,在过渡发生时,文本似乎失去了风格。
知道如何修复它吗?
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,
),
),
]),
);
}
}
不要使用单独的
TextStyle
对象,而是使用来自上下文的某种样式。这样,即使在动画期间,样式也将基于您的 Theme
的 MaterialApp
。
对于两个
Text
小部件,而不是:
style: TextStyle(fontSize: 28, fontWeight: FontWeight.bold),
尝试:
style: Theme.of(context).textTheme.headline6, // or some other style
(您需要删除
const
关键字,因为它们不再是常量。)
您可以使用
copyWith
轻松自定义任何内置样式,例如:
style: Theme.of(context).textTheme.headline6!.copyWith(
fontSize: 28,
fontWeight: FontWeight.bold),
总的来说,我认为使用
Theme
样式是一个很好的做法。
这是一个已知的 Flutter 问题。有人在这里发布了解决方案。对于将来可能有同样问题的任何人都有好处: 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'),
),