Created
January 20, 2022 17:53
-
-
Save Metal-666/9be7f0f888e9f4f82e17bd9fedea80ef to your computer and use it in GitHub Desktop.
Challenge 3 (BLoC)
This file contains hidden or 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_bloc/flutter_bloc.dart'; | |
| import 'dart:ui' as ui; | |
| import 'dart:math'; | |
| void main() => runApp(App()); | |
| //------------------------------Widgets----------------------------- | |
| class App extends StatelessWidget { | |
| final Color _primaryColor = Colors.deepPurple[700]!; | |
| final ThemeData _theme = ThemeData.dark(); | |
| @override | |
| Widget build(BuildContext context) => BlocProvider<RootBloc>( | |
| create: (BuildContext context) => RootBloc(), | |
| child: MaterialApp( | |
| theme: _theme.copyWith( | |
| colorScheme: _theme.colorScheme | |
| .copyWith(primary: _primaryColor, secondary: Colors.white), | |
| appBarTheme: AppBarTheme(color: _primaryColor)), | |
| home: Scaffold( | |
| appBar: _appBar(), | |
| body: SizedBox.expand( | |
| child: _root(), | |
| ), | |
| ), | |
| )); | |
| PreferredSizeWidget _appBar() => AppBar( | |
| title: const Text('Clock'), | |
| ); | |
| Widget _root() => Stack(children: <Widget>[_fab(), _clock()]); | |
| Widget _fab() => Positioned( | |
| bottom: 10, | |
| right: 10, | |
| child: BlocBuilder<RootBloc, RootState>( | |
| builder: (BuildContext context, RootState state) => | |
| FloatingActionButton( | |
| onPressed: () => context.read<RootBloc>().add(ToggleNumberStyle()), | |
| child: const Icon(Icons.refresh), | |
| ), | |
| )); | |
| Widget _clock() => | |
| Center(child: SizedBox(height: 300, width: 300, child: Clock())); | |
| } | |
| class Clock extends StatelessWidget { | |
| @override | |
| Widget build(BuildContext context) => BlocBuilder<RootBloc, RootState>( | |
| builder: (BuildContext context, RootState state) => | |
| CustomPaint(painter: ClockPainter(state.numberStyle))); | |
| } | |
| class ClockPainter extends CustomPainter { | |
| final NumberStyle style; | |
| ClockPainter(this.style); | |
| @override | |
| void paint(Canvas canvas, Size size) { | |
| //Create our paints and colors | |
| final Paint background = Paint()..color = Colors.deepPurple[500]!, | |
| face = Paint() | |
| ..shader = ui.Gradient.linear( | |
| Offset.zero, | |
| Offset(size.width, size.height), | |
| [ | |
| Colors.deepPurple[600]!, | |
| Colors.deepPurple[900]!, | |
| ], | |
| ), | |
| bigMark = (Paint()..color = Colors.white)..strokeWidth = 2, | |
| smallMark = (Paint()..color = Colors.grey[400]!)..strokeWidth = 1; | |
| Color numbers = Colors.white; | |
| //Calculate some useful values | |
| final double radius = size.height / 2, | |
| centerX = size.width / 2, | |
| centerY = size.height / 2; | |
| //We might need this in the future? | |
| //canvas.clipRect(Rect.fromLTWH(0, 0, size.width, size.height)); | |
| //Draw clock background (outer circle) | |
| canvas.drawCircle(Offset(centerX, centerY), radius, background); | |
| //Draw clock face (inner circle) | |
| canvas.drawCircle(Offset(centerX, centerY), radius - 5, face); | |
| //Draw the dot in the middle (idk what it's called) | |
| canvas.drawCircle(Offset(centerX, centerY), 5, background); | |
| //Draw hour marks and minute marks | |
| _drawRadialMarks( | |
| 12, 13, 10, centerX, centerY, radius - 20, canvas, bigMark); | |
| _drawRadialMarks( | |
| 12 * 5, 5, 7, centerX, centerY, radius - 17, canvas, smallMark); | |
| //Draw numbers | |
| _drawRadialText( | |
| 12, centerX, centerY, radius - 35, _getClockNumbers(), canvas, numbers); | |
| } | |
| void _drawRadialMarks( | |
| int howMany, | |
| int skipEach, | |
| double length, | |
| double centerX, | |
| double centerY, | |
| double radius, | |
| Canvas canvas, | |
| Paint paint) { | |
| for (int i = 1; i <= howMany; i++) { | |
| if (i % skipEach != 0) { | |
| final double angle = i * (360 / howMany) * pi / 180; | |
| final double x1 = centerX + radius * cos(angle), | |
| y1 = centerY - radius * sin(angle); | |
| final double x2 = centerX + (radius + length) * cos(angle), | |
| y2 = centerY - (radius + length) * sin(angle); | |
| canvas.drawLine(Offset(x1, y1), Offset(x2, y2), paint); | |
| } | |
| } | |
| } | |
| void _drawRadialText(int howMany, double centerX, double centerY, | |
| double radius, List<String> strings, Canvas canvas, Color textColor) { | |
| final TextStyle style = TextStyle( | |
| color: textColor, | |
| fontSize: 20, | |
| ); | |
| for (int i = 0; i < howMany; i++) { | |
| final TextSpan text = TextSpan( | |
| text: strings.length > i ? strings[i] : 'uh', | |
| style: style, | |
| ); | |
| final TextPainter painter = TextPainter( | |
| text: text, | |
| textDirection: TextDirection.ltr, | |
| )..layout(maxWidth: 100, minWidth: 0); | |
| final double angle = (i * (360 / howMany) + 120) * pi / 180; | |
| final double x = centerX - radius * cos(angle), | |
| y = centerY - radius * sin(angle); | |
| painter.paint( | |
| canvas, Offset(x - painter.width / 2, y - painter.height / 2)); | |
| } | |
| } | |
| //Returns a set of numbers depending on current number style (roman|arabic) | |
| List<String> _getClockNumbers() { | |
| switch (style) { | |
| case NumberStyle.arabic: | |
| { | |
| return <String>[ | |
| '1', | |
| '2', | |
| '3', | |
| '4', | |
| '5', | |
| '6', | |
| '7', | |
| '8', | |
| '9', | |
| '10', | |
| '11', | |
| '12' | |
| ]; | |
| } | |
| case NumberStyle.roman: | |
| { | |
| return <String>[ | |
| 'I', | |
| 'II', | |
| 'III', | |
| 'IV', | |
| 'V', | |
| 'VI', | |
| 'VII', | |
| 'VIII', | |
| 'IX', | |
| 'X', | |
| 'XI', | |
| 'XII' | |
| ]; | |
| } | |
| default: | |
| { | |
| return <String>['Huh?']; | |
| } | |
| } | |
| } | |
| @override | |
| bool shouldRepaint(covariant CustomPainter oldDelegate) => true; | |
| } | |
| //------------------------------Widgets----------------------------- | |
| //------------------------------Events------------------------------ | |
| abstract class RootEvents {} | |
| class ToggleNumberStyle extends RootEvents {} | |
| //------------------------------Events------------------------------ | |
| //------------------------------States------------------------------ | |
| class RootState { | |
| final NumberStyle numberStyle; | |
| RootState(this.numberStyle); | |
| } | |
| enum NumberStyle { roman, arabic } | |
| //------------------------------States------------------------------ | |
| //-------------------------------Bloc------------------------------- | |
| class RootBloc extends Bloc<RootEvents, RootState> { | |
| RootBloc() : super(RootState(NumberStyle.roman)) { | |
| //Toggle numberStyle | |
| on<ToggleNumberStyle>((event, emit) => emit(RootState( | |
| state.numberStyle == NumberStyle.roman | |
| ? NumberStyle.arabic | |
| : NumberStyle.roman))); | |
| } | |
| } | |
| //-------------------------------Bloc------------------------------- |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment