207 lines
6.8 KiB
Dart
207 lines
6.8 KiB
Dart
import 'dart:io';
|
||
|
||
import 'package:flutter/cupertino.dart';
|
||
import 'package:flutter/material.dart';
|
||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||
import 'package:image_cropper/image_cropper.dart';
|
||
import 'package:yumi/app_localizations.dart';
|
||
import 'package:yumi/ui_kit/components/sc_tts.dart';
|
||
import 'package:yumi/shared/tools/sc_loading_manager.dart';
|
||
|
||
import 'package:yumi/app/constants/sc_global_config.dart';
|
||
import 'package:yumi/app/constants/sc_screen.dart';
|
||
import 'package:yumi/app/routes/sc_fluro_navigator.dart';
|
||
import 'package:yumi/shared/data_sources/sources/repositories/sc_general_repository_imp.dart';
|
||
|
||
typedef OnUpLoadCallBack = void Function(bool success, String url);
|
||
|
||
class CropImagePage extends StatefulWidget {
|
||
final double? aspectRatio; // 需要锁定的宽高比,例如 1 表示 1:1
|
||
final bool? backOriginalFile;
|
||
final OnUpLoadCallBack? onUpLoadCallBack;
|
||
final File image; // 原始图片文件
|
||
final bool needUpload;
|
||
|
||
const CropImagePage(this.image, {
|
||
Key? key,
|
||
this.onUpLoadCallBack,
|
||
this.aspectRatio,
|
||
this.backOriginalFile = true,
|
||
this.needUpload = true,
|
||
}) : super(key: key);
|
||
|
||
@override
|
||
_CropImageRouteState createState() => _CropImageRouteState();
|
||
}
|
||
|
||
class _CropImageRouteState extends State<CropImagePage> {
|
||
late Image imageView;
|
||
|
||
@override
|
||
void initState() {
|
||
super.initState();
|
||
imageView = Image.file(widget.image, fit: BoxFit.contain);
|
||
}
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return Scaffold(
|
||
backgroundColor: const Color(0xff333333),
|
||
body: SafeArea(
|
||
top: false,
|
||
child: Stack(
|
||
alignment: Alignment.center,
|
||
children: <Widget>[
|
||
// 预览原图
|
||
Align(
|
||
alignment: Alignment.center,
|
||
child: Container(
|
||
width: double.infinity,
|
||
height:
|
||
SCScreen.designHeight -
|
||
(kToolbarHeight * 2) -
|
||
ScreenUtil().bottomBarHeight -
|
||
ScreenUtil().statusBarHeight,
|
||
child: imageView,
|
||
),
|
||
),
|
||
|
||
// 顶部栏
|
||
Align(
|
||
alignment: Alignment.topCenter,
|
||
child: Container(
|
||
height: kToolbarHeight + ScreenUtil().statusBarHeight,
|
||
width: double.infinity,
|
||
padding: EdgeInsets.only(
|
||
left: width(15),
|
||
right: width(15),
|
||
top: ScreenUtil().statusBarHeight,
|
||
),
|
||
color: Colors.transparent,
|
||
child: Stack(
|
||
alignment: Alignment.centerLeft,
|
||
children: <Widget>[
|
||
GestureDetector(
|
||
onTap: () => SCNavigatorUtils.goBackWithParams(context, ''),
|
||
child: Padding(
|
||
padding: const EdgeInsets.all(8.0),
|
||
child: Icon(
|
||
SCGlobalConfig.lang == "ar"
|
||
? Icons.keyboard_arrow_right
|
||
: Icons.keyboard_arrow_left,
|
||
color: Colors.white,
|
||
),
|
||
),
|
||
),
|
||
Align(
|
||
alignment: Alignment.center,
|
||
child: Text(
|
||
SCAppLocalizations.of(context)!.crop,
|
||
style: TextStyle(fontSize: 18.sp, color: Colors.white),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
),
|
||
|
||
// 底部完成按钮
|
||
Align(
|
||
alignment: Alignment.bottomCenter,
|
||
child: Container(
|
||
width: double.infinity,
|
||
height: kToolbarHeight + ScreenUtil().bottomBarHeight,
|
||
color: const Color(0xff666666),
|
||
alignment: Alignment.centerRight,
|
||
child: GestureDetector(
|
||
onTap: () =>
|
||
_cropAndUpload(context, widget.image, needUpload:widget.needUpload),
|
||
child: Padding(
|
||
padding: const EdgeInsets.all(8.0).copyWith(right: 18),
|
||
child: Text(
|
||
SCAppLocalizations.of(context)!.finish,
|
||
style: TextStyle(color: Colors.white, fontSize: 16.sp),
|
||
),
|
||
),
|
||
),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
);
|
||
}
|
||
|
||
/// 使用 image_cropper 进行裁剪并上传
|
||
Future<void> _cropAndUpload(BuildContext context,
|
||
File originalFile, {
|
||
bool needUpload = true,
|
||
}) async {
|
||
// 调用系统裁剪界面
|
||
CroppedFile? cropped = await ImageCropper().cropImage(
|
||
sourcePath: originalFile.path,
|
||
aspectRatio:
|
||
widget.aspectRatio != null
|
||
? CropAspectRatio(ratioX: widget.aspectRatio!, ratioY: 1)
|
||
: null,
|
||
uiSettings: [
|
||
AndroidUiSettings(
|
||
toolbarTitle: SCAppLocalizations.of(context)!.crop,
|
||
toolbarColor: Colors.black,
|
||
toolbarWidgetColor: Colors.white,
|
||
hideBottomControls: true,
|
||
lockAspectRatio: widget.aspectRatio != null,
|
||
),
|
||
IOSUiSettings(
|
||
title: SCAppLocalizations.of(context)!.crop,
|
||
resetButtonHidden: true,
|
||
rotateButtonsHidden: true,
|
||
aspectRatioPickerButtonHidden: true,
|
||
rotateClockwiseButtonHidden: true,
|
||
aspectRatioLockEnabled: widget.aspectRatio != null,
|
||
),
|
||
],
|
||
);
|
||
|
||
// 用户可能直接点“取消”,此时 cropped 为 null
|
||
File fileToUpload;
|
||
if (cropped == null) {
|
||
if (widget.backOriginalFile ?? true) {
|
||
fileToUpload = originalFile;
|
||
} else {
|
||
widget.onUpLoadCallBack?.call(false, "");
|
||
return;
|
||
}
|
||
} else {
|
||
fileToUpload = File(cropped.path);
|
||
}
|
||
if (needUpload) {
|
||
// 弹出上传中的 loading
|
||
SCLoadingManager.show(context: context);
|
||
await upload(fileToUpload);
|
||
} else {
|
||
widget.onUpLoadCallBack?.call(true, fileToUpload.path);
|
||
SCNavigatorUtils.goBack(context);
|
||
}
|
||
}
|
||
|
||
/// 上传文件至oss
|
||
Future<void> upload(File file) async {
|
||
try {
|
||
String fileUrl = await SCGeneralRepositoryImp().upload(file);
|
||
SCLoadingManager.hide();
|
||
SCNavigatorUtils.goBack(context);
|
||
await Future.delayed(const Duration(milliseconds: 100));
|
||
widget.onUpLoadCallBack?.call(true, fileUrl);
|
||
} catch (e) {
|
||
SCTts.show("upload fail $e");
|
||
SCLoadingManager.hide();
|
||
}
|
||
}
|
||
|
||
/*
|
||
* 获取 OssToken(如果依然需要,可保留)
|
||
*/
|
||
Future<void> _getOssToken() async {}
|
||
}
|