Skip to content

Instantly share code, notes, and snippets.

@sma
Created September 19, 2019 21:46
Show Gist options
  • Save sma/f00d34274a6184121e91fdf23bc3ea51 to your computer and use it in GitHub Desktop.
Save sma/f00d34274a6184121e91fdf23bc3ea51 to your computer and use it in GitHub Desktop.
Trivial Flutter app to track HP for RPGs
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'HP Tracker',
theme: ThemeData(
brightness: Brightness.dark,
primaryColor: Colors.deepOrange,
),
home: TrackerPage(),
);
}
}
class TrackerPage extends StatefulWidget {
@override
_TrackerPageState createState() => _TrackerPageState();
}
class _TrackerPageState extends State<TrackerPage> {
int _hp = 0;
bool _show = false;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("HP Tracker")),
body: Stack(
fit: StackFit.expand,
alignment: Alignment.center,
children: <Widget>[
SwipeDetector(
onTap: () => setState(() => _show = !_show),
onSwipeUp: () => update(1),
onSwipeDown: () => update(-1),
child: Padding(
padding: const EdgeInsets.all(32),
child: FittedBox(
fit: BoxFit.scaleDown,
child: Text(
'$_hp',
style: TextStyle(fontSize: 320, fontWeight: FontWeight.w200),
),
),
),
),
Positioned(
bottom: 20,
child: AnimatedOpacity(
duration: Duration(milliseconds: 1000),
opacity: _hp == 0 ? 1 : 0,
child: Text("Swipe up or down", style: Theme.of(context).textTheme.caption),
),
),
AnimatedOpacity(
duration: Duration(milliseconds: 200),
opacity: _show ? 1 : 0,
child: Column(
children: <Widget>[
Row(
children: <Widget>[
Inc(value: 1, update: update),
Inc(value: 5, update: update),
Inc(value: 10, update: update),
Inc(value: 100, update: update),
],
),
Row(
children: <Widget>[
Inc(value: -1, update: update),
Inc(value: -5, update: update),
Inc(value: -10, update: update),
Inc(value: -100, update: update),
],
),
],
),
),
],
),
);
}
void update(int delta) {
setState(() => _hp += delta);
}
}
class SwipeDetector extends StatefulWidget {
const SwipeDetector({
Key key,
this.onTap,
this.onSwipeUp,
this.onSwipeDown,
this.child,
}) : super(key: key);
final VoidCallback onTap;
final VoidCallback onSwipeUp;
final VoidCallback onSwipeDown;
final Widget child;
@override
_SwipeDetectorState createState() => _SwipeDetectorState();
}
class _SwipeDetectorState extends State<SwipeDetector> {
Offset _start, _end;
@override
Widget build(BuildContext context) {
return GestureDetector(
onVerticalDragStart: (details) {
_start = _end = details.globalPosition;
},
onVerticalDragUpdate: (details) {
_end = details.globalPosition;
},
onVerticalDragEnd: (details) {
final delta = _start - _end;
if (delta.dy > 2) {
widget.onSwipeUp?.call();
} else if (delta.dy < -2) {
widget.onSwipeDown?.call();
} else {
widget.onTap?.call();
}
},
child: widget.child,
);
}
}
class Inc extends StatelessWidget {
const Inc({Key key, this.value, this.update}) : super(key: key);
final int value;
final void Function(int) update;
@override
Widget build(BuildContext context) {
return Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 4),
child: FlatButton(
onPressed: () => update(value),
color: Colors.white10,
child: Text('$value'),
textColor: Colors.grey,
padding: EdgeInsets.all(0),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(0)),
),
),
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment