Open fabricio-godoi opened 3 years ago
I've been trying to fix some bugs with the cursor, but it appears to be something related to the way the TextEditingController works. But I will try to fix this one. Can you provide a minimal sample project with this issue?
I will try to help investigate a little further why this is happening, but I'm using as simple as possible. Try the sample below with the library in 2.1.0 and Flutter 2.0.5.
First, add some number in both field (not filling them up), then try to put the cursor in the middle of the sentence. The date one will not be able to.
Second, put the $100,00 value in the money field, then move the cursor in the middle (after the "1" digit). After you put another digit, you will see the cursor jumping to the end of the sentence. In my debugs, this generally happens because of the way flutter interacts with mask and values updates.
If I find any other way to improve I will share with you.
import 'package:extended_masked_text/extended_masked_text.dart';
import 'package:flutter/material.dart';
class MyWidget extends StatefulWidget {
@override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
final date = MaskedTextController(mask: "00/00/0000");
final money = MoneyMaskedTextController(leftSymbol: "\$", initialValue: 0);
@override
Widget build(BuildContext context) {
return Scaffold(
extendBodyBehindAppBar: true,
resizeToAvoidBottomInset: true,
backgroundColor: Theme.of(context).backgroundColor,
body: SingleChildScrollView(
child: Column(
children: [
TextFormField(controller: date, decoration: InputDecoration(labelText: "Date")),
TextFormField(controller: money, decoration: InputDecoration(labelText: "Money")),
],
),
));
}
}
Thank you!
I think I found the problem, but I still haven't found a way to solve it. I need to implement a way to identify the new cursor position in the mask after changing it.
I've been debugging a little, it seems that the MaskedTextController is detecting every touch as a mask update. I think it will be wiser to detect it by checking for changes in the string itself.
As the mask update, I think that one solution might be getting the cursor position of the previous unmasked text before calling _applyMask. Then, when applying the new mask, count how many new characters are added before the cursor, thus having a new index for the cursor.
Thank you for the help! The changes were released today with version 2.2.0 with only a few variables renamed. Feel free to comment about the changes.
No problem, it was fun to solve this issue. I tried to test as many scenarios as possible in Android, and hope that the behavior persists between platforms. Once I have time again, I will test just to make sure.
About the renames, it got better with your variant, thank you for reviewing!
The same issue with version 2.2.0 on flutter 2.2
I'll take a look in it as soon as possible, for now set the cursorBehavior property to end for some usable behavior.
@fabricio-godoi, @LeandroNovak there is an issue with deleting symbols now (video). My mask: "(000)000-0000".
Also, this is how it works if I set cursorBehavior: CursorBehaviour.end https://user-images.githubusercontent.com/18545029/119382431-ae61e900-bcca-11eb-801a-f0d2cfa6d86e.mov
@Diaglyonok Have you tried the last version 2.2.1? It was uploaded day 23.
I've run the same mask here and all works fine to me.
https://user-images.githubusercontent.com/7767910/119392736-8496cb00-bca6-11eb-917c-ef02f8e26f01.mp4
The only issue I could not solve is that it is not possible to erase the mask if there is some text in the right.
Also, I'm not sure that if the TextEditingController mask is the way to properly add a mask to the text, and suggest to check for some inputFormart alternative if you do not need a dynamic mask (e.g. changing the mask given a parameter such as length or value).
There is another bug with cursor position. If we have mask MaskedTextController(mask: '+100')
and we type 22 cursor will be +12here2 instead of the end of the string. And if we have string +1 and we press backspace cursor will move to the start of the string. That happens because of char 1 is inside of 0 mask char (1-9). Like if we have mask MaskedTextController(mask: '+a00')
cursor behaviour would be normal.
And i think i have a solution. May be i could do a pull request. #16
@Diaglyonok Have you tried the last version 2.2.1? It was uploaded day 23.
I've run the same mask here and all works fine to me.
output_file.mp4 The only issue I could not solve is that it is not possible to erase the mask if there is some text in the right.
Also, I'm not sure that if the TextEditingController mask is the way to properly add a mask to the text, and suggest to check for some inputFormart alternative if you do not need a dynamic mask (e.g. changing the mask given a parameter such as length or value).
@fabricio-godoi Check on iOS please.
Hey guys.
I just created a new PR trying to solve the cursor problem once for all. If anyone could help me to test it out, it would be awesome.
I tried to keep compatibility with Flutter 2.0.0, but it may experience some different behavior in Flutter 2.2.0/2.2.1, since it had some big changes in the TextEditingController.
Check it out: Pull Request
Thanks!
I have some problems:
1) CursorBehaviour.unlocked
:
2) CursorBehaviour.end
(Just can't erase symbols at move cursor manually):
My config
@iksent i made a pull request a month ago that should fix your issue. For some reason there is no release on pub.dev yet. So you could use github link in your pubspec.yaml file like this
extended_masked_text:
git:
url: https://github.com/LeandroNovak/extended_masked_text
Or make your own fork.
I found weird behaviour with the mask on Android (didn't have time to test on iOS yet).
If the user select all the text and type something new, the text field will delete the selected text and add what the user typed, but the cursor will move to the start, instead of being in the end.
Debugging the method [_calculateCursorPosition], I noticed it was returning a negative number, caused by the [unmaskNewChars] being negative (the number of unmasked characters is lower than what's present in the old text).
I fixed it by checking if [unmaskNewChars] is negative, change it to the length of the new unmasked text.
With this change, I can select the text (or part of the text) and replace it, without messing/losing the proper position of the cursor.
I don't know if you need any other validation, so I will add the link to the fix here: Commit
I added a test as well, showing the error here: Commit
masked_text_controller.dart (starting at line 292):
// count how many new characters was added
var unmaskNewChars = newUnmask.length - oldUnmask.length;
if (unmaskNewChars < 0) {
unmaskNewChars = newUnmask.length;
}
I did not test on iOS yet. I can do it sometime later and submit a pull request if you need. Feel free to copy the code from my repo and play with it if you prefer.
To be clear, there are better/more reliable ways to fix this, like checking the text selection and taking it into account in your method instead of just redoing the whole mask, but I don't have the time to do it right now, and this fix is working fine for my need.
Guys, despite this library providing a simple easy way to mask the text, it is conceptually wrong when you look at the way Flutter intends users to use masking features. I strongly suggest taking a look in another package that implements the format method in the inputFormatters
property instead of the controller itself (e.g.: mask_text_input_formatter).
The main reason for that is the Flutter framework itself does not provide the tools to properly calculate the cursor position and updates within the controller. But it can be more easily managed by the inputFormatters
.
I tried my best and wrote a PR to fix the cursor issue in this library, but the cursor inconsistency between platforms and even between Flutter versions was giving me some headaches. In the time, null-safety had just pop-up out, and there were problems when updating from Flutter, 2.0.0, to 2.1.0, etc.
@GuilhermeBrisida I don't know if this fix will resolve for every platform or even every Flutter version, but be aware of it.
Best regards!
@fabricio-godoi I'm aware of that, I just needed a quick dirty fix for a problem I facing in a specific project.
I will take a look at mask_text_input_formatter lib, seems very promissing, thanks for sharing.
As @fabricio-godoi said, it is very hard to properly handle the cursor behavior in a way it works on all platforms. I'm still trying to fix this issue, but can't say when and if I will be able to fix it.
If you don't really need to allow multiple kinds of selection I'd recommend you to lock the cursor to the end, it should work just fine. Otherwise it is better to use an input formatter.
Also, in the next release I was thinking of changing the default behavior from unlocked to end since it is less buggy than the others. At least until I can fix the cursor behavior.
same problem
Greetings,
I'm trying to update de previous library to this one, but I'm getting some behaviors in the 2.1.0 version that I don't know if it is intended.
When typing (both in Android and iOS) I cannot set the cursor to the previous letters with the MaskedTextController. Is there a way to unlock the cursor to be able to put it in the middle of a sentence? I was not able to debug the code to find the reason, but if possible, to put a flag to enable/disable this behavior would be awesome.
Another bug that I found that is coming from the previous library is when it is changing the mask and the cursor is in the middle. Testing the MoneyMaskedTextController I got the cursor to jump back to the end when the mask is changing (when the value goes from 100 to 1000 for instance). It is possible to avoid that cursor flick? I think it is possible to determine from the previous mask where the cursor is, and then update its position based on the new mask.
Best regards!