Flutter自定义Appbar搜索框效果
本文实例为大家分享了Flutter自定义Appbar搜索框效果的具体代码,供大家参考,具体内容如下
首先看一下实现本次实现的效果。
本来想直接偷懒从flutter pub上找个能用的使用起来,但是看了下发现都与目前ui效果相差很大,于是乎决定自己实现一个。整体的话比较简单,本来也是为了练手而做的。
为了方便处理statusbar的高度适配,于是乎直接依托于Appbar进行了实现,这样就可以不用处理状态栏适配了。
class _HotWidgetState extends State<HotWidget> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( titleSpacing: 0, //清除title左右padding,默认情况下会有一定的padding距离 toolbarHeight: 44, //将高度定到44,设计稿的高度。为了方便适配, //推荐使用插件flutter_screenutil做屏幕的适配工作 backgroundColor: Colors.white, elevation: 0, //由于title本身是接受一个widget,所以可以直接给他一个自定义的widget。 title: SearchAppBar( hintLabel: "电影/电视剧/影人", ), ), body: Container(), ); } }
flutter中控件定义推荐的是使用组合控件实现,这个是真的很酷,因为万物皆widget,组合起来很方便。
import 'package:flutter/material.dart'; import 'package:flutter_demo_001/ui.theme/color.dart'; import 'package:flutter_demo_001/ui.theme/theme.dart'; import 'package:flutter_demo_001/utils/padding.dart'; class SearchAppBar extends StatefulWidget { SearchAppBar({Key? key, required this.hintLabel}) : super(key: key); final String hintLabel; @override State<StatefulWidget> createState() { return SearchAppBarState(); } } class SearchAppBarState extends State<SearchAppBar> { late FocusNode _focusNode; ///默认不展示控件 bool _offstage = true; ///监听TextField内容变化 final TextEditingController _textEditingController = TextEditingController(); @override void initState() { super.initState(); _focusNode = FocusNode(); _textEditingController.addListener(() { var isVisible = _textEditingController.text.isNotEmpty; _updateDelIconVisible(isVisible); }); } _updateDelIconVisible(bool isVisible) { setState(() { _offstage = !isVisible; }); } @override Widget build(BuildContext context) { return SizedBox( width: double.infinity, height: 30, child: Row( children: [ Expanded( flex: 1, child: Container( height: double.infinity, margin: const EdgeInsets.only(left: 16), decoration: BoxDecoration( color: colorF5F6FA, borderRadius: BorderRadius.circular(4)), child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ paddingOnly(const EdgeInsets.only(left: 8)), Image.asset( "images/home_search.png", width: 16, height: 16, ), paddingOnly(const EdgeInsets.only(left: 8)), Expanded( flex: 1, child: TextField( controller: _textEditingController, autofocus: true, focusNode: _focusNode, style: TextStyle(fontSize: 14, color: color333), decoration: boxInputDecoration(widget.hintLabel), maxLines: 1, ), ), paddingOnly(const EdgeInsets.only(right: 8)), Offstage( offstage: _offstage, child: GestureDetector( onTap: () => {_textEditingController.clear()}, child: Image.asset( "images/home_search_cancel.png", width: 16, height: 16, ), ), ), paddingOnly(const EdgeInsets.only(right: 8)), ], ), ), ), GestureDetector( onTap: () { _focusNode.unfocus(); }, child: Container( padding: const EdgeInsets.only(left: 16, right: 16), child: Text("取消", style: TextStyle(fontSize: 16, color: Color(0xFF3D7DFF))), ), ), ], ), ); } @override void dispose() { super.dispose(); _focusNode.unfocus(); } }
最后为了美观,需要让状态栏也变成透明。
void main() { //固定屏幕旋转方向 WidgetsFlutterBinding.ensureInitialized(); SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]) .then((_) { runApp(const MyApp()); }); //设置状态栏透明 if (Platform.isAndroid) { SystemUiOverlayStyle systemUiOverlayStyle = const SystemUiOverlayStyle( statusBarColor: Colors.transparent, //设置为透明 ); SystemChrome.setSystemUIOverlayStyle(systemUiOverlayStyle); } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。
赞 (0)