Last active
January 7, 2020 09:23
-
-
Save BoHellgren/1e20bda3a87c5218e067af592ada0b2a to your computer and use it in GitHub Desktop.
Dog camera step 2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/material.dart'; | |
import 'package:flutter/services.dart'; | |
import 'package:camera/camera.dart'; | |
import 'package:soundpool/soundpool.dart'; | |
import 'dart:ui' as ui; | |
import 'package:flutter/foundation.dart'; | |
import 'package:flutter/rendering.dart'; | |
void main() => runApp(MyApp()); | |
class MyApp extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return MaterialApp( | |
home: MyHomePage(), | |
); | |
} | |
} | |
class MyHomePage extends StatefulWidget { | |
MyHomePage({Key key}) : super(key: key); | |
@override | |
_MyHomePageState createState() => _MyHomePageState(); | |
} | |
import 'package:flutter/material.dart'; | |
import 'package:flutter/services.dart'; | |
import 'package:camera/camera.dart'; | |
import 'package:soundpool/soundpool.dart'; | |
import 'dart:ui' as ui; | |
import 'package:flutter/foundation.dart'; | |
import 'package:flutter/rendering.dart'; | |
void main() => runApp(MyApp()); | |
class MyApp extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return MaterialApp( | |
home: MyHomePage(), | |
); | |
} | |
} | |
class MyHomePage extends StatefulWidget { | |
MyHomePage({Key key}) : super(key: key); | |
@override | |
_MyHomePageState createState() => _MyHomePageState(); | |
} | |
class _MyHomePageState extends State<MyHomePage> { | |
CameraController _controller; | |
bool _cameraInitialized = false; | |
Soundpool _pool; | |
int _soundId; | |
@override | |
void initState() { | |
super.initState(); | |
SystemChrome.setEnabledSystemUIOverlays([SystemUiOverlay.bottom]); | |
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.dark); | |
_initializeApp(); | |
} | |
void _initializeApp() async { | |
List<CameraDescription> cameras = await availableCameras(); | |
_controller = CameraController(cameras[0], ResolutionPreset.medium); | |
_controller.initialize().then((_) async { | |
_cameraInitialized = true; | |
}); | |
_pool = Soundpool(streamType: StreamType.notification); | |
_soundId = await rootBundle | |
.load("assets/178186__snapper4298__camera-click-nikon.wav") | |
.then((ByteData soundData) { | |
return _pool.load(soundData); | |
}); | |
} | |
@override | |
void dispose() { | |
_controller?.dispose(); | |
super.dispose(); | |
} | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
body: GestureDetector( | |
onTapDown: (TapDownDetails details) async { | |
double mediaHeight = MediaQuery.of(context).size.height; | |
if (details.localPosition.dy < mediaHeight * 0.8) return; | |
double mediaWidth = MediaQuery.of(context).size.width; | |
double xTap = details.localPosition.dx; | |
if (xTap < mediaWidth * 0.35) { | |
print('Left button tapped'); | |
} else if (xTap < mediaWidth * 0.65) { | |
print('Middle button tapped'); | |
_pool.play(_soundId); | |
} else { | |
print('Right button tapped'); | |
} | |
}, | |
child: Container( | |
child: _cameraInitialized | |
? OverflowBox( | |
maxWidth: double.infinity, | |
child: AspectRatio( | |
aspectRatio: _controller.value.aspectRatio, | |
child: Stack(fit: StackFit.expand, children: <Widget>[ | |
CameraPreview(_controller), | |
CustomPaint(painter: ButtonsPainter(null)), | |
]))) | |
: Text( | |
' Waiting for camera initialization', | |
style: TextStyle(fontSize: 20), | |
), | |
), | |
)); | |
} | |
} | |
class ButtonsPainter extends CustomPainter { | |
ui.Image buttonImage; | |
ButtonsPainter(this.buttonImage); | |
@override | |
void paint(Canvas canvas, Size size) { | |
var paint = Paint(); | |
// First paint black field around buttons with low opacity | |
paint.color = Colors.black.withOpacity(0.1); | |
Rect rect = | |
Offset(0.0, size.height * 0.8) & Size(size.width, size.height * 0.2); | |
canvas.drawRect(rect, paint); | |
// Draw buttons at 10% from the bottom | |
final double yButton = size.height * 0.9; | |
paint.style = PaintingStyle.fill; | |
paint.color = Colors.grey; | |
final double canvasWidth = size.width; | |
double xButton; | |
var icon; | |
// Paint left button if no buttonImage supplied | |
if (buttonImage == null) { | |
xButton = canvasWidth * 0.3; | |
icon = Icons.photo_library; | |
canvas.drawCircle(Offset(xButton, yButton), 22.0, paint); | |
var builder = ui.ParagraphBuilder(ui.ParagraphStyle( | |
fontFamily: icon.fontFamily, | |
fontSize: 25.0, | |
)) | |
..addText(String.fromCharCode(icon.codePoint)); | |
var para = builder.build(); | |
para.layout(const ui.ParagraphConstraints(width: 100.0)); | |
canvas.drawParagraph(para, Offset(xButton - 12.5, yButton - 12.5)); | |
} | |
//Paint middle button. | |
xButton = canvasWidth * 0.5; | |
canvas.drawCircle(Offset(xButton, yButton), 32.0, paint); | |
paint.color = Colors.white; | |
canvas.drawCircle(Offset(xButton, yButton), 28.0, paint); | |
// Paint right button. | |
xButton = canvasWidth * 0.7; | |
icon = Icons.info_outline; | |
paint.color = Colors.grey; | |
canvas.drawCircle(Offset(xButton, yButton), 22.0, paint); | |
var builder = ui.ParagraphBuilder(ui.ParagraphStyle( | |
fontFamily: icon.fontFamily, | |
fontSize: 25.0, | |
)) | |
..addText(String.fromCharCode(icon.codePoint)); | |
var para = builder.build(); | |
para.layout(const ui.ParagraphConstraints(width: 100.0)); | |
canvas.drawParagraph(para, Offset(xButton - 12.5, yButton - 12.5)); | |
// Paint image on left button | |
if (buttonImage != null) { | |
xButton = canvasWidth * 0.3; | |
// First set up a round clipping area. | |
double radius = 22.0; | |
double l, t, r, b; | |
l = xButton - radius; | |
r = xButton + radius; | |
t = yButton - radius; | |
b = yButton + radius; | |
ui.Rect clippingRect = Rect.fromLTRB(l, t, r, b); | |
RRect clippingArea = | |
RRect.fromRectAndRadius(clippingRect, Radius.circular(radius)); | |
canvas.clipRRect(clippingArea); | |
// Then draw the square button image over the round clipping area | |
double x, y = 0.0; | |
x = xButton - buttonImage.height / 2.0; | |
y = yButton - buttonImage.width / 2.0; | |
Offset buttonOffset = Offset(x, y); | |
canvas.drawImage(buttonImage, buttonOffset, Paint()); | |
} | |
} | |
@override | |
bool shouldRepaint(ButtonsPainter oldDelegate) => | |
oldDelegate.buttonImage != buttonImage; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment