I am using a textfield with these properties:
TextField(
controller: textController,
keyboardType: TextInputType.multiline,
maxLines: 4,
maxLength: 150,
),
Which works fine but I was wondering how I could prevent users from typing in break lines that would cause the text field to have more lines that the maxLines (4)..
Is there a way of locking the lines at 4? e.g.
input 1 \n \n \n should work
but 1 \n \n \n \n \n \n should not be allowed
I modified LengthLimitingTextInputFormatter to get my own MaxLinesTextInputFormatter.
Here is the code
class MaxLinesTextInputFormatter extends TextInputFormatter {
MaxLinesTextInputFormatter(this.maxLines)
: assert(maxLines == null || maxLines == -1 || maxLines > 0);
final int maxLines;
@override
TextEditingValue formatEditUpdate(
TextEditingValue oldValue, // unused.
TextEditingValue newValue,
) {
if (maxLines != null && maxLines > 0) {
final regEx = RegExp("^.*((\n?.*){0,${maxLines - 1}})");
String newString = regEx.stringMatch(newValue.text) ?? "";
final maxLength = newString.length;
if (newValue.text.runes.length > maxLength) {
final TextSelection newSelection = newValue.selection.copyWith(
baseOffset: math.min(newValue.selection.start, maxLength),
extentOffset: math.min(newValue.selection.end, maxLength),
);
final RuneIterator iterator = RuneIterator(newValue.text);
if (iterator.moveNext())
for (int count = 0; count < maxLength; ++count)
if (!iterator.moveNext()) break;
final String truncated = newValue.text.substring(0, iterator.rawIndex);
return TextEditingValue(
text: truncated,
selection: newSelection,
composing: TextRange.empty,
);
}
return newValue;
}
return newValue;
}
}
Usage:
TextField(
decoration: InputDecoration(),
maxLines: 4,
inputFormatters: [MaxLinesTextInputFormatter(4)],
)
You can use allMatches() function to count the number of lines the input contains and update an error variable if the function returns 4 or more.
if (('\n'.allMatches(text).length + 1) > 4) { // check for new lines and update bool variable }
An example:
import 'package:flutter/material.dart';
class Demo extends StatefulWidget {
@override
_DemoState createState() => _DemoState();
}
class _DemoState extends State<Demo> {
final textController = TextEditingController();
bool error = false;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("DEMO"),
),
body: Container(
child: Column(children: [
TextField(
controller: textController,
keyboardType: TextInputType.multiline,
maxLines: 4,
maxLength: 150,
onChanged: (text) {
setState(() {
if (('\n'.allMatches(text).length + 1) > 4) {
error = true;
} else {
error = false;
}
});
},
),
error ? Text("More than 4 lines entered") : Container()
])));
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With