AI_Drawing/lib/tools/create/create_page.dart
2024-06-03 15:30:15 +08:00

1546 lines
60 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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<CreatePage> createState() => _CreatePageState();
}
class _CreatePageState extends State<CreatePage> with SingleTickerProviderStateMixin, AutomaticKeepAliveClientMixin {
@override
bool get wantKeepAlive => true;
StreamSubscription? subscription;
final CreateModel _viewModel = CreateModel();
TextToImageBean? textToImageBean;
final StartModel _startModel = StartModel();
StreamSubscription<TabBarEvent>? _tabBarEvent;
StreamSubscription<CopyDrawingEvent>? _copyDrawingEvent;
StreamSubscription<RefreshUserdata>? _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<AssetImage> 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<AssetImage> 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<DrawTemplateBean> templateList = [];
//顶部banner数据
List<UserDrawBean> 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<String> t1 = [];
//选择前
List t2 = [];
//选择后
List t3 = [];
//选择的选项集合
Map<int, List<dynamic>> selectList1 = {};
//引导词
String introducer = "";
/// 动画控制器
AnimationController? _controller;
/// 非线性动画
Animation<double>? _curveAnimation;
Map<String, dynamic>? responseData;
GlobalKey<LoginDialogState> 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<void> _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<String> 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<DrawTemplateBean> 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<AssetImage> list, List<AssetImage> 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<String> 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<String, String> map = {"googleLogin": "googleLogin"};
invokeNativeMethod("googleLogin", map);
break;
}
},
),
"LoginDialog",
canceled: true)))
..show(context);
}
// 获取原生的值
invokeNativeMethod(String method, Map<String, dynamic> map) async {
dynamic args;
try {
args = await Global.method.invokeMethod(method, map);
} on PlatformException catch (e) {}
}
}