未找到 Material 个小部件。英雄动画不适用于 TextField
No Material widget found. Hero Animation is not working with TextField
我想用 TextField 实现这个动画:
但得到这个:
这是我的 TextField 小部件:
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> { FocusNode _focus = new FocusNode();
@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: Row(
children: [
Expanded(
child: TextField(style: AppTextStyles.body2,
focusNode: _focus,
decoration: InputDecoration(
prefixIcon: Icon(LineAwesomeIcons.search, color: Colors.black,),
// suffixIcon: Text("Cancel"),
filled: true,
fillColor: Colors.white,
border: OutlineInputBorder(borderRadius: BorderRadius.circular(8),
borderSide: const BorderSide(color: Colors.blue, width: 1))
))),
if(widget.onCancel != null)
GestureDetector(
onTap: widget.onCancel,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text("Cancel"),
),
)
],
),
); } }
这是我的第一个屏幕:
import 'package:flutter/material.dart';
import 'package:get/get.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){
Navigator.push(
context,
PageRouteBuilder(
transitionDuration: Duration(seconds: 3),
pageBuilder: (_, __, ___) => SearchScreen()));
// await Get.to(() => SearchScreen());
}
},
)
],
),
)
);
}
}
这是我的第二个屏幕:
import 'package:flutter/material.dart';
import 'package:line_awesome_flutter/line_awesome_flutter.dart';
import 'package:move_me_delivery/components/search_field.dart';
import 'package:move_me_delivery/data/styles.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, vertical: 32),
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))
),
),
],
),
),
),
),
);
}
}
我的主机:
======== Exception caught by widgets library =======================================================
The following assertion was thrown building TextField(focusNode: FocusNode#0fba2, decoration: InputDecoration(prefixIcon: Icon(IconData(U+0F002), color: Color(0xff000000)), filled: true, fillColor: Color(0xffffffff), border: OutlineInputBorder()), style: TextStyle(inherit: true, color: Color(0xff000000), size: 15.0, weight: 400, style: normal), dirty, dependencies: [MediaQuery, UnmanagedRestorationScope], state: _TextFieldState#43a28):
No Material widget found.
TextField widgets require a Material widget ancestor.
In material design, most widgets are conceptually "printed" on a sheet of material. In Flutter's material library, that material is represented by the Material widget. It is the Material widget that renders ink splashes, for instance. Because of this, many material library widgets require that there be a Material widget in the tree above them.
To introduce a Material widget, you can either directly include one, or use a widget that contains Material itself, such as a Card, Dialog, Drawer, or Scaffold.
The specific widget that could not find a Material ancestor was: TextField
focusNode: FocusNode#0fba2
decoration: InputDecoration(prefixIcon: Icon(IconData(U+0F002), color: Color(0xff000000)), filled: true, fillColor: Color(0xffffffff), border: OutlineInputBorder())
style: TextStyle(inherit: true, color: Color(0xff000000), size: 15.0, weight: 400, style: normal)
dirty
dependencies: [MediaQuery, UnmanagedRestorationScope]
state: _TextFieldState#43a28
The ancestors of this widget were:
: Expanded
flex: 1
: Row
direction: horizontal
mainAxisAlignment: start
crossAxisAlignment: center
dependencies: [Directionality]
renderObject: RenderFlex#afc02
: GetMaterialApp
: MyApp
...
The relevant error-causing widget was:
TextField file:///Users/akbarpulatov/Desktop/tests/move_me_delivery/lib/components/search_field.dart:49:20
When the exception was thrown, this was the stack:
#0 debugCheckHasMaterial.<anonymous closure> (package:flutter/src/material/debug.dart:27:7)
#1 debugCheckHasMaterial (package:flutter/src/material/debug.dart:48:4)
#2 _TextFieldState.build (package:flutter/src/material/text_field.dart:1116:12)
#3 StatefulElement.build (package:flutter/src/widgets/framework.dart:4691:27)
#4 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4574:15)
...
====================================================================================================
你得到的错误信息已经很好地说明了问题,所以我只给你一个解决方案。将 Hero
小部件的子项包装在 Material
:
中
Hero(
tag: "search",
child: Material(
type: MaterialType.transparency,
child: Row(
children: [
//TextField(),
//GestureDetector(),
],
),
),
);
我想用 TextField 实现这个动画:
但得到这个:
这是我的 TextField 小部件:
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> { FocusNode _focus = new FocusNode();
@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: Row(
children: [
Expanded(
child: TextField(style: AppTextStyles.body2,
focusNode: _focus,
decoration: InputDecoration(
prefixIcon: Icon(LineAwesomeIcons.search, color: Colors.black,),
// suffixIcon: Text("Cancel"),
filled: true,
fillColor: Colors.white,
border: OutlineInputBorder(borderRadius: BorderRadius.circular(8),
borderSide: const BorderSide(color: Colors.blue, width: 1))
))),
if(widget.onCancel != null)
GestureDetector(
onTap: widget.onCancel,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text("Cancel"),
),
)
],
),
); } }
这是我的第一个屏幕:
import 'package:flutter/material.dart';
import 'package:get/get.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){
Navigator.push(
context,
PageRouteBuilder(
transitionDuration: Duration(seconds: 3),
pageBuilder: (_, __, ___) => SearchScreen()));
// await Get.to(() => SearchScreen());
}
},
)
],
),
)
);
}
}
这是我的第二个屏幕:
import 'package:flutter/material.dart';
import 'package:line_awesome_flutter/line_awesome_flutter.dart';
import 'package:move_me_delivery/components/search_field.dart';
import 'package:move_me_delivery/data/styles.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, vertical: 32),
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))
),
),
],
),
),
),
),
);
}
}
我的主机:
======== Exception caught by widgets library =======================================================
The following assertion was thrown building TextField(focusNode: FocusNode#0fba2, decoration: InputDecoration(prefixIcon: Icon(IconData(U+0F002), color: Color(0xff000000)), filled: true, fillColor: Color(0xffffffff), border: OutlineInputBorder()), style: TextStyle(inherit: true, color: Color(0xff000000), size: 15.0, weight: 400, style: normal), dirty, dependencies: [MediaQuery, UnmanagedRestorationScope], state: _TextFieldState#43a28):
No Material widget found.
TextField widgets require a Material widget ancestor.
In material design, most widgets are conceptually "printed" on a sheet of material. In Flutter's material library, that material is represented by the Material widget. It is the Material widget that renders ink splashes, for instance. Because of this, many material library widgets require that there be a Material widget in the tree above them.
To introduce a Material widget, you can either directly include one, or use a widget that contains Material itself, such as a Card, Dialog, Drawer, or Scaffold.
The specific widget that could not find a Material ancestor was: TextField
focusNode: FocusNode#0fba2
decoration: InputDecoration(prefixIcon: Icon(IconData(U+0F002), color: Color(0xff000000)), filled: true, fillColor: Color(0xffffffff), border: OutlineInputBorder())
style: TextStyle(inherit: true, color: Color(0xff000000), size: 15.0, weight: 400, style: normal)
dirty
dependencies: [MediaQuery, UnmanagedRestorationScope]
state: _TextFieldState#43a28
The ancestors of this widget were:
: Expanded
flex: 1
: Row
direction: horizontal
mainAxisAlignment: start
crossAxisAlignment: center
dependencies: [Directionality]
renderObject: RenderFlex#afc02
: GetMaterialApp
: MyApp
...
The relevant error-causing widget was:
TextField file:///Users/akbarpulatov/Desktop/tests/move_me_delivery/lib/components/search_field.dart:49:20
When the exception was thrown, this was the stack:
#0 debugCheckHasMaterial.<anonymous closure> (package:flutter/src/material/debug.dart:27:7)
#1 debugCheckHasMaterial (package:flutter/src/material/debug.dart:48:4)
#2 _TextFieldState.build (package:flutter/src/material/text_field.dart:1116:12)
#3 StatefulElement.build (package:flutter/src/widgets/framework.dart:4691:27)
#4 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4574:15)
...
====================================================================================================
你得到的错误信息已经很好地说明了问题,所以我只给你一个解决方案。将 Hero
小部件的子项包装在 Material
:
Hero(
tag: "search",
child: Material(
type: MaterialType.transparency,
child: Row(
children: [
//TextField(),
//GestureDetector(),
],
),
),
);