AnimatedCrossFade
的一个问题是,即使只显示两个孩子,也必须同时提供两个孩子。
如果这些孩子中的一个(或两个)既复杂又沉重,这是没有效率的。
我试图提供一个Builder
,像这样:
AnimatedCrossFade(
firstChild: widget1,
secondChild: Builder(builder: widget2builder),
duration: const Duration(milliseconds: 500),
crossFadeState: toggle ? CrossFadeState.showFirst : CrossFadeState.showSecond,
),
var widget2builder = (context) {
print("Building widget 2");
return Container(),
);
};
但是,即使第一个窗口小部件正在显示,因此它也会立即打印 Building widget 2
,因此根本不需要窗口小部件2。
这是一个完整的,可运行的示例:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> with TickerProviderStateMixin {
bool toggle;
@override
void initState() {
super.initState();
toggle = true;
}
@override
Widget build(BuildContext context) {
var toggleButton = Padding(
padding: const EdgeInsets.all(8.0),
child: MaterialButton(
child: const Text("Toggle"),
color: Colors.grey,
onPressed: () {
setState(() {
toggle = !toggle;
});
},
),
);
var widget1 = Container(
key: UniqueKey(),
color: Colors.blue,
width: 200.0,
child: const Text(
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt "
"ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation "
"ullamco laboris nisi ut aliquip ex ea commodo consequat.",
),
);
var widget2builder = (context) {
print("Building widget 2.");
return Container(
key: UniqueKey(),
color: Colors.red,
width: 200.0,
child: const Text(
"I am ready for my closeup.",
),
);
};
return MaterialApp(
home: Material(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
toggleButton,
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text("Some text above."),
AnimatedCrossFade(
firstChild: widget1,
secondChild: Builder(builder: widget2builder),
duration: const Duration(milliseconds: 500),
crossFadeState: toggle ? CrossFadeState.showFirst : CrossFadeState.showSecond,
),
const Text("Some text below."),
],
),
],
),
),
);
}
}
如果运行此命令,则会看到 Building widget 2
已打印到控制台,但正在显示的是小部件1。
我的问题:
AnimatedCrossFade
正在构建不使用的小部件吗?
如何预防此问题并有效使用AnimatedCrossFade
?
答案 0 :(得分:2)
我想补充一下Rémi的答案,在问了这个问题后的某个时候,我发布了一个名为AnimatedSizeAndFade
的软件包来解决它:
https://pub.dev/packages/animated_size_and_fade
与其他类似小部件相比如何?
使用AnimatedCrossFade,您必须同时保留firstChild和secondChild,而AnimatedSizeAndFade则不需要。
使用AnimatedSwitcher,您可以简单地更改其子级,但随后只会设置淡入淡出的动画效果,而不是大小。
AnimatedContainer也不起作用,除非您事先知道孩子的大小。
答案 1 :(得分:1)
这是预期的行为。
如飞镖团队所述,您应该期望随时调用void TableDelegate::paint( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const
{
qDebug() << index.row() << index.column();
TableDataRow::Type type = static_cast<TableDataRow::Type>( index.data( Qt::UserRole ).toInt() );
QString text = index.data( Qt::DisplayRole ).toString();
int row = index.row();
if ( option.state & QStyle::State_MouseOver )
{
if ( type == TableDataRow::Type::Data )
{
painter->fillRect( QRect( 0, option.rect.topLeft().y(), option.rect.width()*numberOfColumns, option.rect.height() ), QColor( 249, 126, 18 ) );
for ( int i = 0; i < numberOfColumns; i++ )
{
QModelIndex indexOfRow = index.sibling( row, i );
painter->setPen( Qt::white );
painter->drawText( option.rect, Qt::AlignVCenter | Qt::TextWordWrap, text );
}
}
}
}
方法。
build
被设计为便宜且没有副作用。
构建窗口小部件的事实并不意味着它已在屏幕上呈现。 build
的不透明度为0实际上会缩短绘画过程(并且在完全不透明时进行其他优化)。
如果这引起问题,那么您应该改用AnimatedSwitcher
来替换子元素时播放动画。