1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.inputmethod.keyboard.emoji; 18 19 import androidx.viewpager.widget.PagerAdapter; 20 import android.util.Log; 21 import android.util.SparseArray; 22 import android.view.LayoutInflater; 23 import android.view.View; 24 import android.view.ViewGroup; 25 26 import com.android.inputmethod.keyboard.Key; 27 import com.android.inputmethod.keyboard.Keyboard; 28 import com.android.inputmethod.keyboard.KeyboardView; 29 import com.android.inputmethod.latin.R; 30 31 final class EmojiPalettesAdapter extends PagerAdapter { 32 private static final String TAG = EmojiPalettesAdapter.class.getSimpleName(); 33 private static final boolean DEBUG_PAGER = false; 34 35 private final EmojiPageKeyboardView.OnKeyEventListener mListener; 36 private final DynamicGridKeyboard mRecentsKeyboard; 37 private final SparseArray<EmojiPageKeyboardView> mActiveKeyboardViews = new SparseArray<>(); 38 private final EmojiCategory mEmojiCategory; 39 private int mActivePosition = 0; 40 EmojiPalettesAdapter(final EmojiCategory emojiCategory, final EmojiPageKeyboardView.OnKeyEventListener listener)41 public EmojiPalettesAdapter(final EmojiCategory emojiCategory, 42 final EmojiPageKeyboardView.OnKeyEventListener listener) { 43 mEmojiCategory = emojiCategory; 44 mListener = listener; 45 mRecentsKeyboard = mEmojiCategory.getKeyboard(EmojiCategory.ID_RECENTS, 0); 46 } 47 flushPendingRecentKeys()48 public void flushPendingRecentKeys() { 49 mRecentsKeyboard.flushPendingRecentKeys(); 50 final KeyboardView recentKeyboardView = 51 mActiveKeyboardViews.get(mEmojiCategory.getRecentTabId()); 52 if (recentKeyboardView != null) { 53 recentKeyboardView.invalidateAllKeys(); 54 } 55 } 56 addRecentKey(final Key key)57 public void addRecentKey(final Key key) { 58 if (mEmojiCategory.isInRecentTab()) { 59 mRecentsKeyboard.addPendingKey(key); 60 return; 61 } 62 mRecentsKeyboard.addKeyFirst(key); 63 final KeyboardView recentKeyboardView = 64 mActiveKeyboardViews.get(mEmojiCategory.getRecentTabId()); 65 if (recentKeyboardView != null) { 66 recentKeyboardView.invalidateAllKeys(); 67 } 68 } 69 onPageScrolled()70 public void onPageScrolled() { 71 releaseCurrentKey(false /* withKeyRegistering */); 72 } 73 releaseCurrentKey(final boolean withKeyRegistering)74 public void releaseCurrentKey(final boolean withKeyRegistering) { 75 // Make sure the delayed key-down event (highlight effect and haptic feedback) will be 76 // canceled. 77 final EmojiPageKeyboardView currentKeyboardView = 78 mActiveKeyboardViews.get(mActivePosition); 79 if (currentKeyboardView == null) { 80 return; 81 } 82 currentKeyboardView.releaseCurrentKey(withKeyRegistering); 83 } 84 85 @Override getCount()86 public int getCount() { 87 return mEmojiCategory.getTotalPageCountOfAllCategories(); 88 } 89 90 @Override setPrimaryItem(final ViewGroup container, final int position, final Object object)91 public void setPrimaryItem(final ViewGroup container, final int position, 92 final Object object) { 93 if (mActivePosition == position) { 94 return; 95 } 96 final EmojiPageKeyboardView oldKeyboardView = mActiveKeyboardViews.get(mActivePosition); 97 if (oldKeyboardView != null) { 98 oldKeyboardView.releaseCurrentKey(false /* withKeyRegistering */); 99 oldKeyboardView.deallocateMemory(); 100 } 101 mActivePosition = position; 102 } 103 104 @Override instantiateItem(final ViewGroup container, final int position)105 public Object instantiateItem(final ViewGroup container, final int position) { 106 if (DEBUG_PAGER) { 107 Log.d(TAG, "instantiate item: " + position); 108 } 109 final EmojiPageKeyboardView oldKeyboardView = mActiveKeyboardViews.get(position); 110 if (oldKeyboardView != null) { 111 oldKeyboardView.deallocateMemory(); 112 // This may be redundant but wanted to be safer.. 113 mActiveKeyboardViews.remove(position); 114 } 115 final Keyboard keyboard = 116 mEmojiCategory.getKeyboardFromPagePosition(position); 117 final LayoutInflater inflater = LayoutInflater.from(container.getContext()); 118 final EmojiPageKeyboardView keyboardView = (EmojiPageKeyboardView)inflater.inflate( 119 R.layout.emoji_keyboard_page, container, false /* attachToRoot */); 120 keyboardView.setKeyboard(keyboard); 121 keyboardView.setOnKeyEventListener(mListener); 122 container.addView(keyboardView); 123 mActiveKeyboardViews.put(position, keyboardView); 124 return keyboardView; 125 } 126 127 @Override isViewFromObject(final View view, final Object object)128 public boolean isViewFromObject(final View view, final Object object) { 129 return view == object; 130 } 131 132 @Override destroyItem(final ViewGroup container, final int position, final Object object)133 public void destroyItem(final ViewGroup container, final int position, 134 final Object object) { 135 if (DEBUG_PAGER) { 136 Log.d(TAG, "destroy item: " + position + ", " + object.getClass().getSimpleName()); 137 } 138 final EmojiPageKeyboardView keyboardView = mActiveKeyboardViews.get(position); 139 if (keyboardView != null) { 140 keyboardView.deallocateMemory(); 141 mActiveKeyboardViews.remove(position); 142 } 143 if (object instanceof View) { 144 container.removeView((View)object); 145 } else { 146 Log.w(TAG, "Warning!!! Emoji palette may be leaking. " + object); 147 } 148 } 149 } 150