first commit
This commit is contained in:
52
.gitignore
vendored
Normal file
52
.gitignore
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
# Miscellaneous
|
||||
*.class
|
||||
*.log
|
||||
*.pyc
|
||||
*.swp
|
||||
.DS_Store
|
||||
.atom/
|
||||
.buildlog/
|
||||
.history
|
||||
.svn/
|
||||
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
.idea/
|
||||
|
||||
# The .vscode folder contains launch configuration and tasks you configure in
|
||||
# VS Code which you may wish to be included in version control, so this line
|
||||
# is commented out by default.
|
||||
#.vscode/
|
||||
|
||||
# Flutter/Dart/Pub related
|
||||
**/doc/api/
|
||||
**/ios/Flutter/.last_build_id
|
||||
.dart_tool/
|
||||
.flutter-plugins
|
||||
.flutter-plugins-dependencies
|
||||
.packages
|
||||
.pub-cache/
|
||||
.pub/
|
||||
/build/
|
||||
/ios/
|
||||
/macos/
|
||||
/web/
|
||||
/windows/
|
||||
/android/
|
||||
/linux/
|
||||
|
||||
# Web related
|
||||
lib/generated_plugin_registrant.dart
|
||||
|
||||
# Symbolication related
|
||||
app.*.symbols
|
||||
|
||||
# Obfuscation related
|
||||
app.*.map.json
|
||||
|
||||
# Android Studio will place build artifacts here
|
||||
/android/app/debug
|
||||
/android/app/profile
|
||||
/android/app/release
|
||||
10
.metadata
Normal file
10
.metadata
Normal file
@ -0,0 +1,10 @@
|
||||
# This file tracks properties of this Flutter project.
|
||||
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||
#
|
||||
# This file should be version controlled and should not be manually edited.
|
||||
|
||||
version:
|
||||
revision: fdd0af78bbda27e1084ec859b27765d927cbe27e
|
||||
channel: beta
|
||||
|
||||
project_type: app
|
||||
3
README.md
Normal file
3
README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# Mari Mewarna
|
||||
#### Sebuah aplikasi mari mewarna untuk anak-anak TK dan SD yang meliputi 4 kategori yaitu buah-buahan, sayur-sayuran, binatang dan kenderaan.
|
||||
|
||||
29
analysis_options.yaml
Normal file
29
analysis_options.yaml
Normal file
@ -0,0 +1,29 @@
|
||||
# This file configures the analyzer, which statically analyzes Dart code to
|
||||
# check for errors, warnings, and lints.
|
||||
#
|
||||
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
|
||||
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
|
||||
# invoked from the command line by running `flutter analyze`.
|
||||
|
||||
# The following line activates a set of recommended lints for Flutter apps,
|
||||
# packages, and plugins designed to encourage good coding practices.
|
||||
include: package:flutter_lints/flutter.yaml
|
||||
|
||||
linter:
|
||||
# The lint rules applied to this project can be customized in the
|
||||
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
|
||||
# included above or to enable additional rules. A list of all available lints
|
||||
# and their documentation is published at
|
||||
# https://dart-lang.github.io/linter/lints/index.html.
|
||||
#
|
||||
# Instead of disabling a lint rule for the entire project in the
|
||||
# section below, it can also be suppressed for a single line of code
|
||||
# or a specific dart file by using the `// ignore: name_of_lint` and
|
||||
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
|
||||
# producing the lint.
|
||||
rules:
|
||||
# avoid_print: false # Uncomment to disable the `avoid_print` rule
|
||||
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
|
||||
|
||||
# Additional information about this file can be found at
|
||||
# https://dart.dev/guides/language/analysis-options
|
||||
BIN
assets/bg.jpg
Normal file
BIN
assets/bg.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 537 KiB |
BIN
assets/hewan/burung.jpg
Normal file
BIN
assets/hewan/burung.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 42 KiB |
BIN
assets/hewan/gajah.jpg
Normal file
BIN
assets/hewan/gajah.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 47 KiB |
BIN
assets/hewan/kelinci.jpg
Normal file
BIN
assets/hewan/kelinci.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 94 KiB |
BIN
assets/hewan/monyet.jpg
Normal file
BIN
assets/hewan/monyet.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 95 KiB |
BIN
assets/hewan/singa.jpg
Normal file
BIN
assets/hewan/singa.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 81 KiB |
55
lib/controller/myCustonPainter.dart
Normal file
55
lib/controller/myCustonPainter.dart
Normal file
@ -0,0 +1,55 @@
|
||||
// ignore_for_file: file_names
|
||||
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class MyCustomPainter extends CustomPainter {
|
||||
// List<Offset?> points;
|
||||
List<DrawingArea?> points;
|
||||
// final ui.Image image;
|
||||
|
||||
// MyCustomPainter({required this.points, required this.image});
|
||||
MyCustomPainter({required this.points});
|
||||
// MyCustomPainter(this.image, this.points);
|
||||
// MyCustomPainter(this.points);
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
// Paint background = Paint()..color = Colors.white;
|
||||
// Rect rect = Rect.fromLTWH(0, 0, size.width, size.height);
|
||||
// canvas.drawRect(rect, background);
|
||||
// final paintnya = Paint();
|
||||
// canvas.drawImage(image, Offset.zero, paintnya);
|
||||
|
||||
// print(points);
|
||||
// Paint paint = Paint();
|
||||
// paint.color = const Color.fromRGBO(0, 255, 255, 0.08);
|
||||
// paint.strokeWidth = 5.0;
|
||||
// paint.isAntiAlias = true;
|
||||
// paint.strokeCap = StrokeCap.round;
|
||||
|
||||
for (int i = 0; i < points.length - 1; i++) {
|
||||
if (points[i] != null && points[i + 1] != null) {
|
||||
Paint paint = points[i]!.areaPaint!;
|
||||
|
||||
canvas.drawLine(points[i]!.point!, points[i + 1]!.point!, paint);
|
||||
} else if (points[i] != null && points[i + 1] == null) {
|
||||
Paint paint = points[i]!.areaPaint!;
|
||||
canvas.drawPoints(PointMode.points, [points[i]!.point!], paint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(CustomPainter oldDelegate) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class DrawingArea {
|
||||
Offset? point;
|
||||
Paint? areaPaint;
|
||||
|
||||
DrawingArea({this.point, this.areaPaint});
|
||||
}
|
||||
60
lib/homepage.dart
Normal file
60
lib/homepage.dart
Normal file
@ -0,0 +1,60 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
|
||||
class HomePage extends HookWidget {
|
||||
const HomePage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Mari Mewarna'),
|
||||
),
|
||||
body: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
Image.asset(
|
||||
"assets/bg.jpg",
|
||||
fit: BoxFit.cover,
|
||||
color: Colors.black.withOpacity(0.2),
|
||||
colorBlendMode: BlendMode.darken,
|
||||
),
|
||||
Center(
|
||||
// add two buttons, one named "Pilih Kategori" , the other named "Tentang"
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
//make the button same width
|
||||
SizedBox(
|
||||
// width is half of the screen width
|
||||
width: MediaQuery.of(context).size.width / 3,
|
||||
child: ElevatedButton(
|
||||
child: const Text('Kategori'),
|
||||
onPressed: () {
|
||||
Navigator.pushNamed(context, '/pilih_kategori');
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 15,
|
||||
),
|
||||
SizedBox(
|
||||
width: MediaQuery.of(context).size.width / 3,
|
||||
child: ElevatedButton(
|
||||
child: const Text('Tentang'),
|
||||
onPressed: () {
|
||||
Navigator.pushNamed(context, '/tentang');
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
// child: Text('Home Page'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
37
lib/main.dart
Normal file
37
lib/main.dart
Normal file
@ -0,0 +1,37 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mewarna/homepage.dart';
|
||||
import 'package:mewarna/pages/mewarna.dart';
|
||||
import 'package:mewarna/pages/pilihKategori.dart';
|
||||
import 'package:mewarna/pages/tentang.dart';
|
||||
|
||||
import 'pages/binatang.dart';
|
||||
import 'pages/mewarna1.dart';
|
||||
|
||||
void main() {
|
||||
runApp(const MyApp());
|
||||
}
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
const MyApp({Key? key}) : super(key: key);
|
||||
|
||||
// This widget is the root of your application.
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
//add the routes
|
||||
routes: {
|
||||
'/': (context) => const HomePage(),
|
||||
'/pilih_kategori': (context) => const PilihKategori(),
|
||||
'/tentang': (context) => const Tentang(),
|
||||
'/binatang': (context) => const BinatangPage(),
|
||||
'/mewarna': (context) => const MewarnaPage(),
|
||||
'/mewarna1': (context) => const Mewarna1Page(),
|
||||
},
|
||||
initialRoute: '/',
|
||||
title: 'Flutter Demo',
|
||||
theme: ThemeData(
|
||||
primarySwatch: Colors.blue,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
103
lib/pages/binatang.dart
Normal file
103
lib/pages/binatang.dart
Normal file
@ -0,0 +1,103 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
|
||||
class BinatangPage extends HookWidget {
|
||||
const BinatangPage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Binatang'),
|
||||
),
|
||||
body: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
Image.asset(
|
||||
"assets/bg.jpg",
|
||||
fit: BoxFit.cover,
|
||||
color: Colors.black.withOpacity(0.2),
|
||||
colorBlendMode: BlendMode.darken,
|
||||
),
|
||||
Center(
|
||||
// add two buttons, one named "Pilih Kategori" , the other named "Tentang"
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
//make the button same width
|
||||
SizedBox(
|
||||
// width is half of the screen width
|
||||
width: MediaQuery.of(context).size.width / 3,
|
||||
child: ElevatedButton(
|
||||
child: const Text('Burung'),
|
||||
onPressed: () {
|
||||
Navigator.pushNamed(context, '/mewarna1',
|
||||
arguments: {'kategori': 'hewan', 'nama': 'burung'});
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 15,
|
||||
),
|
||||
SizedBox(
|
||||
width: MediaQuery.of(context).size.width / 3,
|
||||
child: ElevatedButton(
|
||||
child: const Text('Kelinci'),
|
||||
onPressed: () {
|
||||
Navigator.pushNamed(context, '/mewarna1', arguments: {
|
||||
'kategori': 'hewan',
|
||||
'nama': 'kelinci'
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 15,
|
||||
),
|
||||
SizedBox(
|
||||
width: MediaQuery.of(context).size.width / 3,
|
||||
child: ElevatedButton(
|
||||
child: const Text('Gajah'),
|
||||
onPressed: () {
|
||||
Navigator.pushNamed(context, '/mewarna1',
|
||||
arguments: {'kategori': 'hewan', 'nama': 'gajah'});
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 15,
|
||||
),
|
||||
SizedBox(
|
||||
width: MediaQuery.of(context).size.width / 3,
|
||||
child: ElevatedButton(
|
||||
child: const Text('Monyet'),
|
||||
onPressed: () {
|
||||
Navigator.pushNamed(context, '/mewarna1',
|
||||
arguments: {'kategori': 'hewan', 'nama': 'monyet'});
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 15,
|
||||
),
|
||||
SizedBox(
|
||||
width: MediaQuery.of(context).size.width / 3,
|
||||
child: ElevatedButton(
|
||||
child: const Text('Singa'),
|
||||
onPressed: () {
|
||||
Navigator.pushNamed(context, '/mewarna1',
|
||||
arguments: {'kategori': 'hewan', 'nama': 'singa'});
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
// child: Text('Home Page'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
126
lib/pages/mewarna.dart
Normal file
126
lib/pages/mewarna.dart
Normal file
@ -0,0 +1,126 @@
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
|
||||
class MewarnaPage extends HookWidget {
|
||||
const MewarnaPage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final double width = MediaQuery.of(context).size.width;
|
||||
final double height = MediaQuery.of(context).size.height;
|
||||
final points = useState<List<Offset?>>([]);
|
||||
|
||||
return Scaffold(
|
||||
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: [
|
||||
Container(
|
||||
width: width * 0.80,
|
||||
height: height * 0.80,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(20.0)),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.4),
|
||||
blurRadius: 5.0,
|
||||
spreadRadius: 1.0,
|
||||
)
|
||||
],
|
||||
),
|
||||
child: GestureDetector(
|
||||
onPanDown: (details) {
|
||||
points.value.add(details.globalPosition);
|
||||
// print(points);
|
||||
},
|
||||
onPanUpdate: (details) {
|
||||
points.value.add(details.globalPosition);
|
||||
},
|
||||
onPanEnd: (details) {
|
||||
points.value.add(null);
|
||||
// print(details);
|
||||
},
|
||||
child: ClipRRect(
|
||||
borderRadius:
|
||||
const BorderRadius.all(Radius.circular(20.0)),
|
||||
child: CustomPaint(
|
||||
painter: MyCustomPainter(points: points.value),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Container(
|
||||
width: width * 0.80,
|
||||
decoration: const BoxDecoration(
|
||||
borderRadius: BorderRadius.all(Radius.circular(20.0)),
|
||||
color: Colors.white),
|
||||
child: Row(
|
||||
children: [
|
||||
IconButton(
|
||||
onPressed: () {}, icon: const Icon(Icons.color_lens)),
|
||||
IconButton(
|
||||
onPressed: () {},
|
||||
icon: const Icon(Icons.layers_clear)),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class MyCustomPainter extends CustomPainter {
|
||||
List<Offset?> points;
|
||||
|
||||
MyCustomPainter({required this.points});
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
Paint background = Paint()..color = Colors.white;
|
||||
Rect rect = Rect.fromLTWH(0, 0, size.width, size.height);
|
||||
canvas.drawRect(rect, background);
|
||||
|
||||
// print(points);
|
||||
Paint paint = Paint();
|
||||
paint.color = Colors.transparent;
|
||||
paint.strokeWidth = 5.0;
|
||||
paint.isAntiAlias = true;
|
||||
paint.strokeCap = StrokeCap.round;
|
||||
|
||||
for (int i = 0; i < points.length - 1; i++) {
|
||||
if (points[i] != null && points[i + 1] != null) {
|
||||
canvas.drawLine(points[i]!, points[i + 1]!, paint);
|
||||
} else if (points[i] != null && points[i + 1] == null) {
|
||||
canvas.drawPoints(PointMode.points, [points[i]!], paint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(CustomPainter oldDelegate) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
296
lib/pages/mewarna1.dart
Normal file
296
lib/pages/mewarna1.dart
Normal file
@ -0,0 +1,296 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_colorpicker/flutter_colorpicker.dart';
|
||||
// import 'package:flutter/services.dart';
|
||||
// import 'dart:ui' as ui;
|
||||
|
||||
import '../controller/myCustonPainter.dart';
|
||||
// import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
|
||||
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.08);
|
||||
double strokeWidth = 2.0;
|
||||
// ui.Image? image;
|
||||
|
||||
late Map args;
|
||||
|
||||
// @override
|
||||
// void initState() {
|
||||
// // TODO: implement initState
|
||||
// super.initState();
|
||||
// // selectedColor = Colors.black;
|
||||
// // strokeWidth = 2.0;
|
||||
// // loadImage('assets/hewan/singa.jpg');
|
||||
// args = ModalRoute.of(context)?.settings.arguments as Map;
|
||||
// print(args);
|
||||
// }
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
// 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.08);
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
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(
|
||||
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: [
|
||||
Container(
|
||||
width: width * 0.80,
|
||||
height: height * 0.80,
|
||||
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: DecorationImage(
|
||||
image: AssetImage("assets/" +
|
||||
args['kategori'] +
|
||||
"/" +
|
||||
args['nama'] +
|
||||
".jpg"),
|
||||
fit: BoxFit.fill,
|
||||
),
|
||||
),
|
||||
child: GestureDetector(
|
||||
onPanDown: (details) {
|
||||
setState(() {
|
||||
// points.add(details.localPosition);
|
||||
// print(points);
|
||||
points.add(
|
||||
DrawingArea(
|
||||
point: details.localPosition,
|
||||
areaPaint: Paint()
|
||||
..strokeCap = StrokeCap.round
|
||||
..isAntiAlias = true
|
||||
..color = selectedColor
|
||||
..strokeWidth = strokeWidth,
|
||||
),
|
||||
);
|
||||
});
|
||||
},
|
||||
onPanUpdate: (details) {
|
||||
setState(() {
|
||||
// points.add(details.localPosition);
|
||||
// print(points);
|
||||
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: 10,
|
||||
),
|
||||
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: 7.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 > 20) {
|
||||
points.removeRange(
|
||||
points.length - 20, points.length);
|
||||
} else {
|
||||
points.clear();
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
child: Icon(
|
||||
Icons.layers_clear,
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
// IconButton(
|
||||
// onPressed: () {
|
||||
// // points.clear();
|
||||
// // points.removeLast();
|
||||
|
||||
// // search for undoPoints on points and remove it
|
||||
// setState(() {
|
||||
// // points.removeLast();
|
||||
// if (points.isNotEmpty) {
|
||||
// points.removeLast();
|
||||
// }
|
||||
// });
|
||||
// },
|
||||
// icon: Icon(Icons.layers_clear),
|
||||
// ),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
80
lib/pages/pilihKategori.dart
Normal file
80
lib/pages/pilihKategori.dart
Normal file
@ -0,0 +1,80 @@
|
||||
// ignore_for_file: file_names
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
|
||||
class PilihKategori extends HookWidget {
|
||||
const PilihKategori({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Pilih Kategori'),
|
||||
),
|
||||
body: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
Image.asset(
|
||||
"assets/bg.jpg",
|
||||
fit: BoxFit.cover,
|
||||
color: Colors.black.withOpacity(0.2),
|
||||
colorBlendMode: BlendMode.darken,
|
||||
),
|
||||
Center(
|
||||
// add two buttons, one named "Pilih Kategori" , the other named "Tentang"
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
//make the button same width
|
||||
SizedBox(
|
||||
// width is half of the screen width
|
||||
width: MediaQuery.of(context).size.width / 3,
|
||||
child: ElevatedButton(
|
||||
child: const Text('Binatang'),
|
||||
onPressed: () {
|
||||
Navigator.pushNamed(context, '/binatang');
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 15,
|
||||
),
|
||||
SizedBox(
|
||||
width: MediaQuery.of(context).size.width / 3,
|
||||
child: ElevatedButton(
|
||||
child: const Text('Kendaraan'),
|
||||
onPressed: () {},
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 15,
|
||||
),
|
||||
SizedBox(
|
||||
width: MediaQuery.of(context).size.width / 3,
|
||||
child: ElevatedButton(
|
||||
child: const Text('Sayur-Sayuran'),
|
||||
onPressed: () {},
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 15,
|
||||
),
|
||||
SizedBox(
|
||||
width: MediaQuery.of(context).size.width / 3,
|
||||
child: ElevatedButton(
|
||||
child: const Text('Buah-Buahan'),
|
||||
onPressed: () {},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
// child: Text('Home Page'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
18
lib/pages/tentang.dart
Normal file
18
lib/pages/tentang.dart
Normal file
@ -0,0 +1,18 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
|
||||
class Tentang extends HookWidget {
|
||||
const Tentang({ Key? key }) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title : const Text('Tentang'),
|
||||
),
|
||||
body: const Center(
|
||||
child: Text('Tentang'),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
189
pubspec.lock
Normal file
189
pubspec.lock
Normal file
@ -0,0 +1,189 @@
|
||||
# Generated by pub
|
||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||
packages:
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: async
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.8.2"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: boolean_selector
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
characters:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: characters
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
charcode:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: charcode
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.1"
|
||||
clock:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: clock
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: collection
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.15.0"
|
||||
cupertino_icons:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: cupertino_icons
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fake_async
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_colorpicker:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_colorpicker
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.3"
|
||||
flutter_hooks:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_hooks
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.18.2+1"
|
||||
flutter_lints:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: flutter_lints
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
flutter_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
lints:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: lints
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: matcher
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.12.11"
|
||||
material_color_utilities:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: material_color_utilities
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.1.3"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.7.0"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.8.0"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.99"
|
||||
source_span:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_span
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.8.1"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stack_trace
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.10.0"
|
||||
stream_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_channel
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
string_scanner:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: string_scanner
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: term_glyph
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
test_api:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.4.8"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: typed_data
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_math
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
sdks:
|
||||
dart: ">=2.16.0-134.5.beta <3.0.0"
|
||||
flutter: ">=1.20.0"
|
||||
93
pubspec.yaml
Normal file
93
pubspec.yaml
Normal file
@ -0,0 +1,93 @@
|
||||
name: mewarna
|
||||
description: A new Flutter project.
|
||||
|
||||
# The following line prevents the package from being accidentally published to
|
||||
# pub.dev using `flutter pub publish`. This is preferred for private packages.
|
||||
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||
|
||||
# The following defines the version and build number for your application.
|
||||
# A version number is three numbers separated by dots, like 1.2.43
|
||||
# followed by an optional build number separated by a +.
|
||||
# Both the version and the builder number may be overridden in flutter
|
||||
# build by specifying --build-name and --build-number, respectively.
|
||||
# In Android, build-name is used as versionName while build-number used as versionCode.
|
||||
# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
|
||||
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
||||
# Read more about iOS versioning at
|
||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||
version: 1.0.0+1
|
||||
|
||||
environment:
|
||||
sdk: ">=2.16.0-134.5.beta <3.0.0"
|
||||
|
||||
# Dependencies specify other packages that your package needs in order to work.
|
||||
# To automatically upgrade your package dependencies to the latest versions
|
||||
# consider running `flutter pub upgrade --major-versions`. Alternatively,
|
||||
# dependencies can be manually updated by changing the version numbers below to
|
||||
# the latest version available on pub.dev. To see which dependencies have newer
|
||||
# versions available, run `flutter pub outdated`.
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
|
||||
|
||||
# The following adds the Cupertino Icons font to your application.
|
||||
# Use with the CupertinoIcons class for iOS style icons.
|
||||
cupertino_icons: ^1.0.2
|
||||
flutter_hooks: ^0.18.2+1
|
||||
flutter_colorpicker: ^1.0.3
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
|
||||
# The "flutter_lints" package below contains a set of recommended lints to
|
||||
# encourage good coding practices. The lint set provided by the package is
|
||||
# activated in the `analysis_options.yaml` file located at the root of your
|
||||
# package. See that file for information about deactivating specific lint
|
||||
# rules and activating additional ones.
|
||||
flutter_lints: ^1.0.0
|
||||
|
||||
# For information on the generic Dart part of this file, see the
|
||||
# following page: https://dart.dev/tools/pub/pubspec
|
||||
|
||||
# The following section is specific to Flutter.
|
||||
flutter:
|
||||
|
||||
# The following line ensures that the Material Icons font is
|
||||
# included with your application, so that you can use the icons in
|
||||
# the material Icons class.
|
||||
uses-material-design: true
|
||||
|
||||
# To add assets to your application, add an assets section, like this:
|
||||
assets:
|
||||
- assets/
|
||||
- assets/hewan/
|
||||
# - images/a_dot_burr.jpeg
|
||||
# - images/a_dot_ham.jpeg
|
||||
|
||||
# An image asset can refer to one or more resolution-specific "variants", see
|
||||
# https://flutter.dev/assets-and-images/#resolution-aware.
|
||||
|
||||
# For details regarding adding assets from package dependencies, see
|
||||
# https://flutter.dev/assets-and-images/#from-packages
|
||||
|
||||
# To add custom fonts to your application, add a fonts section here,
|
||||
# in this "flutter" section. Each entry in this list should have a
|
||||
# "family" key with the font family name, and a "fonts" key with a
|
||||
# list giving the asset and other descriptors for the font. For
|
||||
# example:
|
||||
# fonts:
|
||||
# - family: Schyler
|
||||
# fonts:
|
||||
# - asset: fonts/Schyler-Regular.ttf
|
||||
# - asset: fonts/Schyler-Italic.ttf
|
||||
# style: italic
|
||||
# - family: Trajan Pro
|
||||
# fonts:
|
||||
# - asset: fonts/TrajanPro.ttf
|
||||
# - asset: fonts/TrajanPro_Bold.ttf
|
||||
# weight: 700
|
||||
#
|
||||
# For details regarding fonts from package dependencies,
|
||||
# see https://flutter.dev/custom-fonts/#from-packages
|
||||
30
test/widget_test.dart
Normal file
30
test/widget_test.dart
Normal file
@ -0,0 +1,30 @@
|
||||
// This is a basic Flutter widget test.
|
||||
//
|
||||
// To perform an interaction with a widget in your test, use the WidgetTester
|
||||
// utility that Flutter provides. For example, you can send tap and scroll
|
||||
// gestures. You can also use WidgetTester to find child widgets in the widget
|
||||
// tree, read text, and verify that the values of widget properties are correct.
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import 'package:mewarna/main.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
|
||||
// Build our app and trigger a frame.
|
||||
await tester.pumpWidget(const MyApp());
|
||||
|
||||
// Verify that our counter starts at 0.
|
||||
expect(find.text('0'), findsOneWidget);
|
||||
expect(find.text('1'), findsNothing);
|
||||
|
||||
// Tap the '+' icon and trigger a frame.
|
||||
await tester.tap(find.byIcon(Icons.add));
|
||||
await tester.pump();
|
||||
|
||||
// Verify that our counter has incremented.
|
||||
expect(find.text('0'), findsNothing);
|
||||
expect(find.text('1'), findsOneWidget);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user