mobile_nebula/lib/components/IPField.dart

119 lines
3.9 KiB
Dart
Raw Permalink Normal View History

2020-07-27 20:43:58 +00:00
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
import 'package:mobile_nebula/components/SpecialTextField.dart';
import '../services/utils.dart';
class IPField extends StatelessWidget {
final String help;
final bool ipOnly;
final bool autoFocus;
final FocusNode focusNode;
final FocusNode nextFocusNode;
final ValueChanged<String> onChanged;
final EdgeInsetsGeometry textPadding;
final TextInputAction textInputAction;
final controller;
final textAlign;
const IPField(
{Key key,
this.ipOnly = false,
this.help = "ip address",
this.autoFocus = false,
this.focusNode,
this.nextFocusNode,
this.onChanged,
this.textPadding = const EdgeInsets.all(6.0),
this.textInputAction,
this.controller,
this.textAlign = TextAlign.center})
: super(key: key);
@override
Widget build(BuildContext context) {
var textStyle = CupertinoTheme.of(context).textTheme.textStyle;
final double ipWidth = ipOnly ? Utils.textSize("000000000000000", textStyle).width + 12 : null;
return SizedBox(
width: ipWidth,
child: SpecialTextField(
keyboardType: ipOnly ? TextInputType.numberWithOptions(decimal: true) : null,
textAlign: textAlign,
autofocus: autoFocus,
focusNode: focusNode,
nextFocusNode: nextFocusNode,
controller: controller,
onChanged: onChanged,
maxLength: ipOnly ? 15 : null,
maxLengthEnforced: ipOnly ? true : false,
inputFormatters: ipOnly
? [IPTextInputFormatter()]
2020-07-27 20:43:58 +00:00
: [WhitelistingTextInputFormatter(RegExp(r'[^\s]+'))],
textInputAction: this.textInputAction,
placeholder: help,
));
}
}
class IPTextInputFormatter extends TextInputFormatter {
final Pattern whitelistedPattern = RegExp(r'[\d\.,]+');
@override
TextEditingValue formatEditUpdate(TextEditingValue oldValue, TextEditingValue newValue) {
return _selectionAwareTextManipulation(
newValue,
(String substring) {
return whitelistedPattern
.allMatches(substring)
.map<String>((Match match) => match.group(0))
.join().replaceAll(RegExp(r','), '.');
},
);
}
}
TextEditingValue _selectionAwareTextManipulation(
TextEditingValue value,
String substringManipulation(String substring),
) {
final int selectionStartIndex = value.selection.start;
final int selectionEndIndex = value.selection.end;
String manipulatedText;
TextSelection manipulatedSelection;
if (selectionStartIndex < 0 || selectionEndIndex < 0) {
manipulatedText = substringManipulation(value.text);
} else {
final String beforeSelection = substringManipulation(
value.text.substring(0, selectionStartIndex)
);
final String inSelection = substringManipulation(
value.text.substring(selectionStartIndex, selectionEndIndex)
);
final String afterSelection = substringManipulation(
value.text.substring(selectionEndIndex)
);
manipulatedText = beforeSelection + inSelection + afterSelection;
if (value.selection.baseOffset > value.selection.extentOffset) {
manipulatedSelection = value.selection.copyWith(
baseOffset: beforeSelection.length + inSelection.length,
extentOffset: beforeSelection.length,
);
} else {
manipulatedSelection = value.selection.copyWith(
baseOffset: beforeSelection.length,
extentOffset: beforeSelection.length + inSelection.length,
);
}
}
return TextEditingValue(
text: manipulatedText,
selection: manipulatedSelection ?? const TextSelection.collapsed(offset: -1),
composing: manipulatedText == value.text
? value.composing
: TextRange.empty,
);
}