[英]how to make hero animation in a datatable widget?
Hello everybody I have a datatable in which I filled with some data I want to add hero tag to each row in the datatable so when I click on that row it will open another MaterialPageRoute which contains a widget with the same hero tag of that particular row.大家好我有一个数据表,我在其中填充了一些数据我想将英雄标签添加到数据表中的每一行,所以当我单击该行时,它将打开另一个 MaterialPageRoute,其中包含一个具有与该特定行相同的英雄标签的小部件. The problem is that the hero animation is not working properly it shows the MaterialPageRoute normally without animation.
问题是英雄 animation 无法正常工作,它在没有 animation 的情况下正常显示 MaterialPageRoute。
import 'package:art_sweetalert/art_sweetalert.dart';
import 'package:flutter/material.dart';
import 'package:global_flutter_lib/I18n-Helper.dart';
import 'package:provider/provider.dart';
import 'package:shopping_cart_data/Data/Models/Setting.dart';
import 'package:shopping_cart_project/App-Widgets/App-Colors.dart';
import 'package:shopping_cart_project/Helpers/App-UI-Helper.dart';
import 'package:shopping_cart_project/States/States.dart';
import 'CustomRect-Tween.dart';
import 'hero-tags.dart';
class SettingTableWidget extends StatefulWidget {
const SettingTableWidget({Key? key}) : super(key: key);
@override
State<SettingTableWidget> createState() => _SettingTableWidgetState();
}
class _SettingTableWidgetState extends State<SettingTableWidget> {
GlobalKey<ArtDialogState>? _artDialogKey;
final Map<int, GlobalKey> _buttonMapKeys = {};
Setting? _selectedSetting;
String? companyHeaderText;
String? nameArabicHeaderText;
String? nameEnglishHeaderText;
String? yearHeaderText;
String? ipHeaderText;
String? portHeaderText;
String? defaultHeaderText;
String? addSettingText;
@override
void initState() {
super.initState();
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
companyHeaderText ??= I18nHelper.t(context, "setting.company");
nameArabicHeaderText ??= I18nHelper.t(context, "setting.nameArabic");
nameEnglishHeaderText ??= I18nHelper.t(context, "setting.nameEnglish");
yearHeaderText ??= I18nHelper.t(context, "setting.year");
ipHeaderText ??= I18nHelper.t(context, "setting.ip");
portHeaderText ??= I18nHelper.t(context, "setting.port");
defaultHeaderText ??= I18nHelper.t(context, "setting.default");
addSettingText ??= I18nHelper.t(context, "global.add");
}
@override
Widget build(BuildContext context) {
SettingState settingState = Provider.of<SettingState>(context);
return Column(
children: [
Row(
children: [
Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: ElevatedButton(
style:
ElevatedButton.styleFrom(primary: AppColors.primaryColor),
onPressed: _addNewRow,
child: Text(addSettingText!)),
)
],
),
const SizedBox(
height: 10,
),
Expanded(
child: DataTable(
headingRowColor: MaterialStateColor.resolveWith(
(states) => Colors.grey.shade300),
showBottomBorder: true,
showCheckboxColumn: false,
columns: _createColumns(),
rows: _createRows()),
),
],
);
}
final TextStyle _columnHeaderStyle =
const TextStyle(fontWeight: FontWeight.bold);
_createColumns() {
List<DataColumn> colList = [];
colList.add(const DataColumn(label: Text("")));
colList.add(DataColumn(
label: Text(
companyHeaderText!,
// I18nHelper.t(context, "setting.company"),
style: _columnHeaderStyle,
)));
colList.add(DataColumn(
label: Text(
nameArabicHeaderText!,
style: _columnHeaderStyle,
)));
colList.add(DataColumn(
label: Text(
nameEnglishHeaderText!,
style: _columnHeaderStyle,
)));
colList.add(DataColumn(
label: Text(
yearHeaderText!,
style: _columnHeaderStyle,
)));
colList.add(DataColumn(
label: Text(
ipHeaderText!,
style: _columnHeaderStyle,
)));
colList.add(DataColumn(
label: Text(
portHeaderText!,
style: _columnHeaderStyle,
)));
colList.add(const DataColumn(
label: SizedBox(
width: 0,
height: 0,
)));
return colList;
}
_createRows() {
SettingState settingState =
Provider.of<SettingState>(context, listen: false);
List<DataRow> rowList = [];
for (Setting s in settingState.list) {
rowList.add(DataRow(
color: settingState.current == s
? MaterialStateProperty.all(Colors.grey.shade300)
: MaterialStateProperty.all(Colors.white),
onSelectChanged: (selected) => _onSelectChanged(s, selected),
cells: [
DataCell(_createActions(s)),
DataCell(Text(s.company ?? "")),
DataCell(Text(s.nameArabic ?? "")),
DataCell(Text(s.nameEnglish ?? "")),
DataCell(Text(s.year.toString())),
DataCell(Text(s.ip.toString())),
DataCell(Text(s.port.toString())),
DataCell(Row(
children: [
settingState.defaultSetting?.id == s.id
? Icon(
Icons.check,
color: AppColors.primaryColor,
)
: Container(),
ElevatedButton(
onPressed: () async {
// I18nHelper.setLocale(context, SessionVariables.language!);
await settingState.setSettingAsDefault(setting: s);
},
child: Text(defaultHeaderText!))
],
)),
]));
}
return rowList;
}
_onSelectChanged(Setting s, bool? selected) {
//=================
// print("_onSelectChanged Selected ;$selected - Setting: ${s.nameArabic}");
SettingState settingState =
Provider.of<SettingState>(context, listen: false);
settingState.setCurrent(s);
// _selectedSetting = s;
}
_createActions(Setting setting) {
if (_buttonMapKeys.containsKey(setting.id) == false) {
_buttonMapKeys[setting.id as int] = GlobalKey();
}
return Row(children: [
Hero(
tag:setting.id,
createRectTween: (begin, end) {
return CustomRectTween(begin: begin!, end: end!);
},
child: IconButton(
key: _buttonMapKeys[setting.id],
color: AppColors.primaryColor,
onPressed: () => _editRow(setting),
icon: const Icon(Icons.edit),
),
),
IconButton(
color: AppColors.primaryColor,
onPressed: () => _deleteRow(setting),
icon: const Icon(Icons.delete),
)
]);
}
_addNewRow() {
Setting s = Setting.create();
AppUIHelper.showSettingFormDialog(context, s);
}
void _editRow(Setting s) async {
RenderBox? renderBox =
_buttonMapKeys[s.id]?.currentContext?.findRenderObject() as RenderBox?;
SettingState settingState =
Provider.of<SettingState>(context, listen: false);
settingState.setCurrent(s);
// AppUIHelper.showSettingFormDialog(context, s,
// offset: renderBox?.localToGlobal(const Offset(0, 0)) as Offset);
showSettingFormDialog(
context,
s,
);
}
void _deleteRow(Setting s) async {
SettingState settingState =
Provider.of<SettingState>(context, listen: false);
settingState.setCurrent(s);
AppUIHelper.showConfirmDelete(context, onConfirm: () async {
await settingState.deleteRow();
});
}
showSettingFormDialog(){
showSettingFormDialog(BuildContext context, Setting setting,
{String title = ""}) {
Navigator.push(
context,
HeroDialogRoute(
horizPadding: 370,
tag: setting.id,
title: title,
builder: (_) => SettingFormWidget(
setting: setting,
)));
}
}
}
//======================HeroTagDialog
/// {@template hero_dialog_route}
/// Custom [PageRoute] that creates an overlay dialog (popup effect).
///
/// Best used with a [Hero] animation.
/// {@endtemplate}
class HeroDialogRoute<T> extends PageRoute<T> {
final double? vertPadding;
final double? horizPadding;
final String? tag;
final String? title;
/// {@macro hero_dialog_route}
HeroDialogRoute(
{required WidgetBuilder builder,
RouteSettings? settings,
bool fullscreenDialog = false,
this.vertPadding = 80,
this.horizPadding = 80,
this.tag,
this.title})
: _builder = builder,
super(settings: settings, fullscreenDialog: fullscreenDialog);
final WidgetBuilder _builder;
@override
bool get opaque => false;
@override
bool get barrierDismissible => false;
@override
Duration get transitionDuration => const Duration(milliseconds: 600);
@override
Duration get reverseTransitionDuration => const Duration(milliseconds: 900);
@override
bool get maintainState => true;
@override
Color get barrierColor => Colors.black54;
@override
Widget buildTransitions(BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation, Widget child) {
return ScaleTransition(scale: animation, child: child);
}
@override
Widget buildPage(BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation) {
return Center(
child: Padding(
padding: EdgeInsets.symmetric(
vertical: vertPadding ?? 80.0, horizontal: horizPadding ?? 80.0),
child: Hero(
tag: tag ?? "HeroTag",
createRectTween: (begin, end) {
return CustomRectTween(begin: begin!, end: end!);
},
child: Container(
decoration: BoxDecoration(
borderRadius: const BorderRadius.all(Radius.circular(20)),
border: Border.all(color: AppColors.primaryColor, width: 4)),
child: ClipRRect(
clipBehavior: Clip.antiAliasWithSaveLayer,
borderRadius: const BorderRadius.all(Radius.circular(20)),
child: Scaffold(
appBar: AppBar(
backgroundColor: AppColors.primaryColor,
title: AppUIHelper.dialogTitle(title: title ?? "No Title")),
body: _builder(context),
),
),
),
),
),
);
}
@override
String get barrierLabel => 'Popup dialog open';
}
I found out the problem I wrapped the SettingTableWidget with AlertDialog and any child widgets inside the AlertDialog does not support the hero tag so instead of using showDialog method I used我发现了我用 AlertDialog 包装 SettingTableWidget 的问题,并且 AlertDialog 内的任何子小部件都不支持 hero 标记,所以我没有使用 showDialog 方法
Navigator.of(context).push(MaterialPageRoute(builder(_)=>SettingTableWidget()))
and it works like charm,thanks.它就像魅力一样,谢谢。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.