英雄小部件中的颤振小吃栏



我以前有两个小部件,第一个显示列表,第二个显示列表中特定项的详细信息页面。

class WidgetA extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: _buildAppBar(context),
body ListView.builder(...)
}
}

class WidgetB extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: _buildAppBar(context),
body ....
}
}

使WidgetA导航到WidgetB

Navigator.push(context,MaterialPageRoute(builder: (context) => WidgetB()));

但是因为我想要一个漂亮的动画过渡,我现在使用一个英雄小部件在两个小部件。

// Widget B
@override
Widget build(BuildContext context) {
return Hero(
tag: someObject,    
);
} 

但现在的问题是,每当WidgetB想要显示一个零食条,它是不可见的。然而,如果你想在零食条消失之前导航回WidgetA,你可以在那里看到它。

ScaffoldMessenger.of(context).showSnackBar(SnackBar(
duration: const Duration(seconds: 3), content: Text('some text'),
));

我看了脚手架文档,上面写着

通常不需要嵌套支架。例如,在一个选项卡UI中,底部导航栏是一个TabBar,主体是一个TabBarView,你可能会想让每个选项卡栏视图都有一个不同标题的AppBar。相反,最好在TabController中添加一个侦听器来更新AppBar

所以我也试着在widgeb中返回一个简单的Column,它被包装在ScaffoldMessenger内,但这些解决方案都不奏效……我在网上查了一下,人们说这是故意的行为。但没有官方消息来源这么说。我怎样才能在细节页面中显示一个小点心栏,同时还能使用漂亮的英雄转场?

你可以模仿相同的效果,但使用

你可以使用我创建的这个自定义类来轻松地显示底部表单,并且可以从项目中的任何地方访问

class BottomSheetManager {
bool _isBottomSheetVisible = false;
ScaffoldState? _scaffoldState;
String? currentMessage;
Timer? _cancelTimer;
PersistentBottomSheetController? _persistentBottomSheetController;
void hideCurrentBottomSheet({bool immediately = false}) {
if (immediately) {
_cancelTimer?.cancel();
_removeBottomSheet();
return;
}
_cancelTimer = Timer(const Duration(seconds: 4), _removeBottomSheet);
}
void _removeBottomSheet() {
_persistentBottomSheetController?.close();
_cancelTimer?.cancel();
_cancelTimer = null;
_persistentBottomSheetController = null;
_isBottomSheetVisible = false;
_scaffoldState = null;
currentMessage = null;
}
void showAlertMessage({
BuildContext? context,
GlobalKey<ScaffoldState>? scaffoldKey,
required String message,
}) =>
showMessage(message: message, scaffoldKey: scaffoldKey, context: context);
void showSuccessMessage({
BuildContext? context,
GlobalKey<ScaffoldState>? scaffoldKey,
required String message,
}) =>
showMessage(message: message, scaffoldKey: scaffoldKey, context: context, backgroundColor: Colors.green, textColor: Colors.white);
void showFailureMessage({
BuildContext? context,
GlobalKey<ScaffoldState>? scaffoldKey,
required String message,
}) =>
showMessage(message: message, scaffoldKey: scaffoldKey, context: context, backgroundColor: Colors.redAccent, textColor: Colors.white);
void showMessage({
BuildContext? context,
GlobalKey<ScaffoldState>? scaffoldKey,
required String message,
Color backgroundColor = Colors.black87,
Color textColor = Colors.white,
}) async {
assert(
(context == null) != (scaffoldKey == null),
'you must provide either the current context or the scaffoldMessenger key to show the snack bar',
);
if (_isBottomSheetVisible && currentMessage == message) {
return;
}
if (_isBottomSheetVisible) {
try {
hideCurrentBottomSheet(immediately: true);
} catch (err) {
debugPrint('something went wrong');
}
_scaffoldState = null;
_isBottomSheetVisible = false;
}
currentMessage = message;
final bottomSheetWidget = Container(
width: double.infinity,
height: 60,
padding: const EdgeInsets.only(right: 40),
alignment: Alignment.centerRight,
decoration: BoxDecoration(
color: backgroundColor,
borderRadius: const BorderRadius.only(
bottomLeft: Radius.circular(10),
bottomRight: Radius.circular(10),
),
),
child: Text(message, style: TextStyle(color: textColor)),
);
if (context != null) {
debugPrint('context is not null');
_scaffoldState = Scaffold.of(context);
} else {
_scaffoldState = scaffoldKey!.currentState as ScaffoldState;
}
_persistentBottomSheetController = _scaffoldState!.showBottomSheet((_) => bottomSheetWidget);
_isBottomSheetVisible = true;
hideCurrentBottomSheet();
_persistentBottomSheetController!.closed.then((value) {
_removeBottomSheet();
});
}
}

最新更新