Skip to content

Instantly share code, notes, and snippets.

@BoHellgren
Last active January 7, 2020 09:23
Show Gist options
  • Save BoHellgren/1e20bda3a87c5218e067af592ada0b2a to your computer and use it in GitHub Desktop.
Save BoHellgren/1e20bda3a87c5218e067af592ada0b2a to your computer and use it in GitHub Desktop.
Dog camera step 2
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