402 lines
14 KiB
Dart
402 lines
14 KiB
Dart
// ignore_for_file: avoid_print
|
|
|
|
import 'dart:convert';
|
|
import 'dart:io';
|
|
|
|
import 'dart:typed_data';
|
|
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/rendering.dart';
|
|
import 'package:flutter_colorpicker/flutter_colorpicker.dart';
|
|
// import 'package:image_gallery_saver/image_gallery_saver.dart';
|
|
import 'package:path_provider/path_provider.dart';
|
|
import 'dart:ui' as ui;
|
|
|
|
import '../controller/myCustonPainter.dart';
|
|
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
|
|
|
import 'package:intl/intl.dart' show toBeginningOfSentenceCase;
|
|
|
|
class Mewarna1Page extends StatefulWidget {
|
|
const Mewarna1Page({Key? key}) : super(key: key);
|
|
|
|
@override
|
|
State<Mewarna1Page> createState() => _Mewarna1PageState();
|
|
}
|
|
|
|
class _Mewarna1PageState extends State<Mewarna1Page> {
|
|
// List<Offset?> points = [];
|
|
List<DrawingArea?> points = [];
|
|
// List<DrawingArea?> undoPoints = [];
|
|
Color selectedColor = Colors.black.withOpacity(0.01);
|
|
double strokeWidth = 2.0;
|
|
// ui.Image? image;
|
|
|
|
late Map args;
|
|
|
|
final GlobalKey _globalKey = GlobalKey();
|
|
|
|
Uint8List? _bytes;
|
|
String _ini = 'tiada';
|
|
|
|
bool _delete = false;
|
|
|
|
// ignore: unused_element
|
|
// Future _saveNetworkImage() async {
|
|
// // String path =
|
|
// // 'https://image.shutterstock.com/image-photo/montreal-canada-july-11-2019-600w-1450023539.jpg';
|
|
// // GallerySaver.saveImage(path, albumName: "Download");
|
|
// }
|
|
|
|
Future _saveImage(Uint8List bytes) async {
|
|
final appStorage = await getApplicationDocumentsDirectory();
|
|
final file = File('${appStorage.path}/screenshot.png');
|
|
await file.writeAsBytes(bytes);
|
|
}
|
|
|
|
Future<Uint8List> _capturePng() async {
|
|
// try {
|
|
await EasyLoading.show(
|
|
status: 'loading...',
|
|
maskType: EasyLoadingMaskType.black,
|
|
);
|
|
RenderRepaintBoundary boundary =
|
|
_globalKey.currentContext!.findRenderObject()! as RenderRepaintBoundary;
|
|
ui.Image image = await boundary.toImage(pixelRatio: 3.0);
|
|
ByteData? byteData = await image.toByteData(format: ui.ImageByteFormat.png);
|
|
var pngBytes = byteData!.buffer.asUint8List();
|
|
var bs64 = base64Encode(pngBytes);
|
|
|
|
setState(() {
|
|
_bytes = base64Decode(bs64);
|
|
_ini = 'ada';
|
|
points.clear();
|
|
});
|
|
await _saveImage(base64Decode(bs64));
|
|
// await _saveNetworkImage();
|
|
|
|
// await ImageGallerySaver.saveImage(Uint8List.fromList(pngBytes),
|
|
// quality: 60, name: "hello");
|
|
|
|
await EasyLoading.dismiss();
|
|
|
|
return pngBytes;
|
|
// } catch (e) {
|
|
// print(e);
|
|
// return null;
|
|
// }
|
|
}
|
|
|
|
@override
|
|
void didChangeDependencies() {
|
|
// ignore: todo
|
|
// TODO: implement didChangeDependencies
|
|
super.didChangeDependencies();
|
|
args = ModalRoute.of(context)?.settings.arguments as Map;
|
|
// print(args);
|
|
}
|
|
|
|
void selectColor() {
|
|
showDialog(
|
|
context: context,
|
|
builder: (context) => AlertDialog(
|
|
title: const Text('Pilih warna'),
|
|
content: SingleChildScrollView(
|
|
child: BlockPicker(
|
|
pickerColor: selectedColor,
|
|
onColorChanged: (color) {
|
|
// print(colorToHex(color));
|
|
setState(() {
|
|
selectedColor = color.withOpacity(0.01);
|
|
});
|
|
},
|
|
),
|
|
),
|
|
actions: [
|
|
ElevatedButton(
|
|
child: const Text('OK'),
|
|
onPressed: () {
|
|
Navigator.of(context).pop();
|
|
},
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final double width = MediaQuery.of(context).size.width;
|
|
final double height = MediaQuery.of(context).size.height;
|
|
// final ValueNotifier<List<Offset>> points = useState([]);
|
|
|
|
return WillPopScope(
|
|
onWillPop: _onWillPopScope,
|
|
child: Scaffold(
|
|
appBar: AppBar(
|
|
title: Text(toBeginningOfSentenceCase(args['nama']?.toString()) ??
|
|
'Mewarna 1'),
|
|
actions: [
|
|
Ink(
|
|
decoration: ShapeDecoration(
|
|
color: _delete ? Colors.red : Colors.transparent,
|
|
shape: const CircleBorder(),
|
|
),
|
|
child: IconButton(
|
|
icon: const Icon(Icons.delete),
|
|
onPressed: () {
|
|
setState(() {
|
|
_delete = !_delete;
|
|
});
|
|
},
|
|
),
|
|
),
|
|
IconButton(
|
|
icon: const Icon(Icons.save_alt_outlined),
|
|
onPressed: () {},
|
|
),
|
|
],
|
|
),
|
|
body: Stack(
|
|
children: [
|
|
Container(
|
|
decoration: const BoxDecoration(
|
|
gradient: LinearGradient(
|
|
begin: Alignment.topCenter,
|
|
end: Alignment.bottomCenter,
|
|
colors: [
|
|
Color.fromRGBO(138, 35, 135, 1.0),
|
|
Color.fromRGBO(233, 64, 87, 1.0),
|
|
Color.fromRGBO(242, 113, 33, 1.0),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
Center(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.center,
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
RepaintBoundary(
|
|
key: _globalKey,
|
|
child: Container(
|
|
width: width * 0.80,
|
|
height: height * 0.70,
|
|
decoration: BoxDecoration(
|
|
borderRadius: const BorderRadius.all(
|
|
Radius.circular(20.0),
|
|
),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.black.withOpacity(0.4),
|
|
blurRadius: 5.0,
|
|
spreadRadius: 1.0,
|
|
)
|
|
],
|
|
image: _ini == 'tiada'
|
|
? DecorationImage(
|
|
image: AssetImage("assets/" +
|
|
args['kategori'] +
|
|
"/" +
|
|
args['nama'] +
|
|
".jpg"),
|
|
fit: BoxFit.fill,
|
|
)
|
|
: DecorationImage(
|
|
image: MemoryImage(_bytes!),
|
|
fit: BoxFit.cover,
|
|
),
|
|
),
|
|
child: GestureDetector(
|
|
onPanDown: (details) {
|
|
if (_delete) {
|
|
setState(() {
|
|
points.add(
|
|
DrawingArea(
|
|
point: details.localPosition,
|
|
areaPaint: Paint()
|
|
..strokeCap = StrokeCap.round
|
|
..isAntiAlias = true
|
|
..color = Colors.white.withOpacity(0.07)
|
|
..strokeWidth = strokeWidth,
|
|
),
|
|
);
|
|
});
|
|
} else {
|
|
setState(() {
|
|
points.add(
|
|
DrawingArea(
|
|
point: details.localPosition,
|
|
areaPaint: Paint()
|
|
..strokeCap = StrokeCap.round
|
|
..isAntiAlias = true
|
|
..color = selectedColor
|
|
..strokeWidth = strokeWidth,
|
|
),
|
|
);
|
|
});
|
|
}
|
|
},
|
|
onPanUpdate: (details) {
|
|
if (_delete) {
|
|
setState(() {
|
|
points.add(
|
|
DrawingArea(
|
|
point: details.localPosition,
|
|
areaPaint: Paint()
|
|
..strokeCap = StrokeCap.round
|
|
..isAntiAlias = true
|
|
..color = Colors.white.withOpacity(0.07)
|
|
..strokeWidth = strokeWidth,
|
|
),
|
|
);
|
|
});
|
|
} else {
|
|
setState(() {
|
|
points.add(
|
|
DrawingArea(
|
|
point: details.localPosition,
|
|
areaPaint: Paint()
|
|
..strokeCap = StrokeCap.round
|
|
..isAntiAlias = true
|
|
..color = selectedColor
|
|
..strokeWidth = strokeWidth,
|
|
),
|
|
);
|
|
});
|
|
}
|
|
},
|
|
onPanEnd: (details) {
|
|
setState(() {
|
|
points.add(null);
|
|
// print(details);
|
|
});
|
|
},
|
|
child: ClipRRect(
|
|
borderRadius:
|
|
const BorderRadius.all(Radius.circular(20.0)),
|
|
child: CustomPaint(
|
|
painter: MyCustomPainter(points: points),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
const SizedBox(height: 5),
|
|
Container(
|
|
width: width * 0.80,
|
|
decoration: const BoxDecoration(
|
|
borderRadius: BorderRadius.all(Radius.circular(20.0)),
|
|
color: Colors.white),
|
|
child: Row(
|
|
children: [
|
|
IconButton(
|
|
onPressed: () {
|
|
selectColor();
|
|
},
|
|
icon: Icon(
|
|
Icons.color_lens,
|
|
color: selectedColor.withOpacity(1),
|
|
),
|
|
),
|
|
Expanded(
|
|
child: Slider(
|
|
min: 1.0,
|
|
max: 20.0,
|
|
activeColor: selectedColor.withOpacity(1),
|
|
value: strokeWidth,
|
|
onChanged: (value) {
|
|
setState(() {
|
|
strokeWidth = value;
|
|
});
|
|
},
|
|
),
|
|
),
|
|
GestureDetector(
|
|
onTap: () {
|
|
setState(() {
|
|
if (points.isNotEmpty) {
|
|
points.removeLast();
|
|
}
|
|
});
|
|
},
|
|
onLongPress: () {
|
|
//remove the 10 last points
|
|
setState(() {
|
|
if (points.isNotEmpty) {
|
|
if (points.length > 200) {
|
|
points.removeRange(
|
|
points.length - 200, points.length);
|
|
} else {
|
|
points.clear();
|
|
}
|
|
}
|
|
});
|
|
},
|
|
child: const Icon(
|
|
Icons.layers_clear,
|
|
color: Colors.black,
|
|
),
|
|
),
|
|
IconButton(
|
|
onPressed: () async {
|
|
_capturePng();
|
|
print("sini untuk simpan");
|
|
// String path =
|
|
// 'https://image.shutterstock.com/image-photo/montreal-canada-july-11-2019-600w-1450023539.jpg';
|
|
// await GallerySaver.saveImage(path);
|
|
},
|
|
icon: const Icon(Icons.save_alt_outlined),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
)
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
// Future loadImage(String path) async {
|
|
// final data = await rootBundle.load(path);
|
|
// final bytes = data.buffer.asUint8List();
|
|
// final image = await decodeImageFromList(bytes);
|
|
// setState(() {
|
|
// this.image = image;
|
|
// });
|
|
// }
|
|
|
|
Future<bool> _onWillPopScope() async {
|
|
// return false;
|
|
return await showDialog<bool>(
|
|
context: context,
|
|
builder: (context) => AlertDialog(
|
|
title: const Text('Berhenti Mewarna'),
|
|
content: const Text('Apakah anda yakin ingin berhenti mewarna?'),
|
|
actions: [
|
|
ElevatedButton(
|
|
child: const Text('Tidak'),
|
|
onPressed: () {
|
|
Navigator.of(context).pop(false);
|
|
},
|
|
),
|
|
ElevatedButton(
|
|
child: const Text('Ya'),
|
|
onPressed: () {
|
|
Navigator.of(context).pop(true);
|
|
},
|
|
style: ElevatedButton.styleFrom(
|
|
primary: Colors.red,
|
|
// backgroundColor: Colors.red,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
) ??
|
|
false;
|
|
}
|
|
}
|