Widget providing input code field to insert pin, sms and other auth codes.\ Also can be used for time/date or any highly formatted input.\ And supports backspace keyboard button.
import 'package:code_field/code_field.dart';
InputCodeControl
handles all logic parts, input validation, holds current value and index pointer to next field.
Standard InputCodeField
is drawn with underline and can be customized with InputCodeDecoration
. Supports enable/disable state, obscuring, sizing, coloring, etc..
final codeControl = InputCodeControl(inputRegex: '^[0-9]*$');
InputCodeField(
control: codeControl,
count: 6,
inputType: TextInputType.number,
decoration: InputCodeDecoration(
focusColor: Colors.blueGrey,
),
),
For better visual control can be used itemBuilder to build custom Field Item.\
To get char at given index use []
operator on InputCodeControl.\
To check if item at given index is focused use InputCodeControl.isFocused(index)
and InputCodeControl.hasFocus
to check if whole Widget has focus.
InputCodeField(
control: codeControl
itemBuilder: (context, index) => CustomCodeItem(
char: control.stringCode.code[index],
fieldFocused: codeControl.hasFocus,
itemFocused: codeControl.isFocused(index),
),
);
class CustomCodeItem extends StatelessWidget {
final String char;
final bool fieldFocused;
final bool itemFocused;
const CustomCodeItem({
Key key,
this.char: '',
this.fieldFocused: false,
this.itemFocused: false,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
width: 42.0,
height: 42.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(6.0),
color: fieldFocused ? (itemFocused ? Colors.grey : Colors.grey.withOpacity(0.5)) : Colors.grey.withOpacity(0.25),
border: Border.all(color: itemFocused ? Colors.black : Colors.grey),
),
child: Center(
child: Text(
char,
style: Theme.of(context).primaryTextTheme.headline4,
),
),
);
}
}
For total visual control use builder to build whole input widget. InputCodeField
and InputCodeControl
still handles all input logic and keyboard actions.
InputCodeField(
control: codeControl
builder: (context) => CustomCodeField(
control: codeControl,
),
);
class CustomCodeField extends StatelessWidget {
final InputCodeControl control;
const CustomCodeField({
Key key,
this.control,
}) : super(key: key);
@override
Widget build(BuildContext context) {
final items = List<Widget>();
for (int i = 0; i < control.count; i++) {
if (i > 0 && i % 3 == 0) {
items.add(Container(
margin: EdgeInsets.symmetric(horizontal: 24.0),
height: 32.0,
width: 2.0,
color: control.hasFocus ? Colors.green : Colors.blueGrey,
));
items.add(Container(
height: 42,
width: 1.0,
color: Colors.blueGrey,
));
}
items.add(Expanded(
child: Container(
height: 42.0,
color: control.isFocused(i, true) ? Colors.greenAccent.withOpacity(0.25) : Colors.transparent,
child: Center(
child: Text(
control[i],
style: Theme.of(context).primaryTextTheme.headline4,
),
),
),
));
if (i < control.count - 1) {
items.add(Container(
height: 42,
width: 1.0,
color: Colors.blueGrey,
));
}
}
return ClipRRect(
borderRadius: BorderRadius.circular(16.0),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16.0),
border: Border.all(color: control.hasFocus ? Colors.green : Colors.blueGrey),
),
child: Row(
children: items,
),
),
);
}
}
What's missing: