如何解决flutter 如何知道Hero动画的结束?
我想实现这一目标:
https://www.spitogatos.gr/pwliseis-katoikies/athina-notia-proastia/
但是当 Hero 动画开始时键盘被强制关闭:
我尝试使用在布局后触发的小部件回调。但是只要英雄动画开始就会触发这个回调。我也尝试使用 Future.delayed(Duration(seconds: 2)
,但它没有帮助。如果我只从小部件树中删除 Hero 小部件,一切都会按预期工作。
这是我的第一个屏幕:
import 'package:flutter/material.dart';
import 'package:move_me_delivery/components/rounded_app_bar.dart';
import 'package:move_me_delivery/components/search_field.dart';
import '../screens.dart';
class HomeTab extends StatelessWidget {
const HomeTab({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: RoundedAppBar(title: ""),body: Padding(
padding: const EdgeInsets.symmetric(horizontal: 24,vertical: 32),child: Column(
children: [
SearchTextField(
onFocusChange: (val) async {
if(val){
await Navigator.push(context,PageRouteBuilder(
transitionDuration: Duration(milliseconds: 400),pageBuilder: (_,__,___) => SearchScreen()));
}
},)
],),)
);
}
}
这是我的第二个屏幕:
import 'package:flutter/material.dart';
import 'package:line_awesome_flutter/line_awesome_flutter.dart';
import 'package:move_me_delivery/components/search_field.dart';
class SearchScreen extends StatefulWidget {
const SearchScreen({Key? key}) : super(key: key);
@override
_SearchScreenState createState() => _SearchScreenState();
}
class _SearchScreenState extends State<SearchScreen> {
final _focusNode = FocusNode();
@override
void initState() {
super.initState();
_focusNode.requestFocus();
}
@override
Widget build(BuildContext context) {
return Container(
color: Colors.white,child: SafeArea(
child: Scaffold(
body: Padding(
padding: const EdgeInsets.symmetric(horizontal: 24,child: Column(
children: [
SearchTextField(
focus: _focusNode,onCancel: (){
FocusScope.of(context).unfocus();
Navigator.pop(context);
},inputDecoration: InputDecoration(
prefixIcon: Icon(LineAwesomeIcons.search,color: Colors.black,filled: true,fillColor: Colors.white,border: OutlineInputBorder(borderRadius: BorderRadius.circular(8),borderSide: const BorderSide(color: Colors.blue,width: 1))
),],);
}
}
最后是我的带有英雄动画的 SearchField 屏幕:
import 'package:flutter/material.dart';
import 'package:line_awesome_flutter/line_awesome_flutter.dart';
import 'package:move_me_delivery/data/styles.dart';
class SearchTextField extends StatefulWidget {
const SearchTextField({Key? key,this.onFocusChange,this.focus,this.onCancel,this.inputDecoration
}) : super(key: key);
final void Function(bool hasFocus)? onFocusChange;
final FocusNode? focus;
final VoidCallback? onCancel;
final InputDecoration? inputDecoration;
@override
_SearchTextFieldState createState() => _SearchTextFieldState();
}
class _SearchTextFieldState extends State<SearchTextField>{
late FocusNode _focus;
@override
void initState() {
super.initState();
_focus = widget.focus ?? new FocusNode();
_focus.addListener(
(){
if(widget.onFocusChange != null){
widget.onFocusChange!(_focus.hasFocus);
}
}
);
}
@override
Widget build(BuildContext context) {
return Hero(
tag: "search",child: Material(
type: MaterialType.card,child: Row(
children: [
Expanded(
child: TextField(style: AppTextStyles.body2,focusNode: _focus,decoration: InputDecoration(
prefixIcon: Icon(LineAwesomeIcons.search,// suffixIcon: Text("Cancel"),width: 1))
))),if(widget.onCancel != null)
GestureDetector(
onTap: widget.onCancel,child: Padding(
padding: const EdgeInsets.all(8.0),child: Text("Cancel"),);
}
}
解决方法
您想要实现的界面不一定使用 Hero
小部件。它可以用其他动画来完成。但是,如果您不想使用 Hero
,您可以尝试一个相当笨拙的解决方案:
在您的屏幕 1 上,在您的 Hero
的 TextField
中设置这两个属性:
Hero(
tag: 'search',child: Material(
type: MaterialType.transparency,child: TextField(
readOnly: true,showCursor: true,onTap: () {
Navigator.push() //to SearchScreen()
}
),),
然后,在屏幕 2 上:
Hero(
tag: 'search',child: TextField(
autofocus: true,
您必须避免在两个屏幕上使用相同的 SearchTextField
;正如我所展示的,他们每个人都需要自己的。此外,如果您使用此方法,您可能可以删除所有 FocusNode
代码。
免责声明:我还没有测试过这段代码。只是想尝试一下
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。