import 'dart:ui'; import 'package:dio/dio.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:huixiang/data/base_list_data.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../generated/l10n.dart'; import '../data/im_user.dart'; import '../retrofit/retrofit_api.dart'; import '../utils/font_weight.dart'; import '../view_widget/custom_image.dart'; import '../view_widget/my_appbar.dart'; import '../view_widget/settlement_tips_dialog.dart'; class ImSearch extends StatefulWidget { @override State createState() { return _ImSearch(); } } class _ImSearch extends State { ApiService? apiService; final TextEditingController editingController = TextEditingController(); FocusNode _focusNode = FocusNode(); List searchUser = []; int searchState = 0; int textType = 0; int searchUserIndex = 0; String selfUserId = ""; @override void initState() { super.initState(); SharedPreferences.getInstance().then((value) { selfUserId = value.getString("userId") ?? ""; }); } ///离开页面记着销毁和清除 @override void dispose() { _focusNode.unfocus(); super.dispose(); } ///搜索列表 queryImSearch(keyword) async { if (apiService == null) { SharedPreferences value = await SharedPreferences.getInstance(); apiService = ApiService(Dio(), context: context, token: value.getString("token"), showLoading:false ); } BaseListData? baseData = await apiService?.memberSearch(keyword).catchError((onError) { return BaseListData()..isSuccess = false; }); if (baseData?.isSuccess ?? false) { searchUser.clear(); baseData?.data?.forEach((element) { if (element.phone != "" && element.nickname != "") { searchUser.add(element); } }); searchState = 1; if (baseData?.data?.isEmpty ?? true) { searchState = 2; } setState(() {}); } } @override Widget build(BuildContext context) { return GestureDetector( onTap: () { FocusScope.of(context).requestFocus(FocusNode()); }, child: Scaffold( backgroundColor: Color(0xFFFFFFFF), resizeToAvoidBottomInset: false, appBar: MyAppBar( title: "搜索", leadingColor: Colors.black, background: Color(0xFFFFFFFF), ), body: Container( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ Expanded(child: imSearch()), GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { Navigator.of(context).pop(); }, child: Container( margin: EdgeInsets.only(top: 8.h, bottom: 29.h), alignment: Alignment.center, padding: EdgeInsets.only(right: 16.w), child: Text( S.of(context).quxiao, textAlign: TextAlign.center, style: TextStyle( color: Color(0xFFA29E9E), fontSize: 14.sp, fontWeight: MyFontWeight.medium, ), )), ) ], ), searchState == 2 ? Center( child: Text( "未找到该用户", style: TextStyle( fontSize: 14.sp, color: Color(0xFFA29E9E), ), ), ) : Expanded( child: Column( children: [ Padding( padding: EdgeInsets.only(bottom: 19.h), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ if (editingController.text != "" && searchState == 1) Padding( padding: EdgeInsets.only(left: 16.w), child: Text( "搜索用户:", textAlign: TextAlign.center, style: TextStyle( color: Color(0xFF060606), fontSize: 16.sp, fontWeight: MyFontWeight.medium, ), ), ), if (editingController.text != "" && searchState == 1) Expanded( child: Text( editingController?.text ?? "", style: TextStyle( fontSize: 16.sp, color: Color(0xFF32A060), fontWeight: MyFontWeight.regular), )) ], ), ), if (editingController.text != "" && searchState == 1) Expanded( child: ListView.builder( itemCount: searchUser?.length ?? 0, physics: BouncingScrollPhysics(), shrinkWrap: true, itemBuilder: (context, position) { return GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { setState(() { searchUserIndex = position; }); Navigator.of(context).pushNamed( '/router/personal_page', arguments: { "memberId": (searchUser[searchUserIndex] .mid ?? "") == selfUserId ? "0" : searchUser[searchUserIndex].mid, "inletType": 0 }); FocusScope.of(context) .requestFocus(FocusNode()); }, child: imSearchItem(searchUser[position]), ); }, )) ], )), ], ), ), ), ); } ///搜索 Widget imSearch() { return Container( margin: EdgeInsets.fromLTRB(16.w, 8.h, 16.w, 29.h), padding: EdgeInsets.symmetric(vertical: 13.h), decoration: BoxDecoration( color: Color(0xFFFDFCFC), borderRadius: BorderRadius.circular(4), ), child: TextField( textInputAction: TextInputAction.search, onChanged: (value) { setState(() { searchState = 3; }); if (isNumeric(value)) { textType = 1; } else { textType = 2; } if (editingController.text == null || editingController.text == "") { return; } else { queryImSearch(editingController.text ?? ""); } }, onEditingComplete: () { FocusScope.of(context).requestFocus(FocusNode()); if (editingController.text == null || editingController.text == "") { SmartDialog.show( widget: SettlementTips( () {}, text: "请输入姓名或手机号搜索", )); } else { queryImSearch(editingController.text ?? ""); } }, controller: editingController, style: TextStyle( fontSize: 14.sp, ), decoration: InputDecoration( hintText: "输入姓名或手机号搜索", hintStyle: TextStyle( fontSize: 14.sp, color: Color(0xFFA29E9E), ), isCollapsed: true, prefixIcon: Padding( padding: EdgeInsets.only(left: 15.w, right: 5.w), child: Image.asset( "assets/image/icon_search.webp", width: 14.h, height: 14.h, color: Color(0xFFB3B3B3), ), ), prefixIconConstraints: BoxConstraints(), border: InputBorder.none, ), ), ); } ///搜索列表 Widget imSearchItem(ImUser searchUser) { return Container( padding: EdgeInsets.only(left: 10.w, right: 16.w, bottom: 15.h), child: Row( children: [ MImage( searchUser?.avatar ?? "", isCircle: true, height: 54.h, width: 54.h, fit: BoxFit.cover, errorSrc: "assets/image/default_1.webp", fadeSrc: "assets/image/default_1.webp", ), SizedBox( width: 12.w, ), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ RichText( text: TextSpan( style: TextStyle(color: Colors.black), // 默认文本颜色为黑色 children: _splitText(searchUser?.nickname ?? "", editingController.text) .map((part) { return TextSpan( text: part, style: part == editingController.text ? TextStyle(color: Colors.green) // 匹配部分变为绿色 : null, ); }).toList(), ), ), SizedBox( height: 7.h, ), RichText( text: TextSpan( style: TextStyle(color: Colors.black), // 默认文本颜色为黑色 children: _splitText( searchUser?.phone ?? "", editingController.text) .map((part) { return TextSpan( text: part, style: part == editingController.text ? TextStyle(color: Colors.green) // 匹配部分变为绿色 : null, ); }).toList(), ), ), ], ), ), ], )); } /// 搜索结构显示 List _splitText(String text, String search) { if (text == null || text.isEmpty || search == null || search.isEmpty) { throw ArgumentError('text and search must not be null or empty'); } final List parts = []; int start = 0; int index = text.indexOf(search); while (index != -1) { if (index > start) { parts.add(text.substring(start, index)); } parts.add(text.substring(index, index + search.length)); start = index + search.length; index = text.indexOf(search, start); } if (start < text.length) { parts.add(text.substring(start)); } return parts; } /// 判断给的字符串是否全部由数字组成 bool isNumeric(String str) { RegExp regExp = RegExp(r'^\d+$'); return regExp.hasMatch(str); } }