١١١١١
This commit is contained in:
260
lib/screens/face_screen.dart
Normal file
260
lib/screens/face_screen.dart
Normal file
@@ -0,0 +1,260 @@
|
||||
import 'package:camera/camera.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class OvalCameraCapturePage extends StatefulWidget {
|
||||
const OvalCameraCapturePage({super.key});
|
||||
|
||||
@override
|
||||
State<OvalCameraCapturePage> createState() => _OvalCameraCapturePageState();
|
||||
}
|
||||
|
||||
class _OvalCameraCapturePageState extends State<OvalCameraCapturePage> {
|
||||
CameraController? _cameraController;
|
||||
bool _isCameraInitialized = false;
|
||||
String? _errorMessage;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_initializeCamera();
|
||||
}
|
||||
|
||||
Future<void> _initializeCamera() async {
|
||||
try {
|
||||
// Dispose existing controller if any
|
||||
await _cameraController?.dispose();
|
||||
_cameraController = null;
|
||||
|
||||
// Get available cameras
|
||||
final cameras = await availableCameras();
|
||||
|
||||
// Check if cameras list is available
|
||||
if (cameras.isEmpty) {
|
||||
setState(() {
|
||||
_errorMessage = "لا توجد كاميرات متاحة";
|
||||
_isCameraInitialized = false;
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to find front camera, fallback to first available camera
|
||||
CameraDescription? selectedCamera;
|
||||
try {
|
||||
selectedCamera = cameras.firstWhere(
|
||||
(cam) => cam.lensDirection == CameraLensDirection.front,
|
||||
);
|
||||
} catch (e) {
|
||||
// If no front camera found, use the first available camera
|
||||
if (cameras.isNotEmpty) {
|
||||
selectedCamera = cameras.first;
|
||||
} else {
|
||||
setState(() {
|
||||
_errorMessage = "لا توجد كاميرات متاحة";
|
||||
_isCameraInitialized = false;
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_cameraController = CameraController(
|
||||
selectedCamera,
|
||||
ResolutionPreset.medium,
|
||||
enableAudio: false,
|
||||
imageFormatGroup: ImageFormatGroup.jpeg,
|
||||
);
|
||||
|
||||
await _cameraController!.initialize();
|
||||
|
||||
if (!mounted) return;
|
||||
|
||||
setState(() {
|
||||
_isCameraInitialized = true;
|
||||
_errorMessage = null;
|
||||
});
|
||||
} catch (e) {
|
||||
if (!mounted) return;
|
||||
|
||||
setState(() {
|
||||
_errorMessage = "خطأ في تهيئة الكاميرا: $e";
|
||||
_isCameraInitialized = false;
|
||||
});
|
||||
print("Error initializing camera: $e");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_cameraController?.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: Color(0xff000000),
|
||||
|
||||
body: _errorMessage != null
|
||||
? Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(20.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.camera_alt_outlined,
|
||||
size: 64,
|
||||
color: Colors.white70,
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
Text(
|
||||
_errorMessage!,
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
SizedBox(height: 24),
|
||||
ElevatedButton(
|
||||
onPressed: _initializeCamera,
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Color(0xffE8001A),
|
||||
foregroundColor: Colors.white,
|
||||
padding: EdgeInsets.symmetric(horizontal: 32, vertical: 12),
|
||||
),
|
||||
child: Text("إعادة المحاولة"),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
: _isCameraInitialized && _cameraController != null
|
||||
? Stack(
|
||||
children: [
|
||||
SizedBox(height: MediaQuery.of(context).size.height ),
|
||||
// Camera Preview
|
||||
Positioned(
|
||||
child: Center(child: CameraPreview(_cameraController!)),
|
||||
),
|
||||
// Oval overlay with dimmed background
|
||||
Positioned.fill(
|
||||
child: CustomPaint(
|
||||
painter: _OvalOverlayPainter(),
|
||||
),
|
||||
),
|
||||
|
||||
|
||||
// // Capture button
|
||||
// Positioned(
|
||||
// bottom: 60,
|
||||
// left: 0,
|
||||
// right: 0,
|
||||
// child: Center(
|
||||
// child: GestureDetector(
|
||||
// onTap: (){},
|
||||
// child: Container(
|
||||
// width: 72,
|
||||
// height: 72,
|
||||
// decoration: BoxDecoration(
|
||||
// shape: BoxShape.circle,
|
||||
// color: Colors.white,
|
||||
// boxShadow: [
|
||||
// BoxShadow(
|
||||
// color: Colors.black26,
|
||||
// blurRadius: 8,
|
||||
// offset: Offset(0, 4),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// child: Icon(Icons.camera_alt, color: Color(0xffE8001A), size: 36),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
],
|
||||
)
|
||||
: Center(child: CircularProgressIndicator(color: Color(0xffE8001A))),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _OvalOverlayPainter extends CustomPainter {
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
final width = size.width * 0.75;
|
||||
final height = size.height * 0.4;
|
||||
final center = Offset(size.width / 2, size.height / 2);
|
||||
final ovalRect = Rect.fromCenter(
|
||||
center: center,
|
||||
width: width,
|
||||
height: height,
|
||||
);
|
||||
|
||||
// Create a path for the whole screen
|
||||
final screenPath = Path()..addRect(Rect.fromLTWH(0, 0, size.width, size.height));
|
||||
// Create a path for the oval
|
||||
final ovalPath = Path()..addOval(ovalRect);
|
||||
// Subtract the oval from the screen path
|
||||
final overlayPath = Path.combine(PathOperation.difference, screenPath, ovalPath);
|
||||
|
||||
// Draw the dimmed area outside the oval with gradient
|
||||
final gradient = LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: [
|
||||
Color.fromARGB(255, 41, 41, 41), // top dark gray
|
||||
Color.fromARGB(255, 0, 20, 15), // bottom deep green
|
||||
],
|
||||
);
|
||||
final paint = Paint()
|
||||
..shader = gradient.createShader(
|
||||
Rect.fromLTWH(0, 0, size.width, size.height),
|
||||
)
|
||||
..style = PaintingStyle.fill;
|
||||
canvas.drawPath(overlayPath, paint);
|
||||
|
||||
// Draw glowing circles effect (like AppBackground) - drawn after overlay
|
||||
// Top circle - positioned similar to AppBackground (top: -250, left: 100, right: -200)
|
||||
final topCircleCenter = Offset(size.width * 0.3, -250);
|
||||
final topCircleRadius = 150.0;
|
||||
// Draw multiple circles with different opacities for spread effect (spreadRadius: 160)
|
||||
for (int i = 0; i < 5; i++) {
|
||||
final spreadPaint = Paint()
|
||||
..color = Color.fromARGB(69 ~/ (i + 1), 62, 254, 190)
|
||||
..maskFilter = MaskFilter.blur(BlurStyle.normal, 140 - (i * 20));
|
||||
canvas.drawCircle(
|
||||
topCircleCenter,
|
||||
topCircleRadius + (i * 30),
|
||||
spreadPaint,
|
||||
);
|
||||
}
|
||||
|
||||
// Bottom circle - positioned similar to AppBackground (bottom: 100, left: -140, right: -120)
|
||||
final bottomCircleCenter = Offset(size.width * 0.2, size.height + 100);
|
||||
final bottomCircleRadius = 160.0;
|
||||
// Draw multiple circles with different opacities for spread effect (spreadRadius: 60)
|
||||
for (int i = 0; i < 5; i++) {
|
||||
final spreadPaint = Paint()
|
||||
..color = Color.fromARGB(83 ~/ (i + 1), 62, 254, 190)
|
||||
..maskFilter = MaskFilter.blur(BlurStyle.normal, 180 - (i * 25));
|
||||
canvas.drawCircle(
|
||||
bottomCircleCenter,
|
||||
bottomCircleRadius + (i * 40),
|
||||
spreadPaint,
|
||||
);
|
||||
}
|
||||
|
||||
// Draw oval border
|
||||
final borderPaint = Paint()
|
||||
..color = Colors.greenAccent
|
||||
..style = PaintingStyle.stroke
|
||||
..strokeWidth = 4;
|
||||
canvas.drawOval(ovalRect, borderPaint);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
|
||||
}
|
||||
Reference in New Issue
Block a user