I have a custom view for editing image and I need to add new feature which will be set text on this Image. This is my code to handle input events inside this view:
private val inputMethodManager by lazy {
context.getSystemService(Activity.INPUT_METHOD_SERVICE) as? InputMethodManager
}
private var mEditable = SpannableStringBuilder("")
private var text: String = ""
private val mMyTextWatcher = object : TextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
text = s.toString()
Log.d("DEBUG", "Text length: ${text.length}")
invalidate()
}
override fun afterTextChanged(s: Editable?) {}
}
init {
isFocusableInTouchMode = true
isFocusable = true
isSaveEnabled = true
setupEditable()
setupKeyboardListener()
}
override fun onCreateInputConnection(outAttrs: EditorInfo): InputConnection {
outAttrs.apply {
inputType = InputType.TYPE_CLASS_TEXT
imeOptions = EditorInfo.IME_ACTION_UNSPECIFIED
initialSelStart = mEditable.length
initialSelEnd = mEditable.length
}
return object : BaseInputConnection(this, true) {
override fun getEditable(): Editable {
return mEditable
}
}
}
override fun onCheckIsTextEditor(): Boolean {
return true
}
private fun showKeyboard() {
try {
requestFocus()
inputMethodManager?.apply {
updateSelection(this@ImageEditorView, 0, mEditable.length, -1, MAX_CHARACTER_NUM)
showSoftInput(this@ImageEditorView, InputMethodManager.SHOW_IMPLICIT)
}
} catch (e: Exception) {
e.printStackTrace()
}
}
private fun hideKeyboard() {
clearFocus()
inputMethodManager?.hideSoftInputFromWindow(
windowToken,
InputMethodManager.SHOW_IMPLICIT
)
}
private fun setupEditable() {
mEditable = SpannableStringBuilder(text)
Selection.setSelection(mEditable, mEditable.length)
mEditable.setSpan(mMyTextWatcher, 0, mEditable.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
mEditable.filters = mEditable.filters.toMutableList().apply {
add(InputFilter.LengthFilter(MAX_CHARACTER_NUM))
}.toTypedArray()
}
Text editing works fine, but I need to set max text length and LengthFilter don't work properly. For example, I have entered 200 symbols and max length is 160. SpannableStringBuilder still have 200 symbols but returns to textwatcher only 160. And when I try to delete text from the end, it start deleting from all 200 symbols and I cant see cursor until 160 symbols left.
How to set max length correctly and restrict enter more symbols?
I also tried this delete LengthFilter and add this code to TextWatcher:
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
if (s != null && s.length > MAX_CHARACTER_NUM) {
text = s.subSequence(0, MAX_CHARACTER_NUM).toString()
setupEditable()
inputMethodManager?.restartInput(this@ImageEditorView)
} else {
text = s.toString()
}
Log.d("DEBUG", "Text length: ${text.length}")
invalidate()
}
It works better? but on Android 8 it make bug:
- enter max length text
- hide keyboard
- open keyboard
- try to delete text
Text don't deleted and returns this warning:
[ANR Warning]Input routeing takes more than 6000ms since 2023-06-26 12:57:34.128, this = com.mediatek.view.impl.ViewDebugManagerImpl@4f786bb
Input event delivered to android.view.ViewRootImpl$SyntheticInputStage@e12fbc0 at 2023-06-26 12:57:40.662
Input event delivered to android.view.ViewRootImpl$EarlyPostImeInputStage@29821fd at 2023-06-26 12:57:40.661
Input event delivered to android.view.ViewRootImpl$NativePostImeInputStage@bcfbef2 at 2023-06-26 12:57:40.661
Input event delivered to android.view.ViewRootImpl$ViewPostImeInputStage@4ce3943 at 2023-06-26 12:57:40.661