diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c21af8..f0c4f7d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [0.1.3] - 2021-July-12. + +* 1. Add wired widget `wired toggle`. +* 2. doc: add pub pkg, likes, release date and MIT to readme +* 3. Add wired widget `wired progress`. + ## [0.1.2] - 2021-July-6. * Add the dart doc comments. @@ -8,5 +14,5 @@ ## [0.1.0] - 2021-July-5. -* Initial release -* Support widgets for wired button, wired card, wired checkbox, wired combo, wired dialog, wired divider, wired input, wired radio, wired slider. \ No newline at end of file +* 1. Initial release +* 2. Support widgets for `wired button`, `wired card`, `wired checkbox`, `wired combo`, `wired dialog`, `wired divider`, `wired input`, `wired radio`, `wired slider`. \ No newline at end of file diff --git a/README.md b/README.md index 5a3f54e..96bd2e9 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,8 @@ +[![Pub](https://img.shields.io/pub/v/wired_elements?label=wired_elements&color=blue)](https://pub.dev/packages/wired_elements) +[![likes](https://badges.bar/wired_elements/likes)](https://pub.dev/packages/wired_elements/score) +[![GitHub Release Date](https://img.shields.io/github/release-date/KevinZhang19870314/wired_elements)](https://pub.dev/packages/wired_elements) +[![GitHub](https://img.shields.io/github/license/KevinZhang19870314/wired_elements)](https://github.com/KevinZhang19870314/wired_elements/blob/main/LICENSE) + # wired_elements Wired Elements is a series of basic UI Elements that have a hand drawn look. These can be used for wireframes, mockups, or just the fun hand-drawn look. It's the Flutter implementation of [wired-elements](https://github.com/rough-stuff/wired-elements). It's base on the library of [flutter_rough](https://github.com/sergiandreplace/flutter_rough). @@ -28,4 +33,10 @@ Some screenshots of the example app: -

\ No newline at end of file +

+ +## Others + +[flutter_rough](https://github.com/sergiandreplace/flutter_rough) is an awesome library, but its not null safety, there is an [issue](https://github.com/sergiandreplace/flutter_rough/issues/5) linked to it, but with no response until now therefore I have to copy all of the code in project and do null safety myself. As long as the author of flutter_rough do the sound null safety, I will use this library as dependency instead of copying all the source code. + +## And, the last, pr is welcome! \ No newline at end of file diff --git a/example/lib/demos.dart b/example/lib/demos.dart index 29022b1..253459d 100644 --- a/example/lib/demos.dart +++ b/example/lib/demos.dart @@ -6,8 +6,10 @@ import 'package:example/src/wired_divider_example.dart'; import 'package:flutter/material.dart'; import 'src/wired_button_example.dart'; import 'src/wired_input_example.dart'; +import 'src/wired_progress_example.dart'; import 'src/wired_radio_example.dart'; import 'src/wired_slider_example.dart'; +import 'src/wired_toggle_example.dart'; final String handWriting1 = 'Shadows Into Light'; final String handWriting2 = 'Architects Daughter'; @@ -67,6 +69,18 @@ final List demos = [ (_) => WiredSliderExample(title: 'Wired slider'), const Icon(Icons.linear_scale, size: 36), ), + NormalDemo( + 'Wired toggle example', + 'Wired toggle', + (_) => WiredToggleExample(title: 'Wired toggle'), + const Icon(Icons.toggle_on, size: 36), + ), + NormalDemo( + 'Wired progress example', + 'Wired progress', + (_) => WiredProgressExample(title: 'Wired progress'), + const Icon(Icons.portrait, size: 36), + ), ]; abstract class Demo { diff --git a/example/lib/src/wired_progress_example.dart b/example/lib/src/wired_progress_example.dart new file mode 100644 index 0000000..a830761 --- /dev/null +++ b/example/lib/src/wired_progress_example.dart @@ -0,0 +1,81 @@ +import 'package:flutter/material.dart'; +import 'package:wired_elements/wired_elements.dart'; + +import 'wired_text.dart'; + +class WiredProgressExample extends StatefulWidget { + final String title; + const WiredProgressExample({Key? key, required this.title}) : super(key: key); + + @override + _WiredProgressExampleState createState() => _WiredProgressExampleState(); +} + +class _WiredProgressExampleState extends State + with TickerProviderStateMixin { + @override + Widget build(BuildContext context) { + final _controller1 = AnimationController( + duration: const Duration(milliseconds: 1000), vsync: this); + final _controller2 = AnimationController( + duration: const Duration(milliseconds: 1000), vsync: this); + return Scaffold( + appBar: AppBar( + title: WiredText( + '${widget.title}', + fontSize: 20.0, + ), + ), + body: Padding( + padding: EdgeInsets.symmetric(horizontal: 20.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + WiredProgress(controller: _controller1, value: 0.5), + SizedBox(height: 20.0), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + ..._example(_controller1), + ], + ), + SizedBox(height: 50.0), + WiredProgress(controller: _controller2), + SizedBox(height: 20.0), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + ..._example(_controller2), + ], + ), + ], + ), + ), + ); + } + + List _example(AnimationController controller) { + return [ + WiredButton( + child: Text('Start'), + onPressed: () { + controller.forward(); + }, + ), + SizedBox(width: 20.0), + WiredButton( + child: Text('Stop'), + onPressed: () { + controller.stop(); + }, + ), + SizedBox(width: 20.0), + WiredButton( + child: Text('Reset'), + onPressed: () { + controller.reset(); + }, + ), + ]; + } +} diff --git a/example/lib/src/wired_toggle_example.dart b/example/lib/src/wired_toggle_example.dart new file mode 100644 index 0000000..9882e34 --- /dev/null +++ b/example/lib/src/wired_toggle_example.dart @@ -0,0 +1,51 @@ +import 'package:flutter/material.dart'; +import 'package:wired_elements/wired_elements.dart'; + +import 'wired_text.dart'; + +class WiredToggleExample extends StatelessWidget { + final String title; + const WiredToggleExample({Key? key, required this.title}) : super(key: key); + + @override + Widget build(BuildContext context) { + bool _firstVal = false; + bool _secondVal = true; + + return Scaffold( + appBar: AppBar( + title: WiredText( + '$title', + fontSize: 20.0, + ), + ), + body: Container( + color: Colors.transparent, + padding: EdgeInsets.all(50.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + WiredToggle( + value: _firstVal, + onChange: (val) { + print(val); + + return false; + }, + ), + SizedBox(height: 50.0), + WiredToggle( + value: _secondVal, + onChange: (val) { + print(val); + + return true; + }, + ), + ], + ), + ), + ); + } +} diff --git a/example/pubspec.lock b/example/pubspec.lock index 3afd036..e52f7b8 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -155,7 +155,7 @@ packages: path: ".." relative: true source: path - version: "0.1.2" + version: "0.1.3" sdks: dart: ">=2.12.0 <3.0.0" flutter: ">=1.17.0" diff --git a/lib/src/wired_base.dart b/lib/src/wired_base.dart index ccabcfe..31ce79b 100644 --- a/lib/src/wired_base.dart +++ b/lib/src/wired_base.dart @@ -82,7 +82,13 @@ class WiredRectangleBase extends WiredPainterBase { /// The amount of empty space to the trailing edge of the rectangle. final double rightIndent; - WiredRectangleBase({this.leftIndent = 0.0, this.rightIndent = 0.0}); + final Color fillColor; + + WiredRectangleBase({ + this.leftIndent = 0.0, + this.rightIndent = 0.0, + this.fillColor = filledColor, + }); @override void paintRough( @@ -95,7 +101,8 @@ class WiredRectangleBase extends WiredPainterBase { size.width - leftIndent - rightIndent, size.height, ); - canvas.drawRough(figure, WiredBase.pathPaint, WiredBase.fillPaint); + canvas.drawRough( + figure, WiredBase.pathPaint, WiredBase.fillPainter(fillColor)); } } diff --git a/lib/src/wired_progress.dart b/lib/src/wired_progress.dart new file mode 100644 index 0000000..c96a027 --- /dev/null +++ b/lib/src/wired_progress.dart @@ -0,0 +1,111 @@ +import 'package:flutter/material.dart'; +import 'package:wired_elements/rough/rough.dart'; +import 'package:wired_elements/src/const.dart'; + +import 'canvas/wired_canvas.dart'; +import 'wired_base.dart'; + +/// Wired progress +/// +/// Usage: +/// ```dart +/// final _controller = AnimationController( +/// duration: const Duration(milliseconds: 1000), vsync: this); +/// ...... +/// WiredProgress(controller: _controller, value: 0.5), +/// ...... +/// _controller.forward(); +/// _controller.stop(); +/// _controller.reset(); +/// ``` +class WiredProgress extends StatefulWidget { + /// The current progress value, range is 0.0 ~ 1.0. + final double value; + + final AnimationController controller; + + const WiredProgress({ + Key? key, + required this.controller, + this.value = 0.0, + }) : super(key: key); + + @override + _WiredProgressState createState() => _WiredProgressState(); +} + +class _WiredProgressState extends State with WiredRepaintMixin { + final double _progressHeight = 20.0; + double _width = 0.0; + + late Animation _animation; + late Tween _tween; + + @override + void initState() { + super.initState(); + + _tween = Tween(begin: 0, end: 1); + _animation = _tween.animate( + CurvedAnimation( + parent: widget.controller, + curve: Curves.easeIn, + ), + )..addListener(() { + setState(() {}); + }); + + // Delay for calculate the width `_getWidth()` during the next frame + Future.delayed(Duration(milliseconds: 0), () { + _tween.begin = widget.value; + setState(() {}); + }); + } + + @override + Widget build(BuildContext context) { + return buildWiredElement(child: _buildWidget()); + } + + Widget _buildWidget() { + _width = _getWidth(); + + return Stack( + children: [ + SizedBox( + height: _progressHeight, + width: _width * _animation.value, + child: WiredCanvas( + painter: WiredRectangleBase(fillColor: borderColor), + fillerType: RoughFilter.HachureFiller, + fillerConfig: FillerConfig.build(hachureGap: 1.5), + ), + ), + SizedBox( + height: _progressHeight, + width: _width, + child: WiredCanvas( + painter: WiredRectangleBase(), + fillerType: RoughFilter.NoFiller, + ), + ), + LinearProgressIndicator( + backgroundColor: Colors.transparent, + minHeight: _progressHeight, + color: Colors.transparent, + value: _animation.value, + ), + ], + ); + } + + double _getWidth() { + double width = 0; + try { + var box = context.findRenderObject() as RenderBox; + width = box.size.width; + } catch (e) {} + + return width; + } +} diff --git a/lib/src/wired_slider.dart b/lib/src/wired_slider.dart index 2e34303..446f505 100644 --- a/lib/src/wired_slider.dart +++ b/lib/src/wired_slider.dart @@ -109,7 +109,7 @@ class _WiredSliderState extends State { ), ), Positioned( - left: _getSliderWidth() * _currentSliderValue / widget.max - 12, + left: _getWidth() * _currentSliderValue / widget.max - 12, child: SizedBox( height: 24.0, width: 24.0, @@ -153,7 +153,7 @@ class _WiredSliderState extends State { ); } - double _getSliderWidth() { + double _getWidth() { double width = 0; try { var box = context.findRenderObject() as RenderBox; diff --git a/lib/src/wired_toggle.dart b/lib/src/wired_toggle.dart new file mode 100644 index 0000000..0996419 --- /dev/null +++ b/lib/src/wired_toggle.dart @@ -0,0 +1,115 @@ +import 'package:flutter/material.dart'; +import 'package:wired_elements/rough/rough.dart'; + +import 'canvas/wired_canvas.dart'; +import 'const.dart'; +import 'wired_base.dart'; + +/// Wired toggle +class WiredToggle extends StatefulWidget { + final bool value; + final bool Function(bool)? onChange; + + const WiredToggle({ + Key? key, + required this.value, + required this.onChange, + }) : super(key: key); + + @override + _WiredToggleState createState() => _WiredToggleState(); +} + +class _WiredToggleState extends State + with SingleTickerProviderStateMixin, WiredRepaintMixin { + bool _isSwitched = false; + final double _thumbRadius = 24.0; + late Animation _animation; + late AnimationController _controller; + + @override + void initState() { + super.initState(); + _isSwitched = widget.value; + _controller = AnimationController( + duration: const Duration(milliseconds: 250), + vsync: this, + ); + + _animation = Tween( + begin: -_thumbRadius, + end: _thumbRadius * 1.5, + ).animate( + CurvedAnimation( + parent: _controller, + curve: Curves.easeIn, + ), + )..addListener( + () { + setState(() {}); + }, + ); + + _toggle(); + } + + @override + Widget build(BuildContext context) { + return buildWiredElement( + child: GestureDetector( + onTap: () { + if (widget.onChange != null) { + bool result = widget.onChange!(!_isSwitched); + if (result) { + _isSwitched = !_isSwitched; + _toggle(); + } + } + }, + child: _buildSwicher(), + ), + ); + } + + Widget _buildSwicher() { + return Stack( + clipBehavior: Clip.none, + children: [ + Positioned( + left: _animation.value, + top: -_thumbRadius / 2, + child: SizedBox( + height: _thumbRadius * 2, + width: _thumbRadius * 2, + child: WiredCanvas( + painter: WiredCircleBase( + diameterRatio: .7, + fillColor: textColor, + ), + fillerType: RoughFilter.HachureFiller, + fillerConfig: FillerConfig.build(hachureGap: 1.0), + ), + ), + ), + SizedBox( + width: _thumbRadius * 2.5, + height: _thumbRadius, + child: WiredCanvas( + painter: WiredRectangleBase(), + fillerType: RoughFilter.NoFiller, + ), + ), + ], + ); + } + + void _toggle() { + _isSwitched ? _controller.forward() : _controller.reverse(); + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } +} diff --git a/lib/wired_elements.dart b/lib/wired_elements.dart index 4d8a545..c5ceb14 100644 --- a/lib/wired_elements.dart +++ b/lib/wired_elements.dart @@ -9,3 +9,5 @@ export 'src/wired_divider.dart'; export 'src/wired_input.dart'; export 'src/wired_radio.dart'; export 'src/wired_slider.dart'; +export 'src/wired_toggle.dart'; +export 'src/wired_progress.dart'; diff --git a/pubspec.yaml b/pubspec.yaml index edc998b..7707970 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: wired_elements description: Wired Elements is a series of basic UI Elements that have a hand drawn look. These can be used for wireframes, mockups, or just the fun hand-drawn look. -version: 0.1.2 +version: 0.1.3 homepage: https://github.com/KevinZhang19870314/wired_elements environment: