import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import 'package:get/get.dart'; import '../constants.dart'; import '../utils/api.dart'; import '../utils/http_utils.dart'; import '../utils/size_fit.dart'; import '../utils/storage.dart'; import 'component/top_container.dart'; class ChooseSocial extends StatelessWidget { const ChooseSocial({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Material( color: kBgColor, child: TopContainer(child: ChooseSocialContent())); } } class ChooseSocialContent extends StatefulWidget { const ChooseSocialContent({Key? key}) : super(key: key); @override State createState() => _ChooseSocialContentState(); } class _ChooseSocialContentState extends State { String keyword = ''; List socials = []; List searchs = []; bool isFirstEnter = true; @override void initState() { Map data = Get.parameters; if (data.isNotEmpty) { isFirstEnter = data['add_more'] != '1'; } getLinks(); // TODO: implement initState super.initState(); } Future getLinks() async { var data = await HttpUtils.get(Api.socials); // print(data.toString()); if (data['data'] is List) { print(data['data'].toString()); setState(() { socials = data['data']; }); } } Widget item(var social) { return SocialItem( keyword: keyword, social: social, isFirstEnter: isFirstEnter); } @override Widget build(BuildContext context) { SizeFit.initialize(context); return Stack(children: [ SingleChildScrollView( child: Column( children: [ SizedBox( height: 72.px, ), if (keyword.isEmpty) Container( width: 375.px, alignment: Alignment.topLeft, padding: EdgeInsets.only(left: 28.px, bottom: 5.px), child: Text( '热门平台', textAlign: TextAlign.left, style: TextStyle( color: const Color(0xFF74747A), fontSize: 12.px, fontWeight: FontWeight.bold), ), ), ...List.generate(socials.length, (i) { return item(socials[i]); }), if (keyword.isNotEmpty) GestureDetector( onTap: () { var social = { "id": "", "name": keyword, "logo": "", "types": ["LINK", "QR"], "description_example": "", "url_example": "" }; if (Get.parameters['update'] == '1') { Get.back(result: social); return; } Get.toNamed('/add_link', parameters: { 'social': jsonEncode(social), 'add_more': isFirstEnter ? '0' : '1' }); StorageUtil().remove('tempGuideLink0'); // Get.toNamed('/add_link'); }, child: Container( // height: 50.px, alignment: Alignment.centerLeft, padding: EdgeInsets.fromLTRB(30.px, 8.px, 30.px, 8.px), child: Row( children: [ SvgPicture.asset( 'assets/icons/other_link.svg', width: 32.px, height: 32.px, ), SizedBox( width: 13.px, ), Text( '用“', style: TextStyle(color: Colors.white, fontSize: 14.px), ), Text( keyword, style: TextStyle(color: kBtnColor, fontSize: 14.px), ), Text( '”做平台名称', style: TextStyle(color: Colors.white, fontSize: 14.px), ) ], ), ), ), SizedBox( height: 50.px, ) ], ), ), Positioned( left: 0, right: 0, bottom: 0, height: 48.px, child: Container( decoration: const BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ Color(0x00131314), Color(0xFF131314), Color(0xFF131314), ])), )), Column( children: [ Container( height: 72.px, padding: EdgeInsets.only(left: 16.px), decoration: const BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ Color(0xFF131314), Color(0xFF131314), Color(0xFF131314), Color(0x00131314) ])), child: Row( children: [ Expanded( child: Container( height: 40.px, padding: EdgeInsets.only(left: 10.px, right: 10.px), decoration: BoxDecoration( borderRadius: BorderRadius.circular(20.px), color: const Color(0xFF2C2C2E)), child: Row( children: [ SvgPicture.asset( 'assets/icons/search.svg', width: 16.px, height: 16.px, ), SizedBox( width: 12.px, ), Expanded( child: Container( height: 40.px, color: Colors.transparent, alignment: Alignment.centerLeft, child: TextField( autofocus: true, cursorColor: kBtnColor, onChanged: (value) { setState(() { keyword = value; }); }, style: TextStyle(color: Colors.white, fontSize: 14.px), decoration: InputDecoration( border: InputBorder.none, hintText: '请输入平台名称', hintStyle: TextStyle( fontSize: 14.px, color: const Color(0xFF74747A)), counterText: "", ), ), )) ], ), )), GestureDetector( onTap: () { Get.back(); }, child: Container( width: 72.px, alignment: Alignment.center, child: Text( '取消', style: TextStyle(color: kThemeColor, fontSize: 14.px), ), ), ) ], ), ) ], ), ]); } } class SocialItem extends StatefulWidget { String keyword; bool isFirstEnter; var social; SocialItem( {Key? key, required this.keyword, required this.social, required this.isFirstEnter}) : super(key: key); @override State createState() => _SocialItemState(); } class _SocialItemState extends State { bool isSeleted = false; @override Widget build(BuildContext context) { if (widget.keyword.isEmpty) { return GestureDetector( onTapDown: (TapDownDetails details) { setState(() { isSeleted = true; }); }, onTapUp: (TapUpDetails details) { setState(() { isSeleted = false; }); }, onTapCancel: () { setState(() { isSeleted = false; }); }, onTap: () { isSeleted = true; if (Get.parameters['update'] == '1') { Get.back(result: widget.social); return; } Get.toNamed('/add_link', parameters: { 'social': jsonEncode(widget.social), 'add_more': widget.isFirstEnter ? '0' : '1' }); StorageUtil().remove('tempGuideLink0'); }, child: Container( // height: 50.px, alignment: Alignment.centerLeft, padding: EdgeInsets.fromLTRB(12.px, 8.px, 12.px, 8.px), margin: EdgeInsets.only(left: 16.px, right: 16.px), decoration: BoxDecoration( color: isSeleted ? const Color(0xFF2C2C2E) : Colors.transparent, borderRadius: BorderRadius.circular(12.px)), child: Row( children: [ ClipRRect( borderRadius: BorderRadius.circular(8.rpx), child: Container( width: 32.px, height: 32.px, decoration: BoxDecoration( image: DecorationImage( image: NetworkImage(widget.social['logo']), fit: BoxFit.cover)), ), ), SizedBox( width: 13.px, ), Text( widget.social['name'], style: TextStyle(color: Colors.white, fontSize: 14.px), ) ], ), ), ); } if (widget.social['name'].indexOf(widget.keyword) == -1) { return const SizedBox( width: 0, height: 0, ); } List spans = []; int start = 0; // 当前要截取字符串的起始位置 int end; // end 表示要高亮显示的文本出现在当前字符串中的索引 String text = widget.social['name']; //'中国中 86'; String lightText = widget.keyword; //'中'; // 如果有符合的高亮文字 while ((end = text.indexOf(lightText, start)) != -1) { // 第一步:添加正常显示的文本 spans.add(TextSpan( text: text.substring(start, end), style: TextStyle(color: Colors.white, fontSize: 14.px))); // 第二步:添加高亮显示的文本 spans.add(TextSpan( text: lightText, style: TextStyle(color: const Color(0xFFFF9900), fontSize: 14.px))); // 设置下一段要截取的开始位置 start = end + lightText.length; } // 下面这行代码的意思是 // 如果没有要高亮显示的,则start=0,也就是返回了传进来的text // 如果有要高亮显示的,则start=最后一个高亮显示文本的索引,然后截取到text的末尾 spans.add( TextSpan( text: text.substring(start, text.length), style: TextStyle(color: Colors.white, fontSize: 14.px)), ); return GestureDetector( onTapDown: (TapDownDetails details) { setState(() { isSeleted = true; }); }, onTapUp: (TapUpDetails details) { setState(() { isSeleted = false; }); }, onTapCancel: () { setState(() { isSeleted = false; }); }, onTap: () { isSeleted = true; print(Get.parameters['update'].toString()); if (Get.parameters['update'] == '1') { Get.back(result: widget.social); return; } Get.toNamed('/add_link', parameters: { 'social': jsonEncode(widget.social), 'add_more': widget.isFirstEnter ? '0' : '1' }); StorageUtil().remove('tempGuideLink0'); }, child: Container( // height: 50.px, alignment: Alignment.centerLeft, padding: EdgeInsets.fromLTRB(12.px, 8.px, 12.px, 8.px), margin: EdgeInsets.only(left: 16.px, right: 16.px), decoration: BoxDecoration( color: isSeleted ? const Color(0xFF2C2C2E) : Colors.transparent, borderRadius: BorderRadius.circular(12.px)), child: Row( children: [ ClipRRect( borderRadius: BorderRadius.circular(6.rpx), child: Container( width: 32.px, height: 32.px, decoration: BoxDecoration( image: DecorationImage( image: NetworkImage(widget.social['logo']), fit: BoxFit.cover)), ), ), SizedBox( width: 13.px, ), RichText(text: TextSpan(children: spans)) ], ), ), ); } }