So, the decision to add a picture inside EditText and so that the keyboard does not jump was this:
- Set the tag via setText and remember it.
- With the following entries, we look, if the tag has not changed - do not use setText. Then the keyboards do not switch (the input completion method is not called) and everything works correctly.
- When the tag changes, remove Spannable and reinstall them.
In the examples below you can see how a) Clean outdated spans b) Create an ImageSpan (in this case make a picture out of text) c) Install a picture - text inside EditText
Hope this helps someone.
/** * Clean the formatting of the string. * * @param editable text which has spannable format */ private void removeOldSpans(Editable editable){ Object[] spans = editable.getSpans(0, editable.toString().length(), Object.class); for (Object span : spans) { if (span instanceof ImageSpan) { editable.removeSpan(span); } } }
/** * Setting formats to tags. * * @param startTag a first tag in the string * @param endTag a last tag in the string * @param editable the string with text */ public void setTagSpans(String startTag, String endTag, Editable editable) { oldStartTag = startTag; oldEndTag = endTag; removeTextChangedListener(tw); //disable listener String currentText = editable.toString(); //remove old span removeOldSpans(editable); //create new span SpannableString spannableString = new SpannableString(editable); if (!TextUtils.isEmpty(startTag) && TextUtils.isEmpty(endTag)) { //we have only first tag final ImageSpan startTagSpan = getChipsSpan(startTag); spannableString.setSpan(startTagSpan, 0, startTag.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } else if (TextUtils.isEmpty(startTag) && !TextUtils.isEmpty(endTag)) { //we have only last tag final ImageSpan endTagSpan = getChipsSpan(endTag); int last = currentText.lastIndexOf("#"); spannableString.setSpan(endTagSpan, last, currentText.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } else if (!TextUtils.isEmpty(startTag) && !TextUtils.isEmpty(endTag)) { //we have both tags at the same time final ImageSpan startTagSpan = getChipsSpan(startTag); final ImageSpan endTagSpan = getChipsSpan(endTag); int last = currentText.lastIndexOf("#"); spannableString.setSpan(startTagSpan, 0, startTag.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); spannableString.setSpan(endTagSpan, last, currentText.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } setText(spannableString, BufferType.SPANNABLE); forceSetCursorPosition = spannableString.length(); setSelection(forceSetCursorPosition); addTextChangedListener(tw); } /** * Format the tag from a text into an image span. * * @param tag text * @return text which has been formatted into an image span */ private ImageSpan getChipsSpan(String tag) { //Build chips view final TextViewFontExt textViewFontExt = new TextViewFontExt(getContext()); textViewFontExt.setTypeface(Helper.Fonts.getTypeface(getContext(), "fonts/Roboto-Medium.ttf")); textViewFontExt.setLayoutParams( new LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)); textViewFontExt.setText(tag); textViewFontExt.setTextSize(getResources().getDimension(R.dimen.chats_chips_span_text_size)); textViewFontExt.setTextColor(getResources().getColor(android.R.color.white)); textViewFontExt.setPadding( (int)getResources().getDimension(R.dimen.chats_chips_span_padding_lr), (int)getResources().getDimension(R.dimen.chats_chips_span_padding_top), (int)getResources().getDimension(R.dimen.chats_chips_span_padding_lr), (int)getResources().getDimension(R.dimen.chats_chips_span_padding_bottom)); Drawable tagBackground; if(Build.VERSION.SDK_INT < 21) { tagBackground = getResources().getDrawable(R.drawable.tag_input_background); } else { tagBackground = getResources().getDrawable(R.drawable.tag_input_background, null); } if(Build.VERSION.SDK_INT < 16) { textViewFontExt.setBackgroundDrawable(tagBackground); } else { textViewFontExt.setBackground(tagBackground); } //Build chips bitmap int spec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); textViewFontExt.measure(spec, spec); textViewFontExt.layout(0, 0, textViewFontExt.getMeasuredWidth(), textViewFontExt.getMeasuredHeight()); Bitmap bitmap = Bitmap.createBitmap(textViewFontExt.getWidth(), textViewFontExt.getHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); canvas.translate(-textViewFontExt.getScrollX(), -textViewFontExt.getScrollY()); textViewFontExt.draw(canvas); textViewFontExt.setDrawingCacheEnabled(true); Bitmap cacheBitmap = textViewFontExt.getDrawingCache(); Bitmap tagBitmap = cacheBitmap.copy(Bitmap.Config.ARGB_8888, true); BitmapDrawable bitmapDrawable = new BitmapDrawable(getResources(), tagBitmap); bitmapDrawable.setBounds(0, 0, bitmapDrawable.getIntrinsicWidth(), bitmapDrawable.getIntrinsicHeight()); //Cleanup textViewFontExt.destroyDrawingCache(); bitmap.recycle(); cacheBitmap.recycle(); return new ImageSpan(bitmapDrawable); }