add open camera files and add packages

This commit is contained in:
Samsularifin01 2026-04-10 17:19:41 +07:00
parent 660e30f937
commit 7f3b71a40b
9 changed files with 317 additions and 20 deletions

View File

@ -7,7 +7,7 @@ plugins {
android {
namespace = "com.example.smart_vision_assist"
compileSdk = flutter.compileSdkVersion
compileSdk = 36
ndkVersion = flutter.ndkVersion
compileOptions {

View File

@ -1,4 +1,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<application
android:label="@string/app_name"
android:name="${applicationName}"

View File

@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-all.zip

View File

@ -18,7 +18,7 @@ pluginManagement {
plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "8.1.0" apply false
id "com.android.application" version "8.2.1" apply false
id "org.jetbrains.kotlin.android" version "1.8.22" apply false
}

View File

@ -0,0 +1,127 @@
import 'package:flutter/material.dart';
import 'package:camera/camera.dart';
class CameraScreen extends StatefulWidget {
@override
_CameraScreenState createState() => _CameraScreenState();
}
class _CameraScreenState extends State<CameraScreen> {
CameraController? controller;
List<CameraDescription>? cameras;
bool isRecording = false;
@override
void initState() {
super.initState();
initCamera();
}
Future<void> initCamera() async {
cameras = await availableCameras();
controller = CameraController(
cameras![0],
ResolutionPreset.high,
);
await controller!.initialize();
setState(() {});
}
// 🔴 START RECORD
Future<void> startRecording() async {
if (!controller!.value.isRecordingVideo) {
await controller!.startVideoRecording();
setState(() {
isRecording = true;
});
}
}
// STOP RECORD
Future<void> stopRecording() async {
if (controller!.value.isRecordingVideo) {
await controller!.stopVideoRecording();
setState(() {
isRecording = false;
});
}
}
@override
void dispose() {
controller?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
if (controller == null || !controller!.value.isInitialized) {
return Scaffold(
body: Center(child: CircularProgressIndicator()),
);
}
return Scaffold(
body: Stack(
children: [
// 📷 PREVIEW KAMERA (FULL SCREEN)
Positioned.fill(
child: CameraPreview(controller!),
),
// 🔙 TOMBOL KEMBALI (KANAN BAWAH)
Positioned(
bottom: 40,
right: 30,
child: Semantics(
label: "Kembali",
button: true,
child: FloatingActionButton(
backgroundColor: Colors.black,
onPressed: () {
Navigator.pop(context);
},
child: Icon(Icons.arrow_back),
),
),
),
// 🔘 TOMBOL RECORD (TENGAH BAWAH)
Positioned(
bottom: 30,
left: MediaQuery.of(context).size.width / 2 - 35,
child: Semantics(
label: isRecording ? "Stop rekam" : "Mulai rekam",
button: true,
child: GestureDetector(
onTap: () {
if (isRecording) {
stopRecording();
} else {
startRecording();
}
},
child: Container(
width: 70,
height: 70,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: isRecording ? Colors.red : Colors.white,
border: Border.all(color: Colors.grey, width: 4),
),
child: Icon(
isRecording ? Icons.stop : Icons.circle,
color: isRecording ? Colors.white : Colors.red,
size: 30,
),
),
),
),
),
],
),
);
}
}

View File

@ -7,6 +7,7 @@ import '../utils/colors.dart';
import 'home_screen.dart';
import 'signup_screen.dart';
import 'forgot_password_screen.dart';
import 'camera_screen.dart';
class LoginScreen extends StatelessWidget {
final TextEditingController emailController = TextEditingController();
@ -95,8 +96,13 @@ class LoginScreen extends StatelessWidget {
// 🔘 LOGIN BUTTON
CustomButton(
text: "Login",
onPressed: () => handleLogin(context),
text: "Buka Kamera",
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (_) => CameraScreen()),
);
},
),
SizedBox(height: 15),
@ -131,4 +137,4 @@ class LoginScreen extends StatelessWidget {
),
);
}
}
}

View File

@ -4,14 +4,35 @@ import '../widgets/custom_button.dart';
import '../services/tts_service.dart';
import '../utils/colors.dart';
class SignUpScreen extends StatelessWidget {
class SignUpScreen extends StatefulWidget {
const SignUpScreen({super.key});
@override
State<SignUpScreen> createState() => _SignUpScreenState();
}
class _SignUpScreenState extends State<SignUpScreen> {
final TextEditingController emailController = TextEditingController();
final TextEditingController passwordController = TextEditingController();
final TextEditingController confirmPasswordController = TextEditingController();
final TTSService tts = TTSService();
String? selectedGender;
SignUpScreen({super.key});
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
tts.speak("Halaman daftar akun");
});
}
@override
void dispose() {
emailController.dispose();
passwordController.dispose();
confirmPasswordController.dispose();
super.dispose();
}
void handleSignUp(BuildContext context) {
String email = emailController.text;
@ -28,31 +49,63 @@ class SignUpScreen extends StatelessWidget {
return;
}
if (selectedGender == null) {
tts.speak("Jenis kelamin wajib dipilih");
return;
}
tts.speak("Pendaftaran berhasil");
Navigator.pop(context);
}
Widget buildGenderOption(String gender) {
return RadioListTile<String>(
contentPadding: EdgeInsets.zero,
value: gender,
groupValue: selectedGender,
activeColor: AppColors.primary,
fillColor: MaterialStateProperty.resolveWith((states) {
if (states.contains(MaterialState.selected)) {
return AppColors.primary;
}
return AppColors.text;
}),
title: Text(
gender,
style: TextStyle(color: AppColors.text),
),
onChanged: (value) {
setState(() {
selectedGender = value;
});
if (value != null) {
tts.speak("Jenis kelamin $value dipilih");
}
},
);
}
@override
Widget build(BuildContext context) {
tts.speak("Halaman daftar akun");
return Scaffold(
backgroundColor: AppColors.background,
appBar: AppBar(
title: Text("Sign Up"),
title: const Text("Sign Up"),
),
body: Padding(
body: SingleChildScrollView(
padding: const EdgeInsets.all(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 20),
const SizedBox(height: 20),
CustomTextField(
label: "Email",
controller: emailController,
),
SizedBox(height: 20),
const SizedBox(height: 20),
CustomTextField(
label: "Password",
@ -60,7 +113,7 @@ class SignUpScreen extends StatelessWidget {
obscure: true,
),
SizedBox(height: 20),
const SizedBox(height: 20),
CustomTextField(
label: "Konfirmasi Password",
@ -68,7 +121,36 @@ class SignUpScreen extends StatelessWidget {
obscure: true,
),
SizedBox(height: 30),
const SizedBox(height: 20),
Semantics(
label: "Pilih jenis kelamin",
child: Container(
width: double.infinity,
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
decoration: BoxDecoration(
border: Border.all(color: AppColors.text),
borderRadius: BorderRadius.circular(4),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
"Jenis Kelamin",
style: TextStyle(
color: AppColors.text,
fontSize: 16,
),
),
buildGenderOption("Laki-laki"),
const Divider(color: Colors.white24, height: 1),
buildGenderOption("Perempuan"),
],
),
),
),
const SizedBox(height: 30),
CustomButton(
text: "Daftar",
@ -79,4 +161,4 @@ class SignUpScreen extends StatelessWidget {
),
);
}
}
}

View File

@ -33,6 +33,46 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.1"
camera:
dependency: "direct main"
description:
name: camera
sha256: dfa8fc5a1adaeb95e7a54d86a5bd56f4bb0e035515354c8ac6d262e35cec2ec8
url: "https://pub.dev"
source: hosted
version: "0.10.6"
camera_android:
dependency: transitive
description:
name: camera_android
sha256: f19ba60b61fdc7b79128191f3509455978eb945b98748fcf93e38921df502176
url: "https://pub.dev"
source: hosted
version: "0.10.10+5"
camera_avfoundation:
dependency: transitive
description:
name: camera_avfoundation
sha256: e4aca5bccaf897b70cac87e5fdd789393310985202442837922fd40325e2733b
url: "https://pub.dev"
source: hosted
version: "0.9.21+1"
camera_platform_interface:
dependency: transitive
description:
name: camera_platform_interface
sha256: "2f757024a48696ff4814a789b0bd90f5660c0fb25f393ab4564fb483327930e2"
url: "https://pub.dev"
source: hosted
version: "2.10.0"
camera_web:
dependency: transitive
description:
name: camera_web
sha256: "595f28c89d1fb62d77c73c633193755b781c6d2e0ebcd8dc25b763b514e6ba8f"
url: "https://pub.dev"
source: hosted
version: "0.3.5"
characters:
dependency: transitive
description:
@ -73,6 +113,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.19.0"
cross_file:
dependency: transitive
description:
name: cross_file
sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670"
url: "https://pub.dev"
source: hosted
version: "0.3.4+2"
fake_async:
dependency: transitive
description:
@ -110,6 +158,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "5.0.0"
flutter_plugin_android_lifecycle:
dependency: transitive
description:
name: flutter_plugin_android_lifecycle
sha256: "6382ce712ff69b0f719640ce957559dde459e55ecd433c767e06d139ddf16cab"
url: "https://pub.dev"
source: hosted
version: "2.0.29"
flutter_test:
dependency: "direct dev"
description: flutter
@ -216,6 +272,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "6.0.2"
plugin_platform_interface:
dependency: transitive
description:
name: plugin_platform_interface
sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
url: "https://pub.dev"
source: hosted
version: "2.1.8"
posix:
dependency: transitive
description:
@ -253,6 +317,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.2"
stream_transform:
dependency: transitive
description:
name: stream_transform
sha256: ad47125e588cfd37a9a7f86c7d6356dde8dfe89d071d293f80ca9e9273a33871
url: "https://pub.dev"
source: hosted
version: "2.1.1"
string_scanner:
dependency: transitive
description:
@ -293,6 +365,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "14.3.0"
web:
dependency: transitive
description:
name: web
sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a"
url: "https://pub.dev"
source: hosted
version: "1.1.1"
xml:
dependency: transitive
description:
@ -311,4 +391,4 @@ packages:
version: "3.1.3"
sdks:
dart: ">=3.6.1 <4.0.0"
flutter: ">=3.18.0-18.0.pre.54"
flutter: ">=3.27.0"

View File

@ -28,7 +28,7 @@ environment:
# the latest version available on pub.dev. To see which dependencies have newer
# versions available, run `flutter pub outdated`.
dependencies:
camera: ^0.10.5+5
flutter:
sdk: flutter
flutter_tts: ^3.5.2