New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix cursor moving back and missing characters #2537
base: master
Are you sure you want to change the base?
Conversation
This, however, has a side effect (which existed earlier as well but was overlooked because of cursor resetting) of missing some characters when typing too fast. Solving this will require more effort. I can think of a solution which will involve detecting "user has stopped typing". Something like this - stackoverflow. Let me know if you want to fix this as well. Will raise a separate issue for this. Alternative: Use RxBindings or do some backpressure solutioning to handle all character inputs from user. But this will need a more complex handling - like "not updating the EditText until upstream processing (handleInput) is complete". |
@jingtang10 what are your thoughts on this? |
I made an attempt at solving the "side effect" as well. Seems good to me but Idk if this behaviour - "detect user has stopped typing" can have any other side effects. Only difficulty is to test this as racing conditions are always a pain to test. Can you try testing this PR ? |
Thanks for all your work on this @MJ1998. @FikriMilano will test the PR tomorrow and we'll get back to you. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @MJ1998, I like your first idea and it's working, in a nutshell -> only apply new answer to questionnaireViewItem after user stops typing for 0.5 second, if there are more inputs coming in, the answer won't be applied since the timer is canceled.
Not sure if it's worth it to introduce RxBinding right now.
override fun afterTextChanged(editable: Editable?) {
timer?.cancel()
// If editable has become empty or this is the first character then invoke afterTextChanged
// instantly else start a timer for user to finish typing
if (editable?.toString().isNullOrEmpty() || firstCharacter) {
Log.d("FIKRI1", "$editable")
afterTextChanged(editable?.toString())
} else {
// countDownInterval is simply kept greater than delay as we don't need onTick
timer =
object : CountDownTimer(delay, delay * 2) {
override fun onTick(millisUntilFinished: Long) {}
override fun onFinish() {
Log.d("FIKRI2", "$editable")
afterTextChanged(editable?.toString())
}
}
.start()
}
}
2024-05-09 11:24:26.372 2316-2316 FIKRI1 com.google.android.fhir.catalog D
2024-05-09 11:24:27.912 2316-2316 FIKRI1 com.google.android.fhir.catalog D a
2024-05-09 11:24:30.037 2316-2316 FIKRI2 com.google.android.fhir.catalog D aa
2024-05-09 11:24:35.997 2316-2316 FIKRI2 com.google.android.fhir.catalog D aaqwertqwertqwertqwertqwert
qwerty.webm
Just FYI an elaboration on how I am testing this:- You can observe some characters being missed before the last commit if you test like this. @FikriMilano In actual case the upstream function can take more time to finish (for example, resolving fhir query) - which makes characters missing clearly visible. |
Regarding your question on RxBinding, I think its a much bigger effort as we dont use simple TextView or EditText views, rather its a EditTextInputLayout which offers more features like validation, header views along with it. So moving from EditTextInputLayout to RxBinding views will be difficult. |
@MJ1998 I agree, we can keep it this way for now |
@MJ1998 this fix you shared is working great. Thank you for prioritising this and getting it resolved so quickly! |
@MJ1998 upon further testing, the issue of the missing characters is significantly affecting the data entry. Missing.letters.bug.webmCan we please go back to the drawing board on this? |
Is this issue happening on this PR? |
@MJ1998 yes it is. |
Gotcha. I had a feeling this will introduce more side effects. |
@MJ1998 there's none, it's just a normal text field |
IMPORTANT: All PRs must be linked to an issue (except for extremely trivial and straightforward changes).
Fixes #1914
Cause of the issue: The EditText temporarily contains an extra character. The TextWatcher gets removed (here) before it can process this extra character, leaving the saved text state (in QuestionnaireViewItem) inconsistent with the actual EditText content. This inconsistency triggers a UI update using EditText#setText (here), which unintentionally resets the cursor position to the beginning.
EditText#append moves the cursor to the last position.
Read comments in rest of the PR for more details.
Description
Clear and concise code change description.
Alternative(s) considered
Have you considered any alternatives? And if so, why have you chosen the approach in this PR?
Type
Choose one: (Bug fix | Feature | Documentation | Testing | Code health | Builds | Releases | Other)
Screenshots (if applicable)
Checklist
./gradlew spotlessApply
and./gradlew spotlessCheck
to check my code follows the style guide of this project../gradlew check
and./gradlew connectedCheck
to test my changes locally.