From 4dce95142f89a7166b370f91a34aae54717a6ab3 Mon Sep 17 00:00:00 2001 From: Jake McGinty Date: Sat, 30 May 2015 23:52:41 -0700 Subject: [PATCH] fix emoji not being replaced with Editable actions Fixes #3267 Closes #3292 // FREEBIE --- .../components/emoji/EmojiEditText.java | 29 +++++++++-------- .../components/emoji/EmojiFilter.java | 32 +++++++++++++++++++ .../components/emoji/EmojiProvider.java | 6 ++-- .../components/emoji/EmojiTextView.java | 20 ++++++------ .../emoji/PostInvalidateCallback.java | 31 ------------------ 5 files changed, 62 insertions(+), 56 deletions(-) create mode 100644 src/org/thoughtcrime/securesms/components/emoji/EmojiFilter.java delete mode 100644 src/org/thoughtcrime/securesms/components/emoji/PostInvalidateCallback.java diff --git a/src/org/thoughtcrime/securesms/components/emoji/EmojiEditText.java b/src/org/thoughtcrime/securesms/components/emoji/EmojiEditText.java index ccffb2dfd2..2bf9d0ef3c 100644 --- a/src/org/thoughtcrime/securesms/components/emoji/EmojiEditText.java +++ b/src/org/thoughtcrime/securesms/components/emoji/EmojiEditText.java @@ -1,39 +1,42 @@ package org.thoughtcrime.securesms.components.emoji; import android.content.Context; -import android.graphics.drawable.Drawable.Callback; +import android.graphics.drawable.Drawable; +import android.support.annotation.NonNull; import android.support.v7.widget.AppCompatEditText; +import android.text.InputFilter; import android.util.AttributeSet; +import org.thoughtcrime.securesms.R; +import org.thoughtcrime.securesms.components.emoji.EmojiProvider.EmojiDrawable; + public class EmojiEditText extends AppCompatEditText { - private final Callback callback = new PostInvalidateCallback(this); + private static final String TAG = EmojiEditText.class.getSimpleName(); public EmojiEditText(Context context) { - super(context); + this(context, null); } public EmojiEditText(Context context, AttributeSet attrs) { - super(context, attrs); + this(context, attrs, R.attr.editTextStyle); } public EmojiEditText(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); - } - - @Override public void setText(CharSequence text, BufferType type) { - super.setText(EmojiProvider.getInstance(getContext()).emojify(text, EmojiProvider.EMOJI_SMALL, callback), - BufferType.SPANNABLE); + setFilters(new InputFilter[]{ new EmojiFilter(this) }); } public void insertEmoji(String emoji) { final int start = getSelectionStart(); final int end = getSelectionEnd(); - final CharSequence text = EmojiProvider.getInstance(getContext()).emojify(emoji, - EmojiProvider.EMOJI_SMALL, - callback); - getText().replace(Math.min(start, end), Math.max(start, end), text); + getText().replace(Math.min(start, end), Math.max(start, end), emoji); setSelection(end + emoji.length()); } + + @Override public void invalidateDrawable(@NonNull Drawable drawable) { + if (drawable instanceof EmojiDrawable) invalidate(); + else super.invalidateDrawable(drawable); + } } diff --git a/src/org/thoughtcrime/securesms/components/emoji/EmojiFilter.java b/src/org/thoughtcrime/securesms/components/emoji/EmojiFilter.java new file mode 100644 index 0000000000..67d8344a4d --- /dev/null +++ b/src/org/thoughtcrime/securesms/components/emoji/EmojiFilter.java @@ -0,0 +1,32 @@ +package org.thoughtcrime.securesms.components.emoji; + +import android.content.Context; +import android.text.InputFilter; +import android.text.Spannable; +import android.text.Spanned; +import android.text.TextUtils; +import android.view.View; +import android.widget.TextView; + +/** + * Created by kaonashi on 6/1/15. + */ +public class EmojiFilter implements InputFilter { + private View view; + + public EmojiFilter(TextView view) { + this.view = view; + } + + @Override public CharSequence filter(CharSequence source, int start, int end, + Spanned dest, int dstart, int dend) + { + char[] v = new char[end - start]; + TextUtils.getChars(source, start, end, v, 0); + Spannable emojified = EmojiProvider.getInstance(view.getContext()).emojify(new String(v), view); + if (source instanceof Spanned) { + TextUtils.copySpansFrom((Spanned) source, start, end, null, emojified, 0); + } + return emojified; + } +} diff --git a/src/org/thoughtcrime/securesms/components/emoji/EmojiProvider.java b/src/org/thoughtcrime/securesms/components/emoji/EmojiProvider.java index 39ab34cf29..3472010bbf 100644 --- a/src/org/thoughtcrime/securesms/components/emoji/EmojiProvider.java +++ b/src/org/thoughtcrime/securesms/components/emoji/EmojiProvider.java @@ -45,7 +45,7 @@ public class EmojiProvider { private static final Pattern EMOJI_RANGE = Pattern.compile("[\\u20a0-\\u32ff\\ud83c\\udc00-\\ud83d\\udeff\\udbb9\\udce5-\\udbb9\\udcee]"); public static final double EMOJI_FULL = 1.00; - public static final double EMOJI_SMALL = 0.50; + public static final double EMOJI_SMALL = 0.60; public static final int EMOJI_RAW_HEIGHT = 96; public static final int EMOJI_RAW_WIDTH = 102; public static final int EMOJI_VERT_PAD = 6; @@ -84,13 +84,13 @@ public class EmojiProvider { } } - public CharSequence emojify(CharSequence text, double size, Callback callback) { + public Spannable emojify(CharSequence text, Callback callback) { Matcher matches = EMOJI_RANGE.matcher(text); SpannableStringBuilder builder = new SpannableStringBuilder(text); while (matches.find()) { int codePoint = matches.group().codePointAt(0); - Drawable drawable = getEmojiDrawable(codePoint, size); + Drawable drawable = getEmojiDrawable(codePoint, EMOJI_SMALL); if (drawable != null) { builder.setSpan(new InvalidatingDrawableSpan(drawable, callback), matches.start(), matches.end(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); diff --git a/src/org/thoughtcrime/securesms/components/emoji/EmojiTextView.java b/src/org/thoughtcrime/securesms/components/emoji/EmojiTextView.java index 39633fdb2b..47cebbdfd9 100644 --- a/src/org/thoughtcrime/securesms/components/emoji/EmojiTextView.java +++ b/src/org/thoughtcrime/securesms/components/emoji/EmojiTextView.java @@ -1,29 +1,31 @@ package org.thoughtcrime.securesms.components.emoji; import android.content.Context; -import android.graphics.drawable.Drawable.Callback; +import android.graphics.drawable.Drawable; +import android.support.annotation.NonNull; import android.support.v7.widget.AppCompatTextView; +import android.text.InputFilter; import android.util.AttributeSet; +import org.thoughtcrime.securesms.components.emoji.EmojiProvider.EmojiDrawable; + public class EmojiTextView extends AppCompatTextView { - private final Callback callback = new PostInvalidateCallback(this); public EmojiTextView(Context context) { - super(context); + this(context, null); } public EmojiTextView(Context context, AttributeSet attrs) { - super(context, attrs); + this(context, attrs, 0); } public EmojiTextView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); + setFilters(new InputFilter[]{ new EmojiFilter(this) }); } - @Override public void setText(CharSequence text, BufferType type) { - super.setText(EmojiProvider.getInstance(getContext()).emojify(text, - EmojiProvider.EMOJI_SMALL, - callback), - BufferType.SPANNABLE); + @Override public void invalidateDrawable(@NonNull Drawable drawable) { + if (drawable instanceof EmojiDrawable) invalidate(); + else super.invalidateDrawable(drawable); } } diff --git a/src/org/thoughtcrime/securesms/components/emoji/PostInvalidateCallback.java b/src/org/thoughtcrime/securesms/components/emoji/PostInvalidateCallback.java deleted file mode 100644 index bb661afee8..0000000000 --- a/src/org/thoughtcrime/securesms/components/emoji/PostInvalidateCallback.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.thoughtcrime.securesms.components.emoji; - -import android.graphics.drawable.Drawable; -import android.graphics.drawable.Drawable.Callback; -import android.view.View; - -import org.thoughtcrime.securesms.util.Util; - -public class PostInvalidateCallback implements Callback { - private final View view; - - public PostInvalidateCallback(View view) { - this.view = view; - } - - @Override public void invalidateDrawable(Drawable who) { - Util.runOnMain(new Runnable() { - @Override public void run() { - view.invalidate(); - } - }); - } - - @Override public void scheduleDrawable(Drawable who, Runnable what, long when) { - - } - - @Override public void unscheduleDrawable(Drawable who, Runnable what) { - - } -}