import 'dart:async'; import 'dart:io'; import 'dart:math'; import 'package:aiplot/common/EventBusUtil.dart'; import 'package:aiplot/common/app_util.dart'; import 'package:aiplot/dialog/ad_free_dialog.dart'; import 'package:aiplot/dialog/free_upper_limit_dialog.dart'; import 'package:aiplot/dialog/guide_theme_switch_tip.dart'; import 'package:aiplot/dialog/reference_image_tip_dialog.dart'; import 'package:aiplot/dialog/tip_overwrite_not_dialog.dart'; import 'package:aiplot/network/NetworkConfig.dart'; import 'package:aiplot/tools/create/create_model.dart'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:flutter_native_image/flutter_native_image.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:image_cropper/image_cropper.dart'; import 'package:image_picker/image_picker.dart'; import 'package:sensors_analytics_flutter_plugin/sensors_analytics_flutter_plugin.dart'; import '../../bean/draw_template_bean.dart'; import '../../bean/text_to_image_bean.dart'; import '../../bean/user_draw_bean.dart'; import '../../common/Global.dart'; import '../../common/dialog_bean.dart'; import '../../common/dialog_manager.dart'; import '../../common/dialog_util.dart'; import '../../common/func.dart'; import '../../dialog/guideDialog.dart'; import '../../dialog/login_dialog.dart'; import '../../dialog/phone_login_dialog.dart'; import '../../generated/l10n.dart'; import '../drawdetails/draw_details_page.dart'; import '../start_model.dart'; import 'guidance_label.dart'; ///创作页 class CreatePage extends StatefulWidget { const CreatePage({Key? key}) : super(key: key); @override State createState() => _CreatePageState(); } class _CreatePageState extends State with SingleTickerProviderStateMixin, AutomaticKeepAliveClientMixin { @override bool get wantKeepAlive => true; StreamSubscription? subscription; final CreateModel _viewModel = CreateModel(); TextToImageBean? textToImageBean; final StartModel _startModel = StartModel(); StreamSubscription? _tabBarEvent; StreamSubscription? _copyDrawingEvent; StreamSubscription? _refreshUserdata; bool isEntered = false; //输入框内容 String promptText = ""; void _textFieldChanged(String str) { if (str != "") { isEntered = true; } else { isEntered = false; } promptText = str; } final TextEditingController _textController = TextEditingController(text: ''); final ScrollController _gridController = ScrollController(); String initImg = ""; //参考图 final FocusNode _commentFocus = FocusNode(); //输入框焦点 int currentIndex = 0; //当前风格下标 int currentSizeIndex = 0; //当前尺寸下标 //尺寸 List sizeList = [ AssetImage('assets/images/img_11.png'), AssetImage('assets/images/img_34.png'), AssetImage('assets/images/img_43.png'), AssetImage('assets/images/img_916.png'), AssetImage('assets/images/img_169.png'), ]; List sizeListNo = [ AssetImage('assets/images/img_11_no.png'), AssetImage('assets/images/img_34_no.png'), AssetImage('assets/images/img_43_no.png'), AssetImage('assets/images/img_916_no.png'), AssetImage('assets/images/img_169_no.png'), ]; //风格列表 List templateList = []; //顶部banner数据 List bannerGalleryList = []; final ScrollController _bannerController = ScrollController(); //滑动条数值 double sliderValue = 4.0; double repaintValue = 0.4; //重绘度 CroppedFile? selectImage; //选择的相册图 String copyImgUrl = ""; //画同款图片 double countP = 0.0; //消耗点数 String cueWord = ""; //选中类型 int selectType = 0; int mainBodyIndex = 0; //当前主体下标 //风格列表 List t1 = []; //选择前 List t2 = []; //选择后 List t3 = []; //选择的选项集合 Map> selectList1 = {}; //引导词 String introducer = ""; /// 动画控制器 AnimationController? _controller; /// 非线性动画 Animation? _curveAnimation; Map? responseData; GlobalKey loginDialogKey = GlobalKey(); //登录弹框key Timer? timer; @override void initState() { // TODO: implement initState super.initState(); if (Platform.isIOS) { subscription = Connectivity().onConnectivityChanged.listen((ConnectivityResult result) { // Got a new connectivity status! if (result == ConnectivityResult.mobile || result == ConnectivityResult.wifi) { setState(() { _viewModel.getDrawTemplateList(); _viewModel.getUserData(); _viewModel.getGalleryList(); _startModel.getAppConfig(); }); } }); } //引导模式数据 if (NetworkConfig.Language != "zh") { responseData = GuidanceLabel.responseDataEn; } else { responseData = GuidanceLabel.responseDataZh; } //banner滑动监听 到底部时跳到第一位 _bannerController.addListener(() { if (_bannerController.offset >= _bannerController.position.maxScrollExtent && !_bannerController.position.outOfRange) { _bannerController.jumpTo(0.0); } }); //设置定时器 自动滑动 timer = Timer.periodic(Duration(milliseconds: 100), (Timer t) { if (_bannerController.hasClients) { _bannerController.animateTo( _bannerController.offset + 15, duration: const Duration(milliseconds: 500), curve: Curves.easeOut, ); } }); ///动画 _controller = AnimationController( duration: const Duration(seconds: 1), vsync: this, ); _curveAnimation = Tween(begin: 0.0, end: 1.0).animate(CurvedAnimation(parent: _controller!, curve: Curves.easeInOut)); ///eventbus //刷新用户信息 _tabBarEvent = EventBusUtil.listen((event) { _commentFocus.unfocus(); if (event.Tab == 1) { _viewModel.getUserData(); } }); _refreshUserdata = EventBusUtil.listen((event) { _commentFocus.unfocus(); _viewModel.getUserData(); }); //画同款 _copyDrawingEvent = EventBusUtil.listen((event) { _textController.text = NetworkConfig.prompt; promptText = NetworkConfig.prompt; copyImgUrl = NetworkConfig.followUrl; selectImage = null; selectList1 = {}; introducer = ""; for (int i = 0; i < templateList.length; i++) { if (NetworkConfig.templateId == templateList[i].Id) { currentIndex = i; ///滑动到选中的风格 double offsetX = (currentIndex / 2) * 86; _gridController.animateTo( offsetX, duration: Duration(milliseconds: 500), curve: Curves.decelerate, ); } } currentSizeIndex = NetworkConfig.sizeTemplateId; print("object${NetworkConfig.prompt}"); print("object${NetworkConfig.templateId}"); print("object${NetworkConfig.sizeTemplateId}"); setState(() {}); }); ///网络请求回调 subscription = _viewModel.streamController.stream.listen((newData) { String code = newData['code']; if (code.isNotEmpty) { switch (code) { case "getDrawTemplateList": //风格列表 EasyLoading.dismiss(); templateList = newData['data']; if (NetworkConfig.isImitate) { _textController.text = NetworkConfig.prompt; promptText = NetworkConfig.prompt; for (int i = 0; i < templateList.length; i++) { if (NetworkConfig.templateId == templateList[i].Id) { currentIndex = i; } } currentSizeIndex = NetworkConfig.sizeTemplateId; } break; case "txt2Img": //上传生成信息 EasyLoading.dismiss(); textToImageBean = newData['data']; Navigator.push( context, MaterialPageRoute( builder: (context) => DrawDetailsPage( true, taskId: textToImageBean!.TaskId!, isMyWork: true, describeText: cueWord, ), )); break; case "upperLimit": //免费保存上限 EasyLoading.dismiss(); FunctionUtil.popDialog(context, FreeUpperLimitDialog( onTap: (index) { if (index == 1) { Navigator.pushNamed(context, "/ShopPage"); } }, )); break; case "InsufficientPoints": //绘画点不足 Fluttertoast.showToast( msg: newData['data'], toastLength: Toast.LENGTH_SHORT, gravity: ToastGravity.CENTER, timeInSecForIosWeb: 1, backgroundColor: Colors.black, textColor: Colors.white, fontSize: 16.0); Navigator.pushNamed(context, "/ShopPage"); break; case "bannerGallery": bannerGalleryList = newData['data']; break; case "getUserData": break; default: String message = newData['data']; EasyLoading.showToast(message); break; } } setState(() {}); }); getData(); } ///获取数据 Future getData() async { for (var name in responseData!["body"]) { t1.add(name["name"]); } t2 = responseData!["body"][0]["content"]; for (int i = 0; i < t2.length; i++) { selectList1[i] = []; } EasyLoading.show(status: 'loading...'); _viewModel.getDrawTemplateList(); _viewModel.getUserData(); _viewModel.getGalleryList(); } //生成图片 0:文生图 1:图生图 Future _createPic(int type, String prompt, int templateId, int sizeTemplateId) async { if (type == 0) { _viewModel.txt2Img(prompt, templateId, sizeTemplateId, 0); } else { _viewModel.img2Img(prompt, initImg, templateId, sizeTemplateId, double.parse(repaintValue.toStringAsFixed(1)), 0); } _viewModel.getUserData(); } @override void dispose() { // TODO: implement dispose subscription?.cancel(); _tabBarEvent?.cancel(); timer?.cancel(); _refreshUserdata?.cancel(); _copyDrawingEvent?.cancel(); super.dispose(); } @override Widget build(BuildContext context) { final size = MediaQuery.of(context).size; final w100 = size.width / 3.6; //100 final h32 = size.width / 11.25; //32 final h70 = size.width / 5.1428571428571; //301 final h40 = size.width / 9; //40 final w193 = size.width / 1.8652849740932; //57 final h186 = size.width / 1.9354838709677; //186 final w86 = size.width / 4.1860465116279; //86 final w124 = size.width / 2.9032258064516; //86 if (templateList.isNotEmpty && templateList[currentIndex].Charging != null) { countP = templateList[currentIndex].Charging! + (selectImage != null || copyImgUrl != "" ? 1 : 0); } //推荐词 List recommendList = [ S.of(context).A_colorful, S.of(context).Brunette_princess, S.of(context).Beautiful_angel, S.of(context).Rapeseed_flowers, S.of(context).Long_hair, S.of(context).A_close, S.of(context).After_rain, S.of(context).Distant_mountains, S.of(context).Snow_mountain, S.of(context).The_stars, ]; return Scaffold( backgroundColor: Colors.white, appBar: AppBar( backgroundColor: Colors.white, elevation: 0, title: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Container( margin: const EdgeInsets.only(right: 10), child: const Image( width: 23, height: 23, image: AssetImage('assets/images/ic_title.png'), ), ), Text( "AI${S.of(context).Creation_ja}", style: const TextStyle(color: Colors.black, fontSize: 20), ), ], ), centerTitle: true, ), body: Stack( alignment: Alignment.center, children: [ SingleChildScrollView( child: Column( mainAxisAlignment: MainAxisAlignment.start, children: [ ///顶部banner bannerGalleryList != null && bannerGalleryList.isNotEmpty ? GestureDetector( onTap: () { EventBusUtil.fire(TabBarJumpEvent(0)); }, child: Container( height: 182, width: size.width, margin: EdgeInsets.only(top: 10), child: ListView.builder( controller: _bannerController, itemCount: bannerGalleryList.length, itemBuilder: (BuildContext context, int index) { return _bannerItem(bannerGalleryList[index], index); }, physics: NeverScrollableScrollPhysics(), scrollDirection: Axis.horizontal), ), ) : Container(), Container( margin: const EdgeInsets.only(left: 15, top: 26), alignment: Alignment.centerLeft, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "*${S.of(context).Describe_in_detail}", style: TextStyle(color: Colors.black, fontSize: NetworkConfig.Language == "ja" ? 12 : 16), ), ///点数 GestureDetector( onTap: () { if (NetworkConfig.userId == "") { showLoginDialog(); } else { Navigator.pushNamed(context, "/ShopPage"); } }, child: Container( height: 18, margin: const EdgeInsets.only(right: 15), padding: const EdgeInsets.only(left: 5, right: 5), decoration: BoxDecoration(borderRadius: const BorderRadius.all(Radius.circular(9))), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ const Image( width: 15, height: 15, image: AssetImage('assets/images/ic_count.png'), ), Container( margin: EdgeInsets.only(left: 5), child: Text( "×${NetworkConfig.allCurrency}", style: const TextStyle(color: Color(0xFF8841FF), fontSize: 12), ), ), ], ), ), ) ], ), ), ///输入框 描述 Container( alignment: Alignment.center, margin: const EdgeInsets.only(top: 13, left: 15, right: 15), padding: const EdgeInsets.only(left: 9, top: 13, right: 9), decoration: const BoxDecoration( //背景 color: Color(0xFFF3F3FB), //设置四周圆角 角度 borderRadius: BorderRadius.all(Radius.circular(6.6)), //设置四周边框 ), child: TextField( controller: _textController, keyboardType: TextInputType.name, focusNode: _commentFocus, decoration: InputDecoration.collapsed( hintText: '${S.of(context).for_instance}\n\n${S.of(context).more_detailed}', hintStyle: const TextStyle(fontSize: 16.0, color: Color(0xFFB5B5B5))), textAlign: TextAlign.left, //文本对齐方式 //最大长度,设置此项会让TextField右下角有一个输入数量的统计字符串 maxLines: 7, //最大行数 style: const TextStyle(fontSize: 16.0, color: Colors.black), //输入文本的样式 onChanged: _textFieldChanged, autofocus: false, maxLength: 500, // inputFormatters: [ // /* FilteringTextInputFormatter.allow(RegExp('[0-9]')),*/ // //只能输入汉字或者字母或数字 // LengthLimitingTextInputFormatter(500), // //最大长度 // ], ), ), ///随机提示词 推荐 Container( alignment: Alignment.centerLeft, margin: const EdgeInsets.only(top: 7, left: 15), child: GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { _startOrStopRotation(); _commentFocus.unfocus(); var indexNet = Random().nextInt(10); if (isEntered) { FunctionUtil.popDialog(context, TipOverwriteNotDialog( onTap: (index) { if (index == 1) { NetworkConfig.prompt = recommendList[indexNet]; _textController.text = recommendList[indexNet]; promptText = recommendList[indexNet]; isEntered = false; } }, )); } else { NetworkConfig.prompt = recommendList[indexNet]; _textController.text = recommendList[indexNet]; promptText = recommendList[indexNet]; } }, child: SizedBox( width: 180, height: 40, child: Row( mainAxisAlignment: MainAxisAlignment.start, children: [ Text( S.of(context).Random_Description, style: TextStyle( color: const Color(0xFFBB71E0), fontSize: NetworkConfig.Language == "ja" ? 12 : 14, ), ), Container( margin: const EdgeInsets.only(left: 5, top: 1), child: RotationTransition( turns: _curveAnimation!, child: const Image( width: 15, height: 15, image: AssetImage('assets/images/ic_random.png'), ), ), ) ], ), ), ), ), ///类型 Container( margin: const EdgeInsets.only(left: 15, top: 20, right: 15), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ ///简易 GestureDetector( onTap: () { setState(() { selectType = 0; }); }, child: Container( width: w100, height: h32, alignment: Alignment.center, decoration: BoxDecoration( color: Color(selectType == 0 ? 0xFFBB70E0 : 0xFFF3F3FB), borderRadius: const BorderRadius.all(Radius.circular(5))), child: Text( S.of(context).Easy_mode, style: TextStyle(color: Color(selectType == 0 ? 0xFFFFFFFF : 0xFF999999)), ), ), ), ///引导模式 GestureDetector( onTap: () { setState(() { selectType = 1; }); }, child: Container( width: w100, height: h32, alignment: Alignment.center, decoration: BoxDecoration( color: Color(selectType == 1 ? 0xFFBB70E0 : 0xFFF3F3FB), borderRadius: const BorderRadius.all(Radius.circular(5))), child: Text( S.of(context).guide, style: TextStyle(color: Color(selectType == 1 ? 0xFFFFFFFF : 0xFF999999)), ), ), ), ///艺术家 GestureDetector( onTap: () { EasyLoading.showToast(S.of(context).The_function); }, child: Stack( children: [ Container( width: w100, height: h32, alignment: Alignment.center, decoration: const BoxDecoration(color: Color(0xFFF3F3FB), borderRadius: BorderRadius.all(Radius.circular(5))), child: Text( S.of(context).Artist, style: const TextStyle(color: Color(0xFF999999)), ), ), Positioned( right: 0, child: Container( width: 30, height: 11, color: Colors.red, alignment: Alignment.center, child: const Text( "VIP", style: TextStyle(color: Colors.white, fontSize: 10), ), )), ], ), ), ], ), ), ///0 简易风格 1 引导模式 selectType == 1 ? Column( children: [ Container( margin: const EdgeInsets.only(left: 15, top: 23), alignment: Alignment.centerLeft, child: Text( S.of(context).The_subject, style: const TextStyle(color: Colors.black, fontSize: 16), ), ), ///主体 Container( margin: const EdgeInsets.only(top: 13), child: GridView.count( shrinkWrap: true, primary: false, //水平子Widget之间间距 crossAxisSpacing: 10, //垂直子Widget之间间距 mainAxisSpacing: 10, //GridView内边距 padding: const EdgeInsets.only(left: 16, right: 16), //一行的Widget数量 crossAxisCount: 4, //子Widget宽高比例 childAspectRatio: 2.7, //子Widget列表 children: _sizeItem2(t1), //类似 cellForRow 函数 scrollDirection: Axis.vertical), ), ///内容 Container( child: ListView.builder( shrinkWrap: true, itemCount: t2.length, itemExtent: 100, padding: const EdgeInsets.all(0), //数据的数量 itemBuilder: (context, index) { return GestureDetector( onTap: () {}, child: Column( children: [ Container( margin: const EdgeInsets.only(left: 15, top: 23), alignment: Alignment.centerLeft, child: Text( t2[index]["name"].toString(), style: const TextStyle(color: Colors.black, fontSize: 16), ), ), _sizeItem3(index), ], )); }, physics: const NeverScrollableScrollPhysics(), //类似 cellForRow 函数 scrollDirection: Axis.vertical), ), ], ) : Container(), ///绘画风格 Container( margin: const EdgeInsets.only(left: 15, top: 30), alignment: Alignment.centerLeft, child: Text( S.of(context).Painting_style, style: const TextStyle(color: Colors.black, fontSize: 16), ), ), Container( margin: const EdgeInsets.only(top: 11), child: SizedBox( height: h186, width: MediaQuery.of(context).size.width, child: GridView.count( controller: _gridController, shrinkWrap: true, //水平子Widget之间间距 crossAxisSpacing: 10.0, //垂直子Widget之间间距 mainAxisSpacing: 10.0, //GridView内边距 padding: const EdgeInsets.only(left: 15, right: 15), //一行的Widget数量 crossAxisCount: 2, //子Widget宽高比例 childAspectRatio: 1.0, //子Widget列表 children: _item(templateList, w86), //类似 cellForRow 函数 scrollDirection: Axis.horizontal)), ), ///尺寸 Container( margin: const EdgeInsets.only(left: 15, top: 23), alignment: Alignment.centerLeft, child: Text( S.of(context).Image_scale, style: const TextStyle(color: Colors.black, fontSize: 16), ), ), Container( margin: const EdgeInsets.only(top: 11), child: GridView.count( shrinkWrap: true, primary: false, //水平子Widget之间间距 crossAxisSpacing: 5, //垂直子Widget之间间距 mainAxisSpacing: 10, //GridView内边距 padding: const EdgeInsets.only(left: 16, right: 16), //一行的Widget数量 crossAxisCount: 3, //子Widget宽高比例 childAspectRatio: 3.2, //子Widget列表 children: _sizeItem(sizeList, sizeListNo), //类似 cellForRow 函数 scrollDirection: Axis.vertical), ), ///参考图 Container( margin: const EdgeInsets.only(left: 15, top: 30, right: 15), alignment: Alignment.center, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( S.of(context).Reference_drawing, style: const TextStyle(color: Colors.black, fontSize: 16), ), //说明弹框 GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { FunctionUtil.popDialog(context, ReferenceImageTipDialog()); }, child: Container( padding: EdgeInsets.all(10), child: const Image( width: 20, height: 20, image: AssetImage('assets/images/ic_tip.png'), ), ), ) ], ), ), ///相册图(选取相册图片) Container( alignment: Alignment.centerLeft, child: Stack( children: [ GestureDetector( onTap: () async { XFile img = await AppUtil.getImages(); selectImage = await AppUtil.cropImage(img.path, currentSizeIndex); setState(() {}); }, child: Container( height: w86, margin: const EdgeInsets.only(left: 15, top: 10), padding: const EdgeInsets.only(right: 20), ///画廊画同款 child: copyImgUrl != "" ? CachedNetworkImage( fit: BoxFit.cover, imageUrl: copyImgUrl, errorWidget: (context, url, error) => const Icon(Icons.error), ) ///相册选择图片 : selectImage != null ? Image.file( File(selectImage!.path), fit: BoxFit.cover, ) : const Image( image: AssetImage('assets/images/ic_upload.png'), ), ), ), Positioned( right: 0, child: selectImage != null || copyImgUrl != "" ? GestureDetector( onTap: () { selectImage = null; copyImgUrl = ""; initImg = ""; setState(() {}); }, child: const Image( width: 15, height: 15, image: AssetImage('assets/images/img_delete.png'), ), ) : Container()) ], ), ), Container( margin: const EdgeInsets.only(left: 15, top: 11), alignment: Alignment.centerLeft, child: Text( S.of(context).Will_refer, style: const TextStyle(color: Color(0xFF999999), fontSize: 12), ), ), Container( margin: const EdgeInsets.only(left: 15, top: 22), alignment: Alignment.centerLeft, child: Text( S.of(context).Reference_drawing_redrawing, style: const TextStyle(color: Colors.black, fontSize: 16), ), ), ///滑动条 重绘度 Container( margin: const EdgeInsets.only(top: 15), alignment: Alignment.centerLeft, child: Row( children: [ Flexible( flex: 9, child: SliderTheme( data: SliderTheme.of(context).copyWith( trackHeight: 4.0, ), child: Slider( value: sliderValue, activeColor: const Color(0xFF8841FF), inactiveColor: const Color(0xFFD1D1D1), min: 1, max: 10, onChanged: (value) { setState(() { sliderValue = value; repaintValue = sliderValue * 0.1; }); }, ), )), Flexible( flex: 1, child: Text( sliderValue.toStringAsFixed(0), style: const TextStyle(color: Color(0xFF555555)), ), ), ], )), Container( margin: const EdgeInsets.only(left: 15, top: 11, bottom: 100), alignment: Alignment.centerLeft, child: Text( S.of(context).The_smaller, style: TextStyle(color: Color(0xFF999999), fontSize: 12), ), ), ], ), ), Positioned( bottom: 0, child: Container( color: Colors.white, width: size.width, height: 80, alignment: Alignment.topCenter, padding: EdgeInsets.only(left: 15, right: 15, top: 10), child: Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ ///生成绘画 GestureDetector( onTap: () async { _generateImages(); }, child: Container( width: w193, height: h40, alignment: Alignment.center, decoration: const BoxDecoration( gradient: LinearGradient( begin: Alignment.centerLeft, //渐变开始于上面的中间开始 end: Alignment.centerRight, //渐变结束于下面的中间 colors: [Color(0xFF808EEF), Color(0xFFBE6FDF)]), borderRadius: BorderRadius.all(Radius.circular(20))), //显示消耗点 child: templateList.isNotEmpty ? Text( "${S.of(context).Generate_painting}(${S.of(context).Consume} ${countP.truncate()} ${S.of(context).point})", style: const TextStyle(color: Colors.white, fontSize: 16), ) : Text( S.of(context).Generate_painting, style: const TextStyle(color: Colors.white, fontSize: 16), ), ), ), ///免费 GestureDetector( onTap: () async { if (NetworkConfig.userId != "") { if (NetworkConfig.appConfigBean != null && NetworkConfig.appConfigBean!.AdFree != null) { FunctionUtil.popDialog( context, AdFreeDialog( onTap: (index) {}, )); } } else { showLoginDialog(); } }, child: Container( width: w124, height: h40, alignment: Alignment.center, decoration: const BoxDecoration(color: Color(0xFFF3F3FB), borderRadius: BorderRadius.all(Radius.circular(20))), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ const Image(width: 22, image: AssetImage('assets/images/ic_ad.png')), Container( margin: EdgeInsets.only(left: 8), child: Text( S.of(context).Free, style: const TextStyle(color: Color(0xFF666666), fontSize: 16), ), ), ], ), ), ), ], ), NetworkConfig.appConfigBean != null && NetworkConfig.appConfigBean!.SharingRewards != null ? Container( alignment: Alignment.centerLeft, margin: const EdgeInsets.only(top: 5), child: Text( "${S.of(context).Upload_the_painting} ${NetworkConfig.appConfigBean!.SharingRewards} ${S.of(context).Painting_points}", style: TextStyle(color: Color(0xFF999999), fontSize: NetworkConfig.Language == "ja" ? 8 : 12), ), ) : Container(), ], ), ), ), ], ), ); } ///生成图片 _generateImages() async { EasyLoading.show(status: 'loading...'); if (NetworkConfig.userId != "") { if (promptText != "" || introducer != "") { _commentFocus.unfocus(); //合并提示词 cueWord = "$promptText${selectType == 0 ? "" : introducer}${selectType == 0 ? "" : ","}${selectType == 0 ? "" : t1[mainBodyIndex]}"; if (cueWord.startsWith(",")) { cueWord = cueWord.substring(1); } if (selectImage != null || copyImgUrl != "") { if (copyImgUrl == "") { //处理图片 initImg = await _compressPictures(); } else { initImg = (await AppUtil.networkImageToBase64(copyImgUrl))!; } ///图生图 _createPic(1, cueWord, templateList[currentIndex].Id!, currentSizeIndex); //埋点 SensorsAnalyticsFlutterPlugin.track('AidrawStart', {'AidrawMode': '图生图', 'AidrawCZMode': selectType == 0 ? '简易模式' : '引导模式'}); } else { ///文生图 _createPic(0, cueWord, templateList[currentIndex].Id!, currentSizeIndex); //埋点 SensorsAnalyticsFlutterPlugin.track('AidrawStart', {'AidrawMode': '文生图', 'AidrawCZMode': selectType == 0 ? '简易模式' : '引导模式'}); } NetworkConfig.prompt = cueWord; } else { EasyLoading.showToast(S.of(context).Please_fill); } } else { showLoginDialog(); } } //动画 void _startOrStopRotation() { setState(() { if (_controller!.isAnimating) { _controller!.stop(); } _controller!.forward(from: 0.0); }); } _bannerItem(UserDrawBean data, int index) { return Container( margin: EdgeInsets.only(left: 10), child: ClipRRect( borderRadius: BorderRadius.circular(7), child: CachedNetworkImage( imageUrl: data.ImageUrl!, fit: BoxFit.fitHeight, )), // child: Image(image: list[index]), ); } //风格 _item(List list, double w86) { return list.map((e) { int index = list.indexOf(e); return GestureDetector( onTap: () { currentIndex = index; NetworkConfig.templateId = list[index].Id!; setState(() {}); }, child: Container( alignment: Alignment.center, child: Stack( alignment: Alignment.center, children: [ CachedNetworkImage(imageUrl: list[index].ImageSmall!), currentIndex == index ? const Image(image: AssetImage('assets/images/ic_style_s.png')) : Container(), Positioned( bottom: 1, child: Container( width: w86, height: 20, alignment: Alignment.center, decoration: const BoxDecoration( color: Color(0x4D000000), borderRadius: BorderRadius.only(bottomLeft: Radius.circular(5), bottomRight: Radius.circular(5))), child: Text( list[index].Title!, overflow: TextOverflow.ellipsis, style: const TextStyle(color: Colors.white, fontSize: 12), ), )), ], ), ), ); }).toList(); } //尺寸 _sizeItem(List list, List listNo) { return list.map((e) { int index = list.indexOf(e); return GestureDetector( onTap: () { if (selectImage == null && copyImgUrl == "") { currentSizeIndex = index; NetworkConfig.sizeTemplateId = currentSizeIndex; setState(() {}); } }, child: Container( alignment: Alignment.center, child: Stack( alignment: Alignment.center, children: [ Image( image: selectImage == null && copyImgUrl == "" ? list[index] : currentSizeIndex == index ? list[index] : listNo[index]), currentSizeIndex == index ? const Image(fit: BoxFit.fill, image: AssetImage('assets/images/ic_size_select.png')) : Container(), ], ), ), ); }).toList(); } //主体切换 _sizeItem2(List list) { return list.map((e) { int index = list.indexOf(e); return GestureDetector( onTap: () { if (introducer != "") { //进行弹窗提示,以下为弹窗中点切换时处理 FunctionUtil.popDialog( context, GuideThemeSwitchTip( t1[index], onTap: (indexTip) { if (indexTip == 1) { mainBodyIndex = index; t2 = responseData!["body"][index]["content"]; selectList1 = {}; for (int i = 0; i < t2.length; i++) { selectList1[i] = []; } introducer = ""; setState(() {}); } }, )); } else { mainBodyIndex = index; t2 = responseData!["body"][index]["content"]; } setState(() {}); }, child: Container( alignment: Alignment.center, decoration: BoxDecoration( color: const Color(0xFFF3F3FB), //设置四周圆角 角度 borderRadius: const BorderRadius.all(Radius.circular(6.6)), //设置四周边框 border: Border.all(width: 1, color: Color(mainBodyIndex == index ? 0xFF8841FF : 0xFFFFFFFF)), ), child: Text( list[index], overflow: TextOverflow.ellipsis, style: TextStyle(color: Color(mainBodyIndex == index ? 0xFF8841FF : 0xFF999999), fontSize: 12), ), ), ); }).toList(); } _sizeItem3(int i) { return GestureDetector( onTap: () { _commentFocus.unfocus(); DialogManager() ..add(DialogBean( createDialogWidget: () => DialogUtil.createTipWidget( context, guideDialog( name: t2[i]["name"], list: t2[i]["content"], selectList: selectList1 != null && selectList1.isNotEmpty ? selectList1[i]! : [], onTap: (selectList) { selectList1[i] = selectList; introducer = ""; selectList1.forEach((key, value) { if (value != null && value.isNotEmpty) { for (var v in value) { introducer = introducer + "," + v; } } }); print(introducer); setState(() {}); }, ), "guideDialog$i", canceled: false))) ..show(context); }, child: Container( margin: const EdgeInsets.only(left: 15, right: 15, top: 13), padding: const EdgeInsets.only( left: 15, right: 15, ), height: 40, decoration: const BoxDecoration( color: Color(0xFFF3F3FB), //设置四周圆角 角度 borderRadius: BorderRadius.all(Radius.circular(6.6)), ), child: Stack( children: [ selectList1 != null && selectList1.isNotEmpty && selectList1[i] != null && selectList1[i]!.isNotEmpty ? Container( height: 40, margin: const EdgeInsets.only( right: 40, ), child: SingleChildScrollView( physics: BouncingScrollPhysics(), scrollDirection: Axis.horizontal, child: Row( children: selectList1[i]! .map((data) => Container( margin: const EdgeInsets.only( right: 10, ), child: GestureDetector( onTap: () { setState(() { selectList1[i]!.remove(data); introducer = ""; selectList1.forEach((key, value) { if (value != null && value.isNotEmpty) { for (var v in value) { introducer = introducer + v; } } }); print(introducer); setState(() {}); }); }, child: Container( padding: const EdgeInsets.only(left: 5, right: 5, top: 1, bottom: 1), decoration: BoxDecoration( //设置四周圆角 角度 borderRadius: const BorderRadius.all(Radius.circular(3.5)), //设置四周边框 border: Border.all(width: 1, color: const Color(0xFF8841FF)), ), child: Row( children: [ Text( data, overflow: TextOverflow.ellipsis, style: const TextStyle(color: Color(0xFF8841FF), fontSize: 12), ), Container( margin: const EdgeInsets.only( left: 9, ), child: Image(width: 13, height: 13, image: AssetImage('assets/images/cuo2.png'))) ], ), ), ), )) .toList()), ), ) : Align( alignment: Alignment.centerLeft, child: Text( S.of(context).What_kind, overflow: TextOverflow.ellipsis, style: TextStyle(color: Color(0xFF999999), fontSize: 12), ), ), Align( alignment: Alignment.centerRight, child: Image(width: 16, height: 16, image: AssetImage('assets/images/zhankai.png')), ) ], ), ), ); } //处理图片 _compressPictures() async { String img = ""; //1,取方向,判断原图方向横竖 // 2,同方向取宽高中最大值,匹配已选择的画面比例宽高值。反方向小值 //1:1 512*512 3:4 512*704 4:3 704*512 9:16 512*910 16:9 910*512 File file = File(selectImage!.path); File? compressedFile; ImageProperties properties = await FlutterNativeImage.getImageProperties(file.path); //判断当前方向 int isDirection = 0; //0 正方形 1 横向长方形 2 纵向长方形 if (properties.width == properties.height) { isDirection = 0; } else if (properties.width! > properties.height!) { isDirection = 1; } else if (properties.width! < properties.height!) { isDirection = 2; } //下标选择方向 if (currentSizeIndex == 0) { if (isDirection == 0) { //如果大于512的正方形直接换比例成512,否则使用原图 if (properties.width! > 512) { compressedFile = await FlutterNativeImage.compressImage(file.path, quality: 100, targetWidth: 512, targetHeight: 512); } else { compressedFile = file; } } else if (isDirection == 1) { if (properties.width! > 512) { compressedFile = await FlutterNativeImage.compressImage(file.path, quality: 100, targetWidth: 512, targetHeight: (properties.height! * 512 / properties.width!).round()); } else { compressedFile = file; } } else if (isDirection == 2) { if (properties.height! > 512) { compressedFile = await FlutterNativeImage.compressImage(file.path, quality: 100, targetWidth: (properties.width! * 512 / properties.height!).round(), targetHeight: 512); } else { compressedFile = file; } } } else if (currentSizeIndex == 1) { //下标方向为纵向 if (isDirection == 0) { //如果大于512的正方形直接换比例成512,否则使用原图 if (properties.width! > 512) { compressedFile = await FlutterNativeImage.compressImage(file.path, quality: 100, targetWidth: 512, targetHeight: 512); } else { compressedFile = file; } } else if (isDirection == 1) { //横向 if (properties.width! > 512) { compressedFile = await FlutterNativeImage.compressImage(file.path, quality: 100, targetWidth: 512, targetHeight: (properties.height! * 512 / properties.width!).round()); } else { compressedFile = file; } } else if (isDirection == 2) { //纵向 if (properties.height! > 704) { compressedFile = await FlutterNativeImage.compressImage(file.path, quality: 100, targetWidth: (properties.width! * 704 / properties.height!).round(), targetHeight: 704); } else { compressedFile = file; } } } else if (currentSizeIndex == 2) { //下标方向为横向 if (isDirection == 0) { //如果大于512的正方形直接换比例成512,否则使用原图 if (properties.height! > 512) { compressedFile = await FlutterNativeImage.compressImage(file.path, quality: 100, targetWidth: 512, targetHeight: 512); } else { compressedFile = file; } } else if (isDirection == 1) { //横向 if (properties.width! > 704) { compressedFile = await FlutterNativeImage.compressImage(file.path, quality: 100, targetWidth: 704, targetHeight: (properties.height! * 704 / properties.width!).round()); } else { compressedFile = file; } } else if (isDirection == 2) { //纵向 if (properties.height! > 512) { compressedFile = await FlutterNativeImage.compressImage(file.path, quality: 100, targetWidth: (properties.width! * 512 / properties.height!).round(), targetHeight: 512); } else { compressedFile = file; } } } else if (currentSizeIndex == 3) { //下标方向为纵向 if (isDirection == 0) { //如果大于512的正方形直接换比例成512,否则使用原图 if (properties.width! > 512) { compressedFile = await FlutterNativeImage.compressImage(file.path, quality: 100, targetWidth: 512, targetHeight: 512); } else { compressedFile = file; } } else if (isDirection == 1) { //横向 if (properties.width! > 512) { compressedFile = await FlutterNativeImage.compressImage(file.path, quality: 100, targetWidth: 512, targetHeight: (properties.height! * 512 / properties.width!).round()); } else { compressedFile = file; } } else if (isDirection == 2) { //纵向 if (properties.height! > 910) { compressedFile = await FlutterNativeImage.compressImage(file.path, quality: 100, targetWidth: (properties.width! * 910 / properties.height!).round(), targetHeight: 910); } else { compressedFile = file; } } } else if (currentSizeIndex == 4) { //下标方向为横向 if (isDirection == 0) { //如果大于512的正方形直接换比例成512,否则使用原图 if (properties.height! > 512) { compressedFile = await FlutterNativeImage.compressImage(file.path, quality: 100, targetWidth: 512, targetHeight: 512); } else { compressedFile = file; } } else if (isDirection == 1) { //横向 if (properties.width! > 910) { compressedFile = await FlutterNativeImage.compressImage(file.path, quality: 100, targetWidth: 910, targetHeight: (properties.height! * 910 / properties.width!).round()); } else { compressedFile = file; } } else if (isDirection == 2) { //纵向 if (properties.height! > 512) { compressedFile = await FlutterNativeImage.compressImage(file.path, quality: 100, targetWidth: (properties.width! * 512 / properties.height!).round(), targetHeight: 512); } else { compressedFile = file; } } } ImageProperties properties2 = await FlutterNativeImage.getImageProperties(compressedFile!.path); print("ImageProperties===" + properties2.width.toString() + "*" + properties2.height.toString()); ///判断图片大小 double size = AppUtil.getFileSizeDouble(bytes: compressedFile.lengthSync()); //取整 大于10m直接抛弃 var s = size.ceil(); if (s > 10) { EasyLoading.showToast(S.of(context).Image_too_large); } else { //取整 大于1m直接压缩,小于1m使用原图 if (s > 1) { //图片压缩,压缩算法为 (10-s)*10,m越大调整后百分比越小 int percentage = (10 - s) * 10; File compressedFile2 = await FlutterNativeImage.compressImage(compressedFile.path, quality: 80, percentage: percentage); //AppUtil.getFileSizeDouble(bytes: compressedFile2.lengthSync()); img = await AppUtil.uploadImage2(compressedFile2); } else { //不压 img = await AppUtil.uploadImage2(compressedFile); } } return img; } //弹出登录 showLoginDialog() { DialogManager() ..add(DialogBean( dialogPriority: DialogPriority.highClear, createDialogWidget: () => DialogUtil.createTipWidget( context, LoginDialog( loginDialogKey, onTap: (index) { switch (index) { case 0: if (loginDialogKey.currentState != null) { loginDialogKey.currentState!.Pop(); } FunctionUtil.bottomSheetDialog(context, const PhoneLoginDialog()); break; case 1: //谷歌登录 Map map = {"googleLogin": "googleLogin"}; invokeNativeMethod("googleLogin", map); break; } }, ), "LoginDialog", canceled: true))) ..show(context); } // 获取原生的值 invokeNativeMethod(String method, Map map) async { dynamic args; try { args = await Global.method.invokeMethod(method, map); } on PlatformException catch (e) {} } }