Add All the files from the touchpad_demonstrator Flutter App which can be build for Android and iOS

This commit is contained in:
Richard Stern
2019-06-04 16:51:24 +02:00
parent 26fcc2491c
commit a951e9518d
1340 changed files with 12844936 additions and 0 deletions
+69
View File
@@ -0,0 +1,69 @@
import 'package:touch_demonstrator/src/blocs/BlocProvider.dart';
import 'package:touch_demonstrator/pages/DebugPage.dart';
import 'package:flutter/material.dart';
import 'package:touch_demonstrator/src/blocs/bluetoothBloc.dart';
import 'package:touch_demonstrator/src/blocs/debugCounterBloc.dart';
Widget buildAppBarPageTouchPoints(BuildContext context) {
void _pageRouteDebugView() {
print('Debug button pressed');
Navigator.push(
context, MaterialPageRoute(builder: (context) => DebugView()));
}
IconButton _buildDebugIconButton() {
return IconButton(
key: Key('debugButton'),
icon: Icon(Icons.bug_report),
onPressed: _pageRouteDebugView,
);
}
StreamBuilder<bool> titleAppBar() {
final bBloc = BlocProvider.of(context).bluetoothBlocGetter;
var appBarText;
return StreamBuilder<bool>(
stream: bBloc.isConnected$,
initialData: false,
builder: (BuildContext context, AsyncSnapshot<bool> snapshot) {
if (snapshot.hasData) {
snapshot.data
? appBarText = 'Connected'
: appBarText = 'Disconnected';
return AnimatedSwitcher(
duration: Duration(milliseconds: 300),
transitionBuilder: (Widget child, Animation<double> opacity) {
return FadeTransition(child: child, opacity: opacity);
},
child: Text(
'$appBarText',
key: ValueKey<String>(appBarText),
textDirection: TextDirection.ltr,
),
);
} else
return Text('Disconnected');
});
}
List<Widget> actionsAppBar() {
final debugBloc = BlocProvider.of(context).debugBlocGetter;
return <Widget>[
StreamBuilder<bool>(
stream: debugBloc.debugEnabledStatus$,
initialData: false,
builder: (BuildContext context, AsyncSnapshot<bool> snapshotDebug) {
if (snapshotDebug.hasData) {
return snapshotDebug.data ? _buildDebugIconButton() : Container();
} else
return Container();
},
),
];
}
return AppBar(
title: titleAppBar(),
actions: actionsAppBar(),
);
}
+126
View File
@@ -0,0 +1,126 @@
import 'package:flutter/material.dart';
import 'package:flutter_blue/flutter_blue.dart';
import 'package:touch_demonstrator/src/blocs/BlocProvider.dart'; //bloc:
import 'package:flare_flutter/flare_actor.dart';
class ConnectButtonWithAnimations extends StatefulWidget {
@override
ConnectButtonWithAnimationsState createState() {
return new ConnectButtonWithAnimationsState();
}
}
class ConnectButtonWithAnimationsState
extends State<ConnectButtonWithAnimations>
with SingleTickerProviderStateMixin {
/// Builds Button if the app is not connected to a touch pad or animates search progress.
Animation animation;
AnimationController animationController;
static const _heightContainer = 60.0;
static const _widthContainer = 170.0;
static const EdgeInsets _containerEdgeInset = EdgeInsets.all(8.0);
static const durationOpacity = Duration(milliseconds: 150);
@override
Widget build(BuildContext context) {
final bBloc = BlocProvider.of(context).bluetoothBlocGetter;
return Hero(
tag: 'buttonHero',
child: Container(
margin: _containerEdgeInset,
height: _heightContainer,
width: _widthContainer,
child: StreamBuilder<BluetoothState>(
stream: bBloc.bluetoothState$,
initialData: BluetoothState.on,
builder: (_, AsyncSnapshot<BluetoothState> snapshot) {
if (snapshot.hasData) {
if (snapshot.data == BluetoothState.on) {
// Bluetooth is on, button enabled.
return StreamBuilder<bool>(
stream: bBloc.isScanning$,
initialData: false,
builder: (_, AsyncSnapshot<bool> snapshotIsScanning) {
if (snapshotIsScanning.hasData) {
return AnimatedSwitcher(
duration: durationOpacity,
transitionBuilder:
(Widget child, Animation<double> opacity) {
return Padding(
padding: EdgeInsets.all(8.0),
child: FadeTransition(
child: child, opacity: opacity),
);
},
child: (snapshotIsScanning.data)
? ScanAnimation()
: ConnectButton());
} else
return Container();
});
} else {
// Bluetooth is off, button disabled.
return Container();
}
}
}),
),
);
}
}
class ScanAnimation extends StatelessWidget {
@override
Widget build(BuildContext context) {
return FlareActor(
'assets/Animations/loading2.flr',
animation: 'Loading',
fit: BoxFit.contain,
alignment: Alignment.center,
isPaused: false,
);
}
}
class ConnectButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
var _primaryColor = Theme.of(context).primaryColor;
var _buttonTextStyle = TextStyle(color: _primaryColor, fontSize: 20.0);
final bBloc = BlocProvider.of(context).bluetoothBlocGetter;
var _buttonText;
var _buttonFunction;
return StreamBuilder<bool>(
stream: bBloc.isConnected$,
initialData: false,
builder: (_, AsyncSnapshot<bool> snapshotIsConnected) {
if (snapshotIsConnected.hasData) {
if (snapshotIsConnected.data) {
_buttonText = Text(
"Disconnect",
style: _buttonTextStyle,
key: Key('DisconnectButton'), // for integration test
);
_buttonFunction = () => bBloc.disconnect.add(null);
} else {
_buttonText = Text(
"Connect",
style: _buttonTextStyle,
key: Key('ConnectButton'), // for integration test
);
_buttonFunction = () => bBloc.scan.add(null);
}
return Center(
child: OutlineButton(
key: Key('ConnectionButton'), // for integration test
borderSide: BorderSide(color: _primaryColor),
shape: BeveledRectangleBorder(),
onPressed: _buttonFunction,
child: _buttonText,
),
);
} else
return Container();
});
}
}
+65
View File
@@ -0,0 +1,65 @@
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:touch_demonstrator/src/blocs/BlocProvider.dart'; //bloc:
class LogoWithText extends StatelessWidget {
final _heightLogo;
LogoWithText(this._heightLogo);
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
TextAboveLogo(),
Logo(_heightLogo),
],
);
}
}
class Logo extends StatelessWidget {
final _heightLogo;
Logo(this._heightLogo);
_buildLogo() {
// returns Logo of PolyIC
return Container(
key: Key('Logo'), // for integration test
height: _heightLogo,
child: Center(
child: Image.asset(
'assets/PolyIC/PolyIC_Logo.png',
),
),
);
}
@override
Widget build(BuildContext context) {
final debugBloc = BlocProvider.of(context).debugBlocGetter;
return Hero(
tag: 'logoHero',
child: Padding(
padding: EdgeInsets.all(10.0),
child: GestureDetector(
onTap: () => debugBloc.debugCounterIncrement.add(null),
// onLongPress: () => debugBloc.debugEnable.add(null),
child: _buildLogo()),
),
);
}
}
class TextAboveLogo extends StatelessWidget {
/// Line of text above the logo that adds information to it.
static const _textStyle = TextStyle(fontSize: 18);
static const _buildText = Text('Touchpad Demonstrator by',
textDirection: TextDirection.ltr, style: _textStyle);
@override
Widget build(BuildContext context) => _buildText;
}
+101
View File
@@ -0,0 +1,101 @@
import 'package:flutter_blue/flutter_blue.dart';
import 'package:flutter/material.dart';
import 'package:touch_demonstrator/src/blocs/BlocProvider.dart';
class Modal {
_buildScanResult(
BuildContext context, Map<DeviceIdentifier, ScanResult> scanResults) {
final bBloc = BlocProvider.of(context).bluetoothBlocGetter;
return scanResults.values
.where((result) => result.advertisementData.localName
.contains('Touchpad Demonstrator'))
.map((result) => ScanResultTile(
result: result,
onTapCallback: () {
bBloc.connect.add(result);
print('Connect to ${result.device.name} pressed!');
Navigator.pop(context);
}))
.toList();
}
_buildHeaderBottomSheet(BuildContext context) {
return Container(
color: Theme.of(context).primaryColor,
child: ListTile(
title: Center(
child: Text(
"CHOOSE TOUCHPAD",
style: TextStyle(color: Colors.white),
),
),
),
);
}
connectBottomSheet(
BuildContext context, Map<DeviceIdentifier, ScanResult> scanResults) {
print('Modal Sheet - Result Count: ${scanResults.length}');
var _bottomSheetElements = List<Widget>();
_bottomSheetElements.add(_buildHeaderBottomSheet(context));
_bottomSheetElements.addAll(_buildScanResult(context, scanResults));
showModalBottomSheet(
context: context,
builder: (BuildContext context) {
return Container(
child: Padding(
padding: EdgeInsets.all(0.0),
child: ListView(
shrinkWrap: true, children: _bottomSheetElements)));
});
}
}
class ScanResultTile extends StatelessWidget {
final ScanResult result;
final VoidCallback onTapCallback;
const ScanResultTile({Key key, this.result, this.onTapCallback})
: super(key: key);
_buildTitle(BuildContext context) {
var textOfTile;
(result.device.name.length > 0)
? textOfTile = result.device.name
: textOfTile = result.device.id.toString();
return Flexible(
child: Container(
child: Text(
textOfTile,
overflow: TextOverflow.ellipsis,
style: TextStyle(fontWeight: FontWeight.bold),
)));
}
_buildConnectButton(BuildContext context) {
return OutlineButton(
borderSide: BorderSide(color: Theme.of(context).primaryColor),
shape: BeveledRectangleBorder(),
onPressed: (result.advertisementData.connectable) ? onTapCallback : null,
child: Text('CONNECT'),
); // Name of devices
}
@override
Widget build(BuildContext context) {
return Container(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
_buildTitle(context),
_buildConnectButton(context),
],
),
),
);
}
}
+582
View File
@@ -0,0 +1,582 @@
import 'dart:async';
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:touch_demonstrator/model/buttonData.dart';
import 'package:touch_demonstrator/model/touchData.dart';
import 'package:touch_demonstrator/model/vibrate.dart';
import 'package:touch_demonstrator/src/blocs/BlocProvider.dart';
import 'package:flare_flutter/flare_actor.dart';
import 'dart:core';
import 'package:vibrate/vibrate.dart';
Duration durationSensorAnimation = Duration(milliseconds: 200);
class Battery extends StatelessWidget {
@override
Widget build(BuildContext context) {
final bBloc = BlocProvider.of(context).bluetoothBlocGetter;
return Positioned(
bottom: 0,
left: 0,
child: StreamBuilder<int>(
stream: bBloc.batteryValue$,
initialData: null,
builder: (BuildContext context, AsyncSnapshot<int> snapshotBattery) {
return Container(
padding: EdgeInsets.all(0.0),
color: Colors.transparent,
child: Padding(
padding: const EdgeInsets.all(3.0),
child: (snapshotBattery.data == null)
? Container()
: Container(
padding: EdgeInsets.all(4.0),
decoration: BoxDecoration(
color: Theme.of(context).accentColor,
borderRadius: new BorderRadius.all(
const Radius.circular(3.0))),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Icon(
Icons.battery_full,
color: Colors.white,
),
Text(
'${snapshotBattery.data.toString()}%',
style: TextStyle(color: Colors.white),
),
],
),
),
),
);
}),
);
}
}
class Sensor extends StatefulWidget {
@override
SensorState createState() {
return SensorState();
}
}
class SensorState extends State<Sensor> {
static var animationDisabled = false;
static var firstTimeDidChangeDependencies = true;
static var canVibrate = false;
_drawButtons(
BuildContext context, double _heightSensor, double _widthSensor) {
final bBloc = BlocProvider.of(context).bluetoothBlocGetter;
final _buttonsPosY = [0.74 * _heightSensor, 0.57 * _heightSensor, 0.39 * _heightSensor];
final _buttonsPosX = 0.074 * _widthSensor;
final _buttonWidth = 0.08 * _widthSensor;
return StreamBuilder<List<bool>>(
stream: bBloc.buttonsState$,
initialData: [false, false, false],
builder:
(BuildContext context, AsyncSnapshot<List<bool>> snapshotButtons) {
if (snapshotButtons.hasData) {
return Stack(
children: <Widget>[
_singleButton(0, _buttonsPosX, _buttonsPosY[0], _buttonWidth,
snapshotButtons.data[0]),
_singleButton(1, _buttonsPosX, _buttonsPosY[1], _buttonWidth,
snapshotButtons.data[1]),
_singleButton(2, _buttonsPosX, _buttonsPosY[2], _buttonWidth,
snapshotButtons.data[2])
],
);
} else
return Container();
});
}
_singleButton(int buttonNumber, double _buttonPosX,
double _buttonPosY, double _widthButton, bool _isPressed) {
///draws a button of Type home(0), multitasking(1) or back(2).
assert(buttonNumber >= 0 && buttonNumber <= 2);
Color buttonColor;
_isPressed
? buttonColor = Theme.of(context).primaryColor
: buttonColor = Colors.white;
if (buttonNumber >= 3) return Container();
return AnimatedPositioned(
duration: durationSensorAnimation,
left: _buttonPosX,
bottom: _buttonPosY,
child: Image(
image: AssetImage('assets/buttons/button$buttonNumber.png'),
color: buttonColor,
width: _widthButton,
),
);
}
_notConnectedText() {
return Positioned.fill(
child: Stack(
children: <Widget>[
BackdropFilter(
filter: ImageFilter.blur(
sigmaX: 0.3,
sigmaY: 0.3,
),
child: Container(color: Colors.black.withOpacity(0)),
),
Center(
child: Container(
padding: EdgeInsets.all(15.0),
decoration: BoxDecoration(
color: Colors.black45,
shape: BoxShape.rectangle,
borderRadius: BorderRadius.circular(8.0),
),
child: Text(
'Not connected to a device',
style: TextStyle(color: Colors.white),
))),
],
));
}
_successAnimation() {
if (animationDisabled) {
print('no animation');
return Container();
}
print('animation');
return Container(
padding: EdgeInsets.all(80.0),
child: Center(
child: FlareActor(
'assets/Animations/success_hide.flr',
animation: 'success',
fit: BoxFit.contain,
alignment: Alignment.center,
isPaused: false,
),
),
);
}
_middleSensor(
BuildContext context, double _heightSensor, double _widthSensor) {
final bBloc = BlocProvider.of(context).bluetoothBlocGetter;
final _marginRight = _widthSensor * 0.168;
final _marginLeft = _widthSensor * 0.18;
return StreamBuilder<List<TouchData>>(
stream: bBloc.getTouchesToVisualise$,
initialData: [TouchData(5, 0, 1200, 1200)],
builder: (BuildContext context,
AsyncSnapshot<List<TouchData>> snapshotTouches) {
if (snapshotTouches.hasData) {
return Container(
height: _heightSensor,
width: _widthSensor,
margin: EdgeInsets.only(left: _marginLeft, right: _marginRight),
child: MiddleOfSensor(
snapshotTouches.data, context, _heightSensor, _widthSensor),
// CustomPaint( foregroundPainter:TouchPainter(context, snapshotTouches.data), ),
);
} else {
return Container();
}
});
}
_sensorImage(){
return BoxDecoration(
image: DecorationImage(
image: ExactAssetImage('assets/sensor.png'),
fit: BoxFit.fitHeight),
);
}
@override
Widget build(BuildContext context) {
final bBloc = BlocProvider.of(context).bluetoothBlocGetter;
final widthOfScreen = MediaQuery.of(context).size.width;
final heightOfScreen = MediaQuery.of(context).size.height;
var _heightSensorConnected;
var _widthSensorConnected;
var _heightSensorDisconnected;
var _widthSensorDisconnected;
(heightOfScreen > widthOfScreen)
? _widthSensorConnected = _heightSensorConnected = widthOfScreen * 0.8
: _heightSensorConnected = _widthSensorConnected = heightOfScreen * 0.8;
_heightSensorDisconnected = _heightSensorConnected * 0.8;
_widthSensorDisconnected = _widthSensorConnected * 0.8;
return StreamBuilder(
stream: bBloc.isConnected$,
initialData: false,
builder:
(BuildContext context, AsyncSnapshot<bool> snapshotIsConnected) {
if (snapshotIsConnected.hasData) {
return Hero(
tag: 'touchpadHero',
child: AnimatedOpacity(
duration: durationSensorAnimation,
opacity: snapshotIsConnected.data ? 1.0 : 0.8,
child: Container(
// margin: EdgeInsets.only(left: 10.0, right: 10.0),
width: _widthSensorConnected,
height: _heightSensorConnected,
child: Center(
child: AnimatedContainer(
duration: durationSensorAnimation,
decoration: _sensorImage(),
height: snapshotIsConnected.data
? _heightSensorConnected
: _heightSensorDisconnected,
width: snapshotIsConnected.data
? _widthSensorConnected
: _widthSensorDisconnected,
child: Stack(
children: <Widget>[
_middleSensor(context, _heightSensorConnected, _widthSensorConnected),
snapshotIsConnected.data
? _drawButtons(
context, _heightSensorConnected, _widthSensorConnected)
: _drawButtons(context, _heightSensorDisconnected,
_widthSensorDisconnected),
DrawSlider(context, _widthSensorConnected, _heightSensorConnected),
snapshotIsConnected.data
? _successAnimation()
: _notConnectedText(),
Battery(),
],
),
),
),
),
),
);
} else
return Container();
});
}
void _disableSuccessAnimation(bool isConnected) {
// If already are connected to a device -> prevent success animation from showing again.
// This would happens if you change orientation of device.
if (isConnected) {
vibrateDelayed(FeedbackType.success,Duration(milliseconds: 50));
Future.delayed(Duration(seconds: 1), () {
animationDisabled = true;
});
} else {
// Activate success animation for next connection.
animationDisabled = false;
}
}
void _vibrateDependingOnButtonEvent(buttonsState buttonState) {
(buttonState == buttonsState.pressed)
? vibrate(FeedbackType.selection)
: vibrate(FeedbackType.impact);
}
@override
void didChangeDependencies() {
final bBloc = BlocProvider.of(context).bluetoothBlocGetter;
print('didchangedependencies');
if (firstTimeDidChangeDependencies) {
bBloc.isConnected$.listen((data) => _disableSuccessAnimation(data));
bBloc.vibrationButton$
.listen((data) => _vibrateDependingOnButtonEvent(data));
firstTimeDidChangeDependencies = false;
}
super.didChangeDependencies();
}
}
class DrawSlider extends StatefulWidget {
final BuildContext context;
final double _heightSensor, _widthSensor;
DrawSlider(this.context, this._heightSensor, this._widthSensor);
@override
_DrawSliderState createState() => _DrawSliderState();
}
class _DrawSliderState extends State<DrawSlider>
with SingleTickerProviderStateMixin {
AnimationController _controller;
Animation _animation;
static const Duration sliderAnimationMoveDuration = Duration(milliseconds: 1);
static int lastPercent = 101;
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: Duration(milliseconds: 300),
);
_animation = Tween(
begin: 1.0,
end: 0.0,
).animate(_controller);
_controller.reverse();
}
@override
void dispose() {
_controller.dispose();
_controller = null;
super.dispose();
}
_sliderFadeAwayAnimation() {
if (_controller != null) {
_controller.reset();
}
Future.delayed(Duration(seconds: 1), () {
if (_controller != null) {
_controller.forward();
}
});
}
_drawSlider(double percent) {
var _sliderPosY = 0.12 * widget._heightSensor +
percent * widget._heightSensor * 0.01 * 0.78;
var _sliderPosX = widget._widthSensor * 0.83;
return Positioned(
left: _sliderPosX,
bottom: _sliderPosY,
child: Image(
color: Theme.of(context).primaryColor,
image: AssetImage('assets/slider_4.png'),
width: widget._widthSensor * 0.15,
),
);
}
_drawSliderText(int percent) {
var _sliderTextPosX = widget._widthSensor * 0.73;
var _sliderTextPosY = 0.13 * widget._heightSensor +
percent * widget._heightSensor * 0.01 * 0.78;
// return AnimatedPositioned(
return Positioned(
// duration: sliderAnimationMoveDuration,
left: _sliderTextPosX,
bottom: _sliderTextPosY,
child: Container(
width: 25.0,
child: Text(
'$percent',
textAlign: TextAlign.end,
style: TextStyle(color: Colors.white),
),
),
);
}
@override
Widget build(BuildContext context) {
final bBloc = BlocProvider.of(context).bluetoothBlocGetter;
// print('slider build');
return StreamBuilder<int>(
stream: bBloc.slider$,
builder: (BuildContext context, AsyncSnapshot<int> sliderSnapshot) {
if (sliderSnapshot.hasData) {
if (sliderSnapshot.data <= 100 && sliderSnapshot.data >= 0) {
if (lastPercent != sliderSnapshot.data)
_sliderFadeAwayAnimation();
lastPercent = sliderSnapshot.data;
print('Slider: ${sliderSnapshot.data}');
print('');
return FadeTransition(
opacity: _animation,
child: Stack(
children: <Widget>[
_drawSlider(sliderSnapshot.data.toDouble()),
_drawSliderText(lastPercent),
],
),
);
} else
return Container();
} else
return Container();
});
}
}
class MiddleOfSensor extends StatefulWidget {
final List<TouchData> touchCollection;
final BuildContext context;
final double _heightSensor;
final double _widthSensor;
MiddleOfSensor(this.touchCollection, this.context, this._heightSensor,
this._widthSensor);
@override
_MiddleOfSensorState createState() => _MiddleOfSensorState();
}
class _MiddleOfSensorState extends State<MiddleOfSensor> {
Duration durationTouchPointChange = Duration(microseconds: 200);
static const leftLine = 100.0;
static const rightLine = 900.0;
static const maxSize = rightLine - leftLine;
static const yMaxSize = 1023;
static const fingerSize = 25.0;
static const List<Color> _fingerColors = [
Colors.lightBlue,
Colors.green,
Colors.deepPurple,
Colors.deepOrangeAccent,
Colors.pink,
];
Widget _buildMiddleOfSensor(List<TouchData> _lastFingerTouchDataPoints) {
Widget _touchPoint(TouchData item, BoxConstraints constraints) {
var _height = constraints.constrainHeight();
var _width = constraints.constrainWidth();
var _xCircle = _width * (item.x.toDouble() - leftLine) / maxSize;
var _yCircle = 0.04 * _height + 0.84 * _height * item.y.toDouble() / yMaxSize;
Text _buildTouchPointText = Text(
'${item.fingerNumber.toString()}',
style: TextStyle(fontSize: 20, color: Colors.white),
);
return AnimatedPositioned(
// return Positioned(
duration: durationTouchPointChange,
left: _xCircle - fingerSize / 2,
top: _yCircle - fingerSize / 2,
child: Container(
width: fingerSize,
height: fingerSize,
decoration: BoxDecoration(
color: _fingerColors[item.fingerNumber],
shape: BoxShape.circle,
),
child: Center(
child: _buildTouchPointText))
);
}
return LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
return Stack(
children: _lastFingerTouchDataPoints
.where((TouchData item) => item.event == 4 || item.event == 1)
.where((TouchData item) => item.x < 1200 && item.y < 1200)
.where((TouchData item) => item.fingerNumber < 5)
.map((TouchData item) => _touchPoint(item, constraints))
.toList());
});
}
@override
Widget build(BuildContext context) {
return _buildMiddleOfSensor(widget.touchCollection);
}
}
/*class TouchPainter extends CustomPainter {
/// Draws Slider or touches in the middle of the touch pad.
List<TouchData> touchCollection;
BuildContext context;
double width;
TouchPainter(this.context, this.touchCollection);
static List<Color> _colorOfTouches = [
Colors.lightBlue,
Colors.green,
Colors.deepPurple,
Colors.deepOrangeAccent,
Colors.pink,
];
@override
void paint(Canvas canvas, Size size) {
double leftLine = 80.0;
double rightLine = 900.0;
double maxSize = rightLine - leftLine;
double xCircle, xText;
double yCircle, yText;
Offset offsetCircle, offsetText;
void _drawCircle(int fingerNumber, Offset offset, Color v) {
// double xCircle;
// double yCircle;
// xCircle = x.toDouble() / maxSize * size.width;
// yCircle = y.toDouble() / 1100 * size.height;
Paint line = Paint()
..color = v
..strokeCap = StrokeCap.round
..style = PaintingStyle.fill
..strokeWidth = 15.0;
// print("C: $xCircle / ${size.width}");
canvas.drawCircle(offset, 16.0, line);
}
void _drawPercent(int fingerNumber, Offset offset){
TextSpan span = TextSpan(style: TextStyle(color: Colors.white, fontSize: 20), text: '$fingerNumber');
TextPainter tp = TextPainter(text: span, textAlign: TextAlign.right, textDirection: TextDirection.ltr);
tp.layout();
tp.paint(canvas, offset);
}
touchCollection.forEach((k) {
// print("${k.f} ${k.e} ${k.x} ${k.y}");
if (k.x >= leftLine && k.x <= rightLine && k.fingerNumber <=4) {
switch (k.event) {
case 5:
break;
case 4:
continue move;
move:
case 1:
{
xCircle = (k.x.toDouble() - leftLine) / maxSize * size.width;
yCircle = k.y.toDouble() / 1100 * size.height;
print("Incoming (${k.x.round().toString()}|${k.y.round().toString()})");
xText = (k.x.toDouble() - leftLine - 27.0) / maxSize * size.width;
yText = (k.y.toDouble() - 44.0) / 1100 * size.height;
offsetCircle = Offset(xCircle, yCircle );
offsetText = Offset(xText, yText);
_drawCircle(k.fingerNumber, offsetCircle, _colorOfTouches[k.fingerNumber.toInt()]);
_drawPercent(k.fingerNumber, offsetText);
break;
}
default:
{
print("Data is Corrupt");
break;
}
}
}
});
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}*/
+54
View File
@@ -0,0 +1,54 @@
import 'package:flutter/material.dart';
import 'package:touch_demonstrator/pages/SideBarContent.dart';
class LeftDrawer extends StatelessWidget {
static const htmlPrivacyNotes = 'assets/html/privacy_notice.html';
static const htmlImprint = 'assets/html/imprint.html';
static const htmlTermsOfUse = 'assets/html/terms_of_use.html';
static const htmlDisclaimer = 'assets/html/disclaimer.html';
static const headerText = Text(
'Touch Demonstrator App',
textScaleFactor: 1.5,
style: TextStyle(color: Colors.white),
);
DrawerHeader _buildHeader(BuildContext context) {
return DrawerHeader(
key: Key('DrawerHeader'),
child: headerText,
decoration: BoxDecoration(color: Theme.of(context).primaryColor),
);
}
ListTile _buildTile(BuildContext context, String title, String html) {
return ListTile(
key: Key(title),
title: Text(title),
onTap: () {
Navigator.pop(context);
Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) =>
SideBarContent(title: title, html: html)));
},
);
}
@override
Widget build(BuildContext context) {
return Drawer(
key: Key('Drawer'),
child: ListView(
padding: EdgeInsets.zero,
children: <Widget>[
_buildHeader(context),
_buildTile(context, 'Privacy Notes', htmlPrivacyNotes),
_buildTile(context, 'Imprint', htmlImprint),
_buildTile(context, 'Terms of Use', htmlTermsOfUse),
_buildTile(context, 'Disclaimer', htmlDisclaimer),
],
),
);
}
}
+101
View File
@@ -0,0 +1,101 @@
import 'dart:ui';
import 'package:flutter/material.dart';
//import 'package:flutter_svg/flutter_svg.dart';
import 'package:touch_demonstrator/pages/PageTouchPoints.dart';
import 'package:touch_demonstrator/src/blocs/BlocProvider.dart'; //bloc:
import 'package:flutter/animation.dart';
class Button extends StatelessWidget {
/// Button that navigates to the page 'PageTouchPoints'
@override
Widget build(BuildContext context) {
return Hero(
tag: 'SearchHero',
child: Padding(
padding: const EdgeInsets.all(8.0),
child: RaisedButton(
color: Theme.of(context).accentColor,
shape: StadiumBorder(),
onPressed: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => PageTouchPoints()));
},
child: Text(
'Search and Connect Touchpad',
style: TextStyle(color: Colors.white),
),
),
),
);
}
}
class TouchPad extends StatelessWidget {
/// Image of the touch pad
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Image.asset('assets/trackpad.png'),
);
}
}
class ReusableWidgets {
getAppBar(String title) {
return AppBar(
title: Text(title),
);
}
getAppBar2(BuildContext context) {
final bBloc = BlocProvider.of(context).bluetoothBlocGetter;
String appBarText;
return AppBar(
title: StreamBuilder<bool>(
stream: bBloc.isConnected$,
initialData: false,
builder: (BuildContext context, AsyncSnapshot<bool> snapshot) {
if (snapshot.hasData) {
if (snapshot.data) {
appBarText = 'Connected';
} else {
// _showSnackbar('Disconnected');
// return Text('Disconnected');
appBarText = 'Disconnected';
}
return AnimatedSwitcher(
duration: const Duration(milliseconds: 350),
transitionBuilder: (Widget child, Animation<double> opacity) {
return FadeTransition(child: child, opacity: opacity);
},
child: new Text(
'$appBarText',
// Must have this key to build a unique widget when _count changes.
key: new ValueKey<String>(appBarText),
textScaleFactor: 1.0,
textDirection: TextDirection.ltr,
),
);
} else
return Text('Disconnected');
}),
// actions: <Widget>[
// enableDebug ?IconButton(
// icon: Icon(Icons.build),
// onPressed: () {
// print('pressed');
// Navigator.push(
// context, MaterialPageRoute(builder: (context) => DebugView()));
// },
// ):Container(),
// ],
);
}
}