在flutter AppBar中的自定义搜索栏中制作动画



我已经实现了一个自定义搜索栏,当用户选择它时可以切换。我正在替换appBar中需要它的地方的SearchBar。最初,搜索栏将显示具有字符串("搜索"(==>的图标(搜索(;view1,当单击其中任何一个时,它将被另一个具有可搜索文本字段===>视图2。我会发布我到目前为止所做的事情。我需要给它一个很好的动画。动画应该像这样移动。最初显示视图1,然后==>从右到左设置视图2的动画替换视图1当需要再次返回视图1时;与上面的动画相反。

迄今为止的解决方案

class SearchBar extends StatefulWidget with PreferredSizeWidget {
const SearchBar({Key? key}) : super(key: key);
@override
_SearchBarState createState() => _SearchBarState();
@override
Size get preferredSize => Size.fromHeight(kToolbarHeight);
}
class _SearchBarState extends State<SearchBar> {
bool _toggle = true;
@override
Widget build(BuildContext context) {
return AppBar(
elevation: 0.0,
backgroundColor: CustomColors.mWhite,
automaticallyImplyLeading: false,
title:
AnimatedContainer(
width: MediaQuery.of(context).size.width * 0.8,
decoration: _toggle
? null
: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(15.0),
border: Border.all(
width: 1,
color: CustomColors.grey600,
),
),
duration: Duration(seconds: 2),
child: _toggle
? GestureDetector(
onTap: () {
setState(() {
_toggle = !_toggle;
});
},
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Icon(
Icons.search,
size: 24.0,
),
SizedBox(
width: 10.0,
),
Text(
"Search",
style: tBody1,
),
],
),
)
: Center(
child: TextField(
textInputAction: TextInputAction.search,
decoration: InputDecoration(
prefixIcon: IconButton(
icon: Icon(Icons.arrow_back_ios),
onPressed: () {
setState(() {
_toggle = !_toggle;
});
},
),
border: InputBorder.none),
),
),
),
actions: [
Container(
width: 50.0,
height: 50.0,
padding: EdgeInsets.only(right: 8.0),
child: Image.asset(
'assets/images/settings.png',
),
),
],
);
}
}

AnimatedContainer应该有一个取决于_toggle值的width,在您的情况下,AnimatedContainer中应该只包括搜索字段。

我简化了你的代码,展示了如何让动画工作,见下文。transform参数负责从右到左的动画,如果对其进行注释,它将从左到右进行动画。

我还添加了一个AnimatedOpacity来淡入/淡出背面图标。

(你可以将代码原样粘贴到DartPad中,看看它是如何工作的。(

import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return const MaterialApp(home: Scaffold(appBar: SearchBar()));
}
}
class SearchBar extends StatefulWidget with PreferredSizeWidget {
const SearchBar({Key? key}) : super(key: key);
@override
_SearchBarState createState() => _SearchBarState();
@override
Size get preferredSize => const Size.fromHeight(kToolbarHeight);
}
class _SearchBarState extends State<SearchBar> {
bool _toggle = true;
void _doToggle() => setState(() => _toggle = !_toggle);
@override
Widget build(BuildContext context) {
return AppBar(
title: Stack(children: [
GestureDetector(
onTap: _doToggle,
child: SizedBox(
height: kToolbarHeight * 0.8,
child: Row(
children: const [
Icon(
Icons.search,
size: 24.0,
),
SizedBox(
width: 10.0,
),
Text("Search"),
],
)),
),
AnimatedContainer(
width: _toggle ? 0 : MediaQuery.of(context).size.width,
transform: Matrix4.translationValues(_toggle ? MediaQuery.of(context).size.width : 0, 0, 0),
duration: const Duration(seconds: 1),
height: kToolbarHeight * 0.8,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(15.0),
border: Border.all(
width: 1,
color: Colors.grey[600]!,
),
),
child: TextField(
textInputAction: TextInputAction.search,
decoration: InputDecoration(
prefixIcon: AnimatedOpacity(
duration: const Duration(seconds: 1),
opacity: _toggle ? 0 : 1,
child: IconButton(
icon: const Icon(Icons.arrow_back_ios),
onPressed: _doToggle,
)),
border: InputBorder.none),
),
)
]),
);
}
}

最新更新