Flutter高仿微信系列共59篇,从Flutter客户端、Kotlin客户端、Web服务器、数据库表结构、Xmpp即时通讯服务器、视频通话服务器、腾讯云服务器全面讲解。
效果图:
实现代码:
/** * Author : wangning * Email : maoning20080809@163.com * Date : 2022/8/11 12:16 * Description : 搜索好友 */ Color themeDef = Color(0xffEDEDED); class SearchFriends extends StatelessWidget { const SearchFriends({super.key}); @override Widget build(BuildContext context) { return const SearchFriendsPage(title: '搜索好友'); } } class SearchFriendsPage extends StatefulWidget { const SearchFriendsPage({super.key, required this.title}); final String title; @override State<SearchFriendsPage> createState() => _SearchFriendsState(); } class _SearchFriendsState extends State<SearchFriendsPage> { //搜索提示框 bool hideSearch = true; //搜索结果 bool hideSearchResult = true; //从服务器搜索好友 void _getUserLikeAccount(String searchAccount) async { bool isNetwork = await CommonNetwork.isNetwork(); if(!isNetwork) { CommonUtils.showNetworkError(context); return; } if(searchAccount.isEmpty){ return; } String account = ""; List<UserBean> userlist = await UserRepository.getInstance().getUserLikeAccount(account, searchAccount); if(userlist.isEmpty){ hideSearchResult = false; } setState(() { _userlist = userlist; }); } @override void initState() { super.initState(); } String results = "";//原来的内容是空的 final TextEditingController controller = TextEditingController(text: ""); ScrollController _controller = ScrollController(); List<UserBean> _userlist = []; @override Widget build(BuildContext context) { return Scaffold( appBar: WnAppBar.getAppBar(context, Text("${widget.title}")), body: Column( children: [ _getEnterAccountWidget(), _getSearchWidget(), Offstage( offstage: hideSearchResult, child: _noDataWidget(), ), Expanded( child: ListView.builder( controller: _controller, itemBuilder: (BuildContext context, int index) { return ChatContentView(userBean: _userlist[index]); }, itemCount: _userlist.length, ) ), ], ), ); } //没有好友提示 Widget _noDataWidget() { return Center( child: Padding( padding: EdgeInsets.all(10.0), child: Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: <Widget>[ Text('搜索结果为空...',style: TextStyle(fontSize: 16.0),) ], ), ), ); } //账号输入框 Widget _getEnterAccountWidget(){ return Container( height: 60, padding: const EdgeInsets.only(left: 20.0, top: 10, right: 10, bottom: 10),//上下左右都设置边距 child: Row( children: [ Expanded( child: Container( margin: EdgeInsets.only(right: 20), padding: EdgeInsets.only(left: 10, top:10, right: 10), height: 60, decoration: BoxDecoration(borderRadius: BorderRadius.all(Radius.circular(5.0),),color: Colors.white), child: TextField( controller: controller, //decoration: InputDecoration.collapsed(hintText: "账号/手机号"), decoration: InputDecoration(hintText: "账号/手机号", counterText: "", border: InputBorder.none), autocorrect: true, //是否自动更正 autofocus: false, maxLines: 1, minLines: 1, maxLength: 20, textAlign: TextAlign.start, style: TextStyle(color: Colors.black), cursorColor: Colors.green, onTap: (){ }, onChanged: (value){ //LogUtils.d("录入的值:${value}"); String content = controller.text; if(content.length > 0){ hideSearch = false; } else { hideSearch = true; } hideSearchResult = true; setState(() { }); }, //onSubmitted: _handleSubmitted, enabled: true, //是否禁用 ), ), ), MaterialButton( color: Colors.blue, textColor: Colors.white, child: Text("取消"), onPressed: (){ Navigator.pop(context); }, ), ], ), ); } //点击搜索按钮 Widget _getSearchWidget(){ return InkWell( onTap: (){ _getUserLikeAccount(controller.text); }, child: Offstage( offstage: hideSearch, child: Container( height: 70, width: double.infinity, padding: const EdgeInsets.only(left: 12.0, top: 10, right: 20,bottom: 10),//上下左右都设置边距 child: Row( children: [ Image.asset(CommonUtils.getBaseIconUrlPng("main_contacts_icon"), width: 50, height: 50,), SizedBox(width: 10,), Text("搜索:"), Expanded(child: Text("${controller.text}")) ], ), ), ), ); } } class ChatContentView extends StatefulWidget { final UserBean userBean; ChatContentView({required this.userBean}); @override State<ChatContentView> createState() => _ChatContentViewState(); } class _ChatContentViewState extends State<ChatContentView> { String account = SpUtils.getString(CommonUtils.LOGIN_ACCOUNT); @override void initState() { super.initState(); } void _clickDetails(String searchAcccount) async{ ContactsBean? contactsBean = await ContactsRepository.getInstance().findContactByFromOrToAccount(account, searchAcccount); if(contactsBean != null && contactsBean.type == ContactsBean.typeReceive){ //好友直接跳转到聊天页面 Navigator.popUntil(context, (route) {return route.isFirst;}); await Navigator.push(context, MaterialPageRoute(builder: (c) {return HomeChatPage(toChatId: searchAcccount);})); } else { Navigator.pop(context); Navigator.push(context,MaterialPageRoute(builder: (context)=>AddFriends(userBean: widget.userBean,))); } } @override Widget build(BuildContext context) { return InkWell( onTap: (){ _clickDetails(widget.userBean.account??""); }, child: Container( //decoration: BoxDecoration(color: Colors.white70), decoration: BoxDecoration(color: Colors.white70, border: Border(bottom:BorderSide(color: Color(0xffd9d9d9), width: 0.3))), //margin: EdgeInsets.only(top: 8.0, bottom: 8), padding: EdgeInsets.all(16.0), child: Row( children: <Widget>[ Expanded( child: Stack( alignment: AlignmentDirectional.centerStart, children: [ Text("账号:${widget.userBean.account} 昵称:${widget.userBean.nickName}",style: TextStyle(fontSize: 18),), ], ), ), ], ), ), ); } }