├── .gitignore
├── .idea
├── libraries
│ └── Dart_SDK.xml
├── modules.xml
└── workspace.xml
├── CHANGELOG.md
├── LICENSE
├── README.md
├── code_input.iml
├── example
└── main.dart
├── lib
└── code_input.dart
├── pubspec.lock
├── pubspec.yaml
└── screenshots
└── new code input.gif
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .dart_tool/
3 |
4 | .packages
5 | .pub/
6 |
7 | flutter_code_input.iml
8 | flutter_code_input_android.iml
9 |
10 | build/
11 | android/
12 | ios/
13 | ios/.generated/
14 | ios/Flutter/Generated.xcconfig
15 | ios/Runner/GeneratedPluginRegistrant.*
16 |
17 | .metadata
18 | launch.json
19 | *.lock
20 | *.xml
21 |
--------------------------------------------------------------------------------
/.idea/libraries/Dart_SDK.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/workspace.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 | 1534679491680
180 |
181 |
182 | 1534679491680
183 |
184 |
185 | 1541493298941
186 |
187 |
188 |
189 | 1541493298942
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 |
389 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | ## [2.0.0]
4 | * Migrate to null-safety. Thank you [0xdecade](https://github.com/0xdecade)!
5 |
6 | ## [1.0.5]
7 | * add support for spacing property. Thank you [0xdecade](https://github.com/0xdecade)!
8 |
9 | ## [1.0.4]
10 | * add support for onDone callback. Thank you [0xdecade](https://github.com/0xdecade)!
11 |
12 | ## [1.0.3]
13 | * BUG FIX : Not a constant expression: unexpected kernel tag
14 |
15 | ## [1.0.2]
16 | * Add support custom focus node
17 |
18 | ## [1.0.0] - Stable release
19 |
20 | * Full rewrite of the library.
21 | * You can provide a custom builder to build the character entities.
22 | * Provided a wide range of pre-build builders to use (circles or rectangles to be used in light or dark mode).
23 | * Example added.
24 | * Readme edited. Installation does _not_ have to be described there, that's what pub's "Install" tab is for.
25 | * License added.
26 |
27 | ## [0.0.1] - Initial release
28 |
29 | * Initial release.
30 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2018 Marcel Garus & Rahiche
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | SOFTWARE.
20 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # code_input
2 |
3 | A Flutter widget for inputting content with a fixed length, visually treating each character as a separate segment.
4 |
5 | - [Pub Package](https://pub.dartlang.org/packages/code_input)
6 | - [GitHub Repository](https://github.com/rahiche/flutter_code_input)
7 | - [API reference](https://pub.dartlang.org/documentation/code_input/)
8 |
9 | ## Usage
10 |
11 | This is a small example:
12 |
13 | ```dart
14 | CodeInput(
15 | length: 4,
16 | keyboardType: TextInputType.number,
17 | builder: CodeInputBuilders.lightCircle(),
18 | onFilled: (value) => print('Your input is $value.'),
19 | )
20 | ```
21 |
22 |
23 |
24 | For more information about the properties, have a look at the [API reference](https://pub.dartlang.org/documentation/code_input/).
25 |
26 | ## LICENSE
27 |
28 | ```legal
29 | Copyright (c) 2018 Marcel Garus & Rahiche Raouf
30 |
31 | Permission is hereby granted, free of charge, to any person obtaining a copy
32 | of this software and associated documentation files (the "Software"), to deal
33 | in the Software without restriction, including without limitation the rights
34 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
35 | copies of the Software, and to permit persons to whom the Software is
36 | furnished to do so, subject to the following conditions:
37 |
38 | The above copyright notice and this permission notice shall be included in all
39 | copies or substantial portions of the Software.
40 |
41 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
42 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
43 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
44 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
45 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
46 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
47 | SOFTWARE.
48 | ```
49 |
--------------------------------------------------------------------------------
/code_input.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/example/main.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:code_input/code_input.dart';
3 |
4 | void main() => runApp(MyApp());
5 |
6 | class MyApp extends StatelessWidget {
7 | @override
8 | Widget build(BuildContext context) {
9 | return MaterialApp(
10 | title: 'Code input',
11 | color: Colors.deepOrange,
12 | home: Scaffold(
13 | backgroundColor: Colors.deepOrange,
14 | body: Center(child: _buildCodeInput())
15 | ),
16 | );
17 | }
18 |
19 | Widget _buildCodeInput() {
20 | return CodeInput(
21 | length: 4,
22 | keyboardType: TextInputType.number,
23 | builder: CodeInputBuilders.lightCircle(),
24 | spacing: 8,
25 | onFilled: (value) => print('Your input is $value.'),
26 | onDone: (value) => print('Your input is $value.'),
27 | );
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/lib/code_input.dart:
--------------------------------------------------------------------------------
1 | library code_input;
2 |
3 | import 'dart:async';
4 |
5 | import 'package:flutter/material.dart';
6 | import 'package:flutter/services.dart';
7 |
8 | /// A widget for inputting content with a fixed length, visually treating each
9 | /// character as a separate segment.
10 | ///
11 | /// ## Sample code
12 | ///
13 | /// ```dart
14 | /// CodeInput(
15 | /// length: 4,
16 | /// keyboardType: TextInputType.number,
17 | /// builder: CodeInputBuilders.lightCircle(),
18 | /// onFilled: (value) => print('Your input is $value.'),
19 | /// onDone: (value) => print('Your input is $value.'),
20 | /// )
21 | /// ```
22 | ///
23 | /// See also:
24 | ///
25 | /// * [TextField], an input where the characters aren't separated from each
26 | /// other.
27 | typedef CodeInputBuilder = Widget Function(bool hasFocus, String char);
28 |
29 | class CodeInput extends StatefulWidget {
30 | CodeInput._({
31 | Key? key,
32 | required this.length,
33 | required this.focusNode,
34 | required this.keyboardType,
35 | required this.inputFormatters,
36 | required this.builder,
37 | this.spacing = 8,
38 | this.onChanged,
39 | this.onFilled,
40 | this.onDone,
41 | }) : super(key: key);
42 |
43 | factory CodeInput({
44 | Key? key,
45 | required int length,
46 | FocusNode? focusNode,
47 | TextInputType keyboardType = TextInputType.text,
48 | List? inputFormatters,
49 | required CodeInputBuilder builder,
50 | double spacing = 8,
51 | void Function(String value)? onChanged,
52 | void Function(String value)? onFilled,
53 | void Function(String value)? onDone,
54 | }) {
55 | assert(length > 0, 'The length needs to be larger than zero.');
56 | assert(length.isFinite, 'The length needs to be finite.');
57 |
58 | return CodeInput._(
59 | key: key,
60 | length: length,
61 | focusNode: focusNode ?? FocusNode(),
62 | keyboardType: keyboardType,
63 | inputFormatters:
64 | inputFormatters ?? _createInputFormatters(length, keyboardType),
65 | builder: builder,
66 | spacing: spacing,
67 | onChanged: onChanged,
68 | onFilled: onFilled,
69 | onDone: onDone,
70 | );
71 | }
72 |
73 | /// The length of character widgets to always display.
74 | ///
75 | /// ## Sample code
76 | ///
77 | /// A code input with 4 characters:
78 | ///
79 | /// ```dart
80 | /// CodeInput(length: 4)
81 | /// ```
82 | final int length;
83 |
84 | /// Defines the keyboard focus for this widget.
85 | ///
86 | /// The [focusNode] is a long-lived object that's typically managed by a
87 | /// [StatefulWidget] parent. See [FocusNode] for more information.
88 | ///
89 | /// ## Sample code
90 | ///
91 | /// ```dart
92 | /// CodeInput(focusNode: myFocusNode);
93 | /// ```
94 | ///
95 | /// You can then request the `CodeInput`'s focus by calling:
96 | ///
97 | /// ```dart
98 | /// FocusScope.of(context).requestFocus(myFocusNode);
99 | /// ```
100 | final FocusNode focusNode;
101 |
102 | /// The type of keyboard which shows up.
103 | ///
104 | /// ## Sample code
105 | ///
106 | /// ```dart
107 | /// CodeInput(keyboardType: TextInputType.number)
108 | /// ```
109 | final TextInputType keyboardType;
110 |
111 | /// A list of input formatters which can validate the text as it is being
112 | /// typed.
113 | ///
114 | /// If you specify this parameter, the default input formatters aren't used,
115 | /// so make sure you really check for everything (like length of the input).
116 | ///
117 | /// ## Sample code
118 | ///
119 | /// An code input that displays a normal keyboard but only allows for
120 | /// hexadecimal input:
121 | ///
122 | /// ```dart
123 | /// CodeInput(
124 | /// inputFormatters: [
125 | /// FilteringTextInputFormatter.allow(RegExp('^[0-9a-fA-F]*\$'))
126 | /// ]
127 | /// )
128 | /// ```
129 | final List inputFormatters;
130 |
131 | /// A builder for the character widgets.
132 | ///
133 | /// See [CodeInputBuilders] for examples.
134 | final CodeInputBuilder builder;
135 |
136 | /// A parameter for customizing the padding between characters.
137 | final double spacing;
138 |
139 | /// A callback for changes to the input.
140 | final void Function(String value)? onChanged;
141 |
142 | /// A callback for when the input is filled.
143 | final void Function(String value)? onFilled;
144 |
145 | /// A callback for when the done button clicked
146 | final void Function(String value)? onDone;
147 |
148 | /// A helping function that creates input formatters for a given [length] and
149 | /// [keyboardType].
150 | static List _createInputFormatters(
151 | int length, TextInputType keyboardType) {
152 | final formatters = [
153 | LengthLimitingTextInputFormatter(length)
154 | ];
155 |
156 | // Add keyboard specific formatters.
157 | // For example, a code input with a number keyboard type probably doesn't
158 | // want to allow decimal separators or signs.
159 | if (keyboardType == TextInputType.number) {
160 | formatters.add(FilteringTextInputFormatter.allow(RegExp('^[0-9]*\$')));
161 | }
162 |
163 | return formatters;
164 | }
165 |
166 | @override
167 | _CodeInputState createState() => _CodeInputState();
168 | }
169 |
170 | class _CodeInputState extends State {
171 | final controller = TextEditingController();
172 |
173 | String get text => controller.text;
174 |
175 | @override
176 | Widget build(BuildContext context) {
177 | // We'll display the visual widget and a not shown EditableText for doing
178 | // the actual work on top of each other.
179 | return Stack(children: [
180 | // This is the actual EditableText wrapped in a Container with zero
181 | // dimensions.
182 | Container(
183 | width: 0.0,
184 | height: 0.0,
185 | child: EditableText(
186 | controller: controller,
187 | focusNode: widget.focusNode,
188 | inputFormatters: widget.inputFormatters,
189 | keyboardType: widget.keyboardType,
190 | backgroundCursorColor: Colors.black,
191 | style: TextStyle(),
192 | // Doesn't really matter.
193 | cursorColor: Colors.black,
194 | // Doesn't really matter.
195 | onChanged: (value) => setState(() {
196 | widget.onChanged?.call(value);
197 | if (value.length == widget.length) {
198 | widget.onFilled?.call(value);
199 | }
200 | }),
201 | onEditingComplete: () => setState((){
202 | widget.onDone?.call(controller.text);
203 | }),
204 | )),
205 | // These are the actual character widgets. A transparent container lies
206 | // right below the gesture detector, so all taps get collected, even
207 | // the ones between the character widgets.
208 | GestureDetector(
209 | onTap: () {
210 | final focusScope = FocusScope.of(context);
211 | focusScope.requestFocus(FocusNode());
212 | Future.delayed(
213 | Duration.zero,
214 | () => focusScope.requestFocus(widget.focusNode),
215 | );
216 | },
217 | child: Container(
218 | color: Colors.transparent,
219 | child: Row(
220 | mainAxisAlignment: MainAxisAlignment.spaceBetween,
221 | mainAxisSize: MainAxisSize.min,
222 | children: List.generate(widget.length, (i) {
223 | final hasFocus = controller.selection.start == i;
224 | final char = i < text.length ? text[i] : '';
225 | var characterWidget = widget.builder(hasFocus, char);
226 | if (i > 0) {
227 | characterWidget = Padding(
228 | padding: EdgeInsets.only(left: widget.spacing),
229 | child: widget.builder(hasFocus, char),
230 | );
231 | }
232 | return characterWidget;
233 | }),
234 | ),
235 | )),
236 | ]);
237 | }
238 | }
239 |
240 | /// An abstract class that provides some commonly-used builders for the
241 | /// character widgets.
242 | ///
243 | /// * [containerized]: A builder putting chars in an animated container.
244 | /// * [circle]: A builder putting chars in circles.
245 | /// * [rectangle]: A builder putting chars in rectangles.
246 | /// * [lightCircle]: A builder putting chars in light circles.
247 | /// * [darkCircle]: A builder putting chars in dark circles.
248 | /// * [lightRectangle]: A builder putting chars in light rectangles.
249 | /// * [darkRectangle]: A builder putting chars in dark rectangles.
250 | abstract class CodeInputBuilders {
251 | /// Builds the input inside an animated container.
252 | static CodeInputBuilder containerized({
253 | Duration animationDuration = const Duration(milliseconds: 50),
254 | required Size totalSize,
255 | required Size emptySize,
256 | required Size filledSize,
257 | required BoxDecoration emptyDecoration,
258 | required BoxDecoration filledDecoration,
259 | required TextStyle emptyTextStyle,
260 | required TextStyle filledTextStyle,
261 | }) {
262 | return (bool hasFocus, String char) => Container(
263 | width: totalSize.width,
264 | height: totalSize.height,
265 | alignment: Alignment.center,
266 | child: AnimatedContainer(
267 | duration: Duration(milliseconds: 100),
268 | decoration: char.isEmpty ? emptyDecoration : filledDecoration,
269 | width: char.isEmpty ? emptySize.width : filledSize.width,
270 | height: char.isEmpty ? emptySize.height : filledSize.height,
271 | alignment: Alignment.center,
272 | child: Text(char,
273 | style: char.isEmpty ? emptyTextStyle : filledTextStyle),
274 | ));
275 | }
276 |
277 | /// Builds the input inside a circle.
278 | static CodeInputBuilder circle(
279 | {double totalRadius = 30.0,
280 | double emptyRadius = 10.0,
281 | double filledRadius = 25.0,
282 | required Border border,
283 | required Color color,
284 | required TextStyle textStyle}) {
285 | final decoration = BoxDecoration(
286 | shape: BoxShape.circle,
287 | border: border,
288 | color: color,
289 | );
290 |
291 | return containerized(
292 | totalSize: Size.fromRadius(totalRadius),
293 | emptySize: Size.fromRadius(emptyRadius),
294 | filledSize: Size.fromRadius(filledRadius),
295 | emptyDecoration: decoration,
296 | filledDecoration: decoration,
297 | emptyTextStyle: textStyle.copyWith(fontSize: 0.0),
298 | filledTextStyle: textStyle);
299 | }
300 |
301 | /// Builds the input inside a rectangle.
302 | static CodeInputBuilder rectangle({
303 | Size totalSize = const Size(50.0, 60.0),
304 | Size emptySize = const Size(20.0, 20.0),
305 | Size filledSize = const Size(40.0, 60.0),
306 | BorderRadius borderRadius = BorderRadius.zero,
307 | required Border border,
308 | required Color color,
309 | required TextStyle textStyle,
310 | }) {
311 | final decoration = BoxDecoration(
312 | border: border,
313 | borderRadius: borderRadius,
314 | color: color,
315 | );
316 |
317 | return containerized(
318 | totalSize: totalSize,
319 | emptySize: emptySize,
320 | filledSize: filledSize,
321 | emptyDecoration: decoration,
322 | filledDecoration: decoration,
323 | emptyTextStyle: textStyle.copyWith(fontSize: 0.0),
324 | filledTextStyle: textStyle);
325 | }
326 |
327 | /// Builds the input inside a light circle.
328 | static CodeInputBuilder lightCircle({
329 | double totalRadius = 30.0,
330 | double emptyRadius = 10.0,
331 | double filledRadius = 25.0,
332 | }) {
333 | return circle(
334 | totalRadius: totalRadius,
335 | emptyRadius: emptyRadius,
336 | filledRadius: filledRadius,
337 | border: Border.all(color: Colors.white, width: 2.0),
338 | color: Colors.white10,
339 | textStyle: TextStyle(
340 | color: Colors.white, fontSize: 20.0, fontWeight: FontWeight.bold));
341 | }
342 |
343 | /// Builds the input inside a light circle.
344 | static CodeInputBuilder darkCircle({
345 | double totalRadius = 30.0,
346 | double emptyRadius = 10.0,
347 | double filledRadius = 25.0,
348 | }) {
349 | return circle(
350 | totalRadius: totalRadius,
351 | emptyRadius: emptyRadius,
352 | filledRadius: filledRadius,
353 | border: Border.all(color: Colors.black, width: 2.0),
354 | color: Colors.black12,
355 | textStyle: TextStyle(
356 | color: Colors.black, fontSize: 20.0, fontWeight: FontWeight.bold));
357 | }
358 |
359 | /// Builds the input inside a light rectangle.
360 | static CodeInputBuilder lightRectangle({
361 | Size totalSize = const Size(50.0, 60.0),
362 | Size emptySize = const Size(20.0, 20.0),
363 | Size filledSize = const Size(40.0, 60.0),
364 | BorderRadius borderRadius = BorderRadius.zero,
365 | }) {
366 | return rectangle(
367 | totalSize: totalSize,
368 | emptySize: emptySize,
369 | filledSize: filledSize,
370 | borderRadius: borderRadius,
371 | border: Border.all(color: Colors.white, width: 2.0),
372 | color: Colors.white10,
373 | textStyle: TextStyle(
374 | color: Colors.white, fontSize: 20.0, fontWeight: FontWeight.bold));
375 | }
376 |
377 | /// Builds the input inside a dark rectangle.
378 | static CodeInputBuilder darkRectangle({
379 | Size totalSize = const Size(50.0, 60.0),
380 | Size emptySize = const Size(20.0, 20.0),
381 | Size filledSize = const Size(40.0, 60.0),
382 | BorderRadius borderRadius = BorderRadius.zero,
383 | }) {
384 | return rectangle(
385 | totalSize: totalSize,
386 | emptySize: emptySize,
387 | filledSize: filledSize,
388 | borderRadius: borderRadius,
389 | border: Border.all(color: Colors.black, width: 2.0),
390 | color: Colors.black12,
391 | textStyle: TextStyle(
392 | color: Colors.black, fontSize: 20.0, fontWeight: FontWeight.bold));
393 | }
394 | }
395 |
--------------------------------------------------------------------------------
/pubspec.lock:
--------------------------------------------------------------------------------
1 | # Generated by pub
2 | # See https://dart.dev/tools/pub/glossary#lockfile
3 | packages:
4 | async:
5 | dependency: transitive
6 | description:
7 | name: async
8 | url: "https://pub.dartlang.org"
9 | source: hosted
10 | version: "2.6.1"
11 | boolean_selector:
12 | dependency: transitive
13 | description:
14 | name: boolean_selector
15 | url: "https://pub.dartlang.org"
16 | source: hosted
17 | version: "2.1.0"
18 | characters:
19 | dependency: transitive
20 | description:
21 | name: characters
22 | url: "https://pub.dartlang.org"
23 | source: hosted
24 | version: "1.1.0"
25 | charcode:
26 | dependency: transitive
27 | description:
28 | name: charcode
29 | url: "https://pub.dartlang.org"
30 | source: hosted
31 | version: "1.2.0"
32 | clock:
33 | dependency: transitive
34 | description:
35 | name: clock
36 | url: "https://pub.dartlang.org"
37 | source: hosted
38 | version: "1.1.0"
39 | collection:
40 | dependency: transitive
41 | description:
42 | name: collection
43 | url: "https://pub.dartlang.org"
44 | source: hosted
45 | version: "1.15.0"
46 | fake_async:
47 | dependency: transitive
48 | description:
49 | name: fake_async
50 | url: "https://pub.dartlang.org"
51 | source: hosted
52 | version: "1.2.0"
53 | flutter:
54 | dependency: "direct main"
55 | description: flutter
56 | source: sdk
57 | version: "0.0.0"
58 | flutter_test:
59 | dependency: "direct dev"
60 | description: flutter
61 | source: sdk
62 | version: "0.0.0"
63 | matcher:
64 | dependency: transitive
65 | description:
66 | name: matcher
67 | url: "https://pub.dartlang.org"
68 | source: hosted
69 | version: "0.12.10"
70 | meta:
71 | dependency: transitive
72 | description:
73 | name: meta
74 | url: "https://pub.dartlang.org"
75 | source: hosted
76 | version: "1.3.0"
77 | path:
78 | dependency: transitive
79 | description:
80 | name: path
81 | url: "https://pub.dartlang.org"
82 | source: hosted
83 | version: "1.8.0"
84 | sky_engine:
85 | dependency: transitive
86 | description: flutter
87 | source: sdk
88 | version: "0.0.99"
89 | source_span:
90 | dependency: transitive
91 | description:
92 | name: source_span
93 | url: "https://pub.dartlang.org"
94 | source: hosted
95 | version: "1.8.1"
96 | stack_trace:
97 | dependency: transitive
98 | description:
99 | name: stack_trace
100 | url: "https://pub.dartlang.org"
101 | source: hosted
102 | version: "1.10.0"
103 | stream_channel:
104 | dependency: transitive
105 | description:
106 | name: stream_channel
107 | url: "https://pub.dartlang.org"
108 | source: hosted
109 | version: "2.1.0"
110 | string_scanner:
111 | dependency: transitive
112 | description:
113 | name: string_scanner
114 | url: "https://pub.dartlang.org"
115 | source: hosted
116 | version: "1.1.0"
117 | term_glyph:
118 | dependency: transitive
119 | description:
120 | name: term_glyph
121 | url: "https://pub.dartlang.org"
122 | source: hosted
123 | version: "1.2.0"
124 | test_api:
125 | dependency: transitive
126 | description:
127 | name: test_api
128 | url: "https://pub.dartlang.org"
129 | source: hosted
130 | version: "0.3.0"
131 | typed_data:
132 | dependency: transitive
133 | description:
134 | name: typed_data
135 | url: "https://pub.dartlang.org"
136 | source: hosted
137 | version: "1.3.0"
138 | vector_math:
139 | dependency: transitive
140 | description:
141 | name: vector_math
142 | url: "https://pub.dartlang.org"
143 | source: hosted
144 | version: "2.1.0"
145 | sdks:
146 | dart: ">=2.12.0 <3.0.0"
147 |
--------------------------------------------------------------------------------
/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: code_input
2 | description: Flutter Code Input Widget
3 | version: 2.0.0
4 | homepage: https://github.com/Rahiche/flutter_code_input
5 |
6 | environment:
7 | sdk: ">=2.12.0 <3.0.0"
8 |
9 |
10 | dependencies:
11 | flutter:
12 | sdk: flutter
13 |
14 | dev_dependencies:
15 | flutter_test:
16 | sdk: flutter
17 |
--------------------------------------------------------------------------------
/screenshots/new code input.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rahiche/flutter_code_input/d5f0aa748e97f8a02381e8beb9d5b3bc8b72e3b4/screenshots/new code input.gif
--------------------------------------------------------------------------------