当前位置:网站首页>开源一夏|Flutter实现搜索的三种方式
开源一夏|Flutter实现搜索的三种方式
2022-08-08 08:29:00 【InfoQ】
示例 1:使用搜索表单创建全屏模式
编码
// 大前端之旅
// main.dart
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
// remove the debug banner
debugShowCheckedModeBanner: false,
title: '大前端之旅',
theme: ThemeData(
primarySwatch: Colors.green,
),
home: const KindaCodeDemo(),
);
}
}
// this class defines the full-screen search modal
// by extending the ModalRoute class
class FullScreenSearchModal extends ModalRoute {
@override
Duration get transitionDuration => const Duration(milliseconds: 500);
@override
bool get opaque => false;
@override
bool get barrierDismissible => false;
@override
Color get barrierColor => Colors.black.withOpacity(0.6);
@override
String? get barrierLabel => null;
@override
bool get maintainState => true;
@override
Widget buildPage(
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
) {
return Scaffold(
body: SafeArea(
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 15),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// implement the search field
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: TextField(
autofocus: true,
decoration: InputDecoration(
contentPadding: const EdgeInsets.symmetric(
vertical: 0, horizontal: 20),
filled: true,
fillColor: Colors.grey.shade300,
suffixIcon: const Icon(Icons.close),
hintText: 'Search 大前端之旅',
border: OutlineInputBorder(
borderSide: BorderSide.none,
borderRadius: BorderRadius.circular(30)),
),
),
),
const SizedBox(
width: 10,
),
// This button is used to close the search modal
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: const Text('Cancel'))
],
),
// display other things like search history, suggestions, search results, etc.
const SizedBox(
height: 20,
),
const Padding(
padding: EdgeInsets.only(left: 5),
child: Text('Recently Searched',
style:
TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
),
const ListTile(
title: Text('Flutter tutorials'),
leading: Icon(Icons.search),
trailing: Icon(Icons.close),
),
const ListTile(
title: Text('How to fry a chicken'),
leading: Icon(Icons.search),
trailing: Icon(Icons.close),
),
const ListTile(
title: Text('大前端之旅'),
leading: Icon(Icons.search),
trailing: Icon(Icons.close),
),
const ListTile(
title: Text('Goodbye World'),
leading: Icon(Icons.search),
trailing: Icon(Icons.close),
),
const ListTile(
title: Text('Cute Puppies'),
leading: Icon(Icons.search),
trailing: Icon(Icons.close),
)
],
),
),
),
);
}
// animations for the search modal
@override
Widget buildTransitions(BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation, Widget child) {
// add fade animation
return FadeTransition(
opacity: animation,
// add slide animation
child: SlideTransition(
position: Tween<Offset>(
begin: const Offset(0, -1),
end: Offset.zero,
).animate(animation),
child: child,
),
);
}
}
// This is the main screen of the application
class KindaCodeDemo extends StatelessWidget {
const KindaCodeDemo({Key? key}) : super(key: key);
void _showModal(BuildContext context) {
Navigator.of(context).push(FullScreenSearchModal());
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('大前端之旅'), actions: [
// this button is used to open the search modal
IconButton(
icon: const Icon(Icons.search),
onPressed: () => _showModal(context),
)
]),
body: Container(),
);
}
}
示例 2:AppBar 内的搜索字段(最常见于娱乐应用程序)
编码
// main.dart
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
// Remove the debug banner
debugShowCheckedModeBanner: false,
title: '大前端之旅',
theme: ThemeData(
primarySwatch: Colors.indigo,
),
home: const HomePage());
}
}
// Home Page
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('大前端之旅'),
actions: [
// Navigate to the Search Screen
IconButton(
onPressed: () => Navigator.of(context)
.push(MaterialPageRoute(builder: (_) => const SearchPage())),
icon: const Icon(Icons.search))
],
),
);
}
}
// Search Page
class SearchPage extends StatelessWidget {
const SearchPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
// The search area here
title: Container(
width: double.infinity,
height: 40,
decoration: BoxDecoration(
color: Colors.white, borderRadius: BorderRadius.circular(5)),
child: Center(
child: TextField(
decoration: InputDecoration(
prefixIcon: const Icon(Icons.search),
suffixIcon: IconButton(
icon: const Icon(Icons.clear),
onPressed: () {
/* Clear the search field */
},
),
hintText: 'Search...',
border: InputBorder.none),
),
),
)),
);
}
}
示例 3:搜索字段和 SliverAppBar
编码
// main.dart
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
// Remove the debug banner
debugShowCheckedModeBanner: false,
title: '大前端之旅',
theme: ThemeData(
primarySwatch: Colors.deepPurple,
),
home: const HomePage());
}
}
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
slivers: [
SliverAppBar(
floating: true,
pinned: true,
snap: false,
centerTitle: false,
title: const Text('大前端之旅'),
actions: [
IconButton(
icon: const Icon(Icons.shopping_cart),
onPressed: () {},
),
],
bottom: AppBar(
title: Container(
width: double.infinity,
height: 40,
color: Colors.white,
child: const Center(
child: TextField(
decoration: InputDecoration(
hintText: 'Search for something',
prefixIcon: Icon(Icons.search),
suffixIcon: Icon(Icons.camera_alt)),
),
),
),
),
),
// Other Sliver Widgets
SliverList(
delegate: SliverChildListDelegate([
const SizedBox(
height: 400,
child: Center(
child: Text(
'This is an awesome shopping platform',
),
),
),
Container(
height: 1000,
color: Colors.pink,
),
]),
),
],
),
);
}
}
结论
边栏推荐
- PhpStudy 2016搭建-DVWA靶场
- 蔚来杯2022牛客暑期多校训练营6 ABGJM
- lua --- 基本语法学习
- 阿里巴巴的三个“一”打通业务价值
- lvm建立逻辑卷
- 数学基础(二)逆矩阵、伪逆矩阵、最小二乘解、最小范数解
- 67:第五章:开发admin管理服务:20:开发【解冻/冻结用户,接口】;(用户状态变更后,需要刷新用户状态,即变更用户会话信息:我们一般通过“删除redis中会话信息,强制用户重新登录“来做的;)
- 攻防世界——leaking
- Django+MySQL+HarmonyOS------------笔记二
- 业内首个「因果推断全流程」挑战赛!WAIC 2022 · 黑客马拉松邀全球开发者精英来挑战
猜你喜欢

【树莓派】在没有显示屏的情况下通过WIFI连电脑

【项目问题】Ionic开发移动端app,手把手教你如何打包生成apk

你真的了解IP地址吗?

CesiumJS 更新日志 1.96 与 1.97 - 新构建工具 esbuild 体验及 Model API 更替完成

攻防世界——leaking

SSRF漏洞

数学基础(一)矩阵对角化、SVD分解以及应用

67:第五章:开发admin管理服务:20:开发【解冻/冻结用户,接口】;(用户状态变更后,需要刷新用户状态,即变更用户会话信息:我们一般通过“删除redis中会话信息,强制用户重新登录“来做的;)

C#实现在企业微信内发送消息给指定人员帮助类

BLOB, TEXT, GEOMETRY or JSON column ‘xxxx‘ can‘t have a default value
随机推荐
我的MySQL安装这样了怎么解决也
Want to use SQL to achieve two days after the data contrast, the new data sheet and a list of tags
Do you really know IP addresses?
At the time of data intelligence, Jiuzhang Yunji DataCanvas won the "Most Investment Value Company"
云服务器搭建MQTT消息代理EMQX
看顶级测工怎么玩转Apifox接口测试工具
under项目under项目
DVWA全级别详细通关教程
HTTS 为什么更安全?
IIC通讯协议与EEPROM简介
攻防世界——fakebook
攻防世界——mfw
在数学里,minimum 和 minimal 有啥区别吗?
Offensive and defensive world - leaking
HyperLynx(三)传输线类型及相关设置
lvm creates logical volumes
手机APP测试流程规范和方法你知道多少?
The industry's first "Causal Inference Whole Process" Challenge!WAIC 2022 · Hackathon invites global developer elites to challenge
推荐系统 使用surprise库基于协同过滤的方法实现
进程间的五种通信方法