| /* |
| * Copyright 2021 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package androidx.emoji2.helpers; |
| |
| import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX; |
| |
| import android.text.Editable; |
| import android.text.Selection; |
| import android.text.Spannable; |
| import android.widget.EditText; |
| |
| import androidx.annotation.RequiresApi; |
| import androidx.annotation.RestrictTo; |
| import androidx.emoji2.text.EmojiCompat; |
| import androidx.emoji2.text.EmojiCompat.InitCallback; |
| import androidx.emoji2.text.EmojiDefaults; |
| |
| import java.lang.ref.Reference; |
| import java.lang.ref.WeakReference; |
| |
| /** |
| * TextWatcher used for an EditText. |
| * |
| * @hide |
| */ |
| @RestrictTo(LIBRARY_GROUP_PREFIX) |
| @RequiresApi(19) |
| final class EmojiTextWatcher implements android.text.TextWatcher { |
| private final EditText mEditText; |
| private InitCallback mInitCallback; |
| private int mMaxEmojiCount = EmojiDefaults.MAX_EMOJI_COUNT; |
| @EmojiCompat.ReplaceStrategy |
| private int mEmojiReplaceStrategy = EmojiCompat.REPLACE_STRATEGY_DEFAULT; |
| |
| EmojiTextWatcher(EditText editText) { |
| mEditText = editText; |
| } |
| |
| void setMaxEmojiCount(int maxEmojiCount) { |
| this.mMaxEmojiCount = maxEmojiCount; |
| } |
| |
| int getMaxEmojiCount() { |
| return mMaxEmojiCount; |
| } |
| |
| @EmojiCompat.ReplaceStrategy int getEmojiReplaceStrategy() { |
| return mEmojiReplaceStrategy; |
| } |
| |
| void setEmojiReplaceStrategy(@EmojiCompat.ReplaceStrategy int replaceStrategy) { |
| mEmojiReplaceStrategy = replaceStrategy; |
| } |
| |
| @Override |
| public void onTextChanged(CharSequence charSequence, final int start, final int before, |
| final int after) { |
| if (mEditText.isInEditMode()) { |
| return; |
| } |
| |
| //before > after --> a deletion occurred |
| if (before <= after && charSequence instanceof Spannable) { |
| switch (EmojiCompat.get().getLoadState()){ |
| case EmojiCompat.LOAD_STATE_SUCCEEDED: |
| final Spannable s = (Spannable) charSequence; |
| EmojiCompat.get().process(s, start, start + after, mMaxEmojiCount, |
| mEmojiReplaceStrategy); |
| break; |
| case EmojiCompat.LOAD_STATE_LOADING: |
| case EmojiCompat.LOAD_STATE_DEFAULT: |
| EmojiCompat.get().registerInitCallback(getInitCallback()); |
| break; |
| case EmojiCompat.LOAD_STATE_FAILED: |
| default: |
| break; |
| } |
| } |
| } |
| |
| @Override |
| public void beforeTextChanged(CharSequence s, int start, int count, int after) { |
| // do nothing |
| } |
| |
| @Override |
| public void afterTextChanged(Editable s) { |
| // do nothing |
| } |
| |
| private InitCallback getInitCallback() { |
| if (mInitCallback == null) { |
| mInitCallback = new InitCallbackImpl(mEditText); |
| } |
| return mInitCallback; |
| } |
| |
| @RequiresApi(19) |
| private static class InitCallbackImpl extends InitCallback { |
| private final Reference<EditText> mViewRef; |
| |
| InitCallbackImpl(EditText editText) { |
| mViewRef = new WeakReference<>(editText); |
| } |
| |
| @Override |
| public void onInitialized() { |
| super.onInitialized(); |
| final EditText editText = mViewRef.get(); |
| if (editText != null && editText.isAttachedToWindow()) { |
| final Editable text = editText.getEditableText(); |
| |
| final int selectionStart = Selection.getSelectionStart(text); |
| final int selectionEnd = Selection.getSelectionEnd(text); |
| |
| EmojiCompat.get().process(text); |
| |
| EmojiInputFilter.updateSelection(text, selectionStart, selectionEnd); |
| } |
| } |
| } |
| } |