mirror of
https://github.com/Helium314/HeliBoard.git
synced 2025-06-08 15:47:43 +00:00
Allow for switching between emoji categories using swipe left/right (#1488)
This commit is contained in:
parent
199f177c2d
commit
731c6cdd5e
9 changed files with 217 additions and 252 deletions
|
@ -107,6 +107,7 @@ dependencies {
|
|||
implementation("androidx.core:core-ktx:1.16.0")
|
||||
implementation("androidx.recyclerview:recyclerview:1.4.0")
|
||||
implementation("androidx.autofill:autofill:1.1.0")
|
||||
implementation("androidx.viewpager2:viewpager2:1.1.0")
|
||||
|
||||
// kotlin
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.8.1")
|
||||
|
|
|
@ -479,7 +479,6 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
|
|||
if (mKeyboardViewWrapper.getOneHandedModeEnabled() == enabled) {
|
||||
return;
|
||||
}
|
||||
mEmojiPalettesView.clearKeyboardCache();
|
||||
final Settings settings = Settings.getInstance();
|
||||
mKeyboardViewWrapper.setOneHandedModeEnabled(enabled);
|
||||
mKeyboardViewWrapper.setOneHandedGravity(settings.getCurrent().mOneHandedModeGravity);
|
||||
|
@ -645,6 +644,12 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
|
|||
}
|
||||
}
|
||||
|
||||
public void trimMemory() {
|
||||
if (mEmojiPalettesView != null) {
|
||||
mEmojiPalettesView.clearKeyboardCache();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("InflateParams")
|
||||
public View onCreateInputView(@NonNull Context displayContext, final boolean isHardwareAcceleratedDrawingEnabled) {
|
||||
if (mKeyboardView != null) {
|
||||
|
|
|
@ -261,20 +261,6 @@ final class EmojiCategory {
|
|||
return 0;
|
||||
}
|
||||
|
||||
// Returns the view pager's page position for the categoryId
|
||||
public int getPagerPageIdFromCategoryAndPageId(final int categoryId, final int categoryPageId) {
|
||||
int sum = 0;
|
||||
for (int i = 0; i < mShownCategories.size(); ++i) {
|
||||
final CategoryProperties props = mShownCategories.get(i);
|
||||
if (props.mCategoryId == categoryId) {
|
||||
return sum + categoryPageId;
|
||||
}
|
||||
sum += props.getPageCount();
|
||||
}
|
||||
Log.w(TAG, "categoryId not found: " + categoryId);
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int getRecentTabId() {
|
||||
return getTabIdFromCategoryId(EmojiCategory.ID_RECENTS);
|
||||
}
|
||||
|
@ -285,11 +271,11 @@ final class EmojiCategory {
|
|||
}
|
||||
|
||||
// Returns a keyboard from the recycler view's adapter position.
|
||||
public DynamicGridKeyboard getKeyboardFromAdapterPosition(final int position) {
|
||||
if (position >= 0 && position < getCurrentCategoryPageCount()) {
|
||||
return getKeyboard(mCurrentCategoryId, position);
|
||||
public DynamicGridKeyboard getKeyboardFromAdapterPosition(int categoryId, final int position) {
|
||||
if (position >= 0 && position < getCategoryPageCount(categoryId)) {
|
||||
return getKeyboard(categoryId, position);
|
||||
}
|
||||
Log.w(TAG, "invalid position for categoryId : " + mCurrentCategoryId);
|
||||
Log.w(TAG, "invalid position for categoryId : " + categoryId);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ package helium314.keyboard.keyboard.emoji
|
|||
import android.content.res.Resources
|
||||
import android.view.View
|
||||
import android.widget.LinearLayout
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import helium314.keyboard.keyboard.internal.KeyboardParams
|
||||
import helium314.keyboard.latin.R
|
||||
import helium314.keyboard.latin.settings.Settings
|
||||
|
@ -47,7 +47,7 @@ internal class EmojiLayoutParams(res: Resources) {
|
|||
emojiKeyboardHeight = emojiListHeight - emojiCategoryPageIdViewHeight - emojiListBottomMargin
|
||||
}
|
||||
|
||||
fun setEmojiListProperties(vp: RecyclerView) {
|
||||
fun setEmojiListProperties(vp: ViewPager2) {
|
||||
val lp = vp.layoutParams as LinearLayout.LayoutParams
|
||||
lp.height = emojiKeyboardHeight
|
||||
lp.bottomMargin = emojiListBottomMargin
|
||||
|
|
|
@ -12,156 +12,32 @@ import android.view.LayoutInflater;
|
|||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import helium314.keyboard.keyboard.Key;
|
||||
import helium314.keyboard.keyboard.Keyboard;
|
||||
import helium314.keyboard.keyboard.KeyboardView;
|
||||
import helium314.keyboard.latin.R;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import helium314.keyboard.latin.settings.Settings;
|
||||
|
||||
final class EmojiPalettesAdapter extends RecyclerView.Adapter<EmojiPalettesAdapter.ViewHolder>{
|
||||
private static final String TAG = EmojiPalettesAdapter.class.getSimpleName();
|
||||
private static final boolean DEBUG_PAGER = false;
|
||||
|
||||
private final int mCategoryId;
|
||||
private final OnKeyEventListener mListener;
|
||||
private final DynamicGridKeyboard mRecentsKeyboard;
|
||||
private final SparseArray<EmojiPageKeyboardView> mActiveKeyboardViews = new SparseArray<>();
|
||||
private final EmojiCategory mEmojiCategory;
|
||||
private int mActivePosition = 0;
|
||||
|
||||
public EmojiPalettesAdapter(final EmojiCategory emojiCategory,
|
||||
final OnKeyEventListener listener) {
|
||||
public EmojiPalettesAdapter(final EmojiCategory emojiCategory, int categoryId, final OnKeyEventListener listener) {
|
||||
mEmojiCategory = emojiCategory;
|
||||
mCategoryId = categoryId;
|
||||
mListener = listener;
|
||||
mRecentsKeyboard = mEmojiCategory.getKeyboard(EmojiCategory.ID_RECENTS, 0);
|
||||
}
|
||||
|
||||
public void flushPendingRecentKeys() {
|
||||
mRecentsKeyboard.flushPendingRecentKeys();
|
||||
final KeyboardView recentKeyboardView =
|
||||
mActiveKeyboardViews.get(mEmojiCategory.getRecentTabId());
|
||||
if (recentKeyboardView != null) {
|
||||
recentKeyboardView.invalidateAllKeys();
|
||||
}
|
||||
}
|
||||
|
||||
public void addRecentKey(final Key key) {
|
||||
if (Settings.getValues().mIncognitoModeEnabled) {
|
||||
// We do not want to log recent keys while being in incognito
|
||||
return;
|
||||
}
|
||||
if (mEmojiCategory.isInRecentTab()) {
|
||||
mRecentsKeyboard.addPendingKey(key);
|
||||
return;
|
||||
}
|
||||
mRecentsKeyboard.addKeyFirst(key);
|
||||
final KeyboardView recentKeyboardView =
|
||||
mActiveKeyboardViews.get(mEmojiCategory.getRecentTabId());
|
||||
if (recentKeyboardView != null) {
|
||||
recentKeyboardView.invalidateAllKeys();
|
||||
}
|
||||
}
|
||||
|
||||
public void onPageScrolled() {
|
||||
releaseCurrentKey(false /* withKeyRegistering */);
|
||||
}
|
||||
|
||||
public void releaseCurrentKey(final boolean withKeyRegistering) {
|
||||
// Make sure the delayed key-down event (highlight effect and haptic feedback) will be
|
||||
// canceled.
|
||||
final EmojiPageKeyboardView currentKeyboardView =
|
||||
mActiveKeyboardViews.get(mActivePosition);
|
||||
if (currentKeyboardView == null) {
|
||||
return;
|
||||
}
|
||||
currentKeyboardView.releaseCurrentKey(withKeyRegistering);
|
||||
}
|
||||
|
||||
/*
|
||||
@Override
|
||||
public Object instantiateItem(final ViewGroup container, final int position) {
|
||||
if (DEBUG_PAGER) {
|
||||
Log.d(TAG, "instantiate item: " + position);
|
||||
}
|
||||
final EmojiPageKeyboardView oldKeyboardView = mActiveKeyboardViews.get(position);
|
||||
if (oldKeyboardView != null) {
|
||||
oldKeyboardView.deallocateMemory();
|
||||
// This may be redundant but wanted to be safer..
|
||||
mActiveKeyboardViews.remove(position);
|
||||
}
|
||||
final Keyboard keyboard =
|
||||
mEmojiCategory.getKeyboardFromPagePosition(position);
|
||||
final LayoutInflater inflater = LayoutInflater.from(container.getContext());
|
||||
final EmojiPageKeyboardView keyboardView = (EmojiPageKeyboardView) inflater.inflate(
|
||||
R.layout.emoji_keyboard_page, container, false);
|
||||
keyboardView.setKeyboard(keyboard);
|
||||
keyboardView.setOnKeyEventListener(mListener);
|
||||
container.addView(keyboardView);
|
||||
mActiveKeyboardViews.put(position, keyboardView);
|
||||
return keyboardView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPrimaryItem(final ViewGroup container, final int position,
|
||||
final Object object) {
|
||||
if (mActivePosition == position) {
|
||||
return;
|
||||
}
|
||||
final EmojiPageKeyboardView oldKeyboardView = mActiveKeyboardViews.get(mActivePosition);
|
||||
if (oldKeyboardView != null) {
|
||||
oldKeyboardView.releaseCurrentKey(false);
|
||||
oldKeyboardView.deallocateMemory();
|
||||
}
|
||||
mActivePosition = position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isViewFromObject(final View view, final Object object) {
|
||||
return view == object;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroyItem(final ViewGroup container, final int position,
|
||||
final Object object) {
|
||||
if (DEBUG_PAGER) {
|
||||
Log.d(TAG, "destroy item: " + position + ", " + object.getClass().getSimpleName());
|
||||
}
|
||||
final EmojiPageKeyboardView keyboardView = mActiveKeyboardViews.get(position);
|
||||
if (keyboardView != null) {
|
||||
keyboardView.deallocateMemory();
|
||||
mActiveKeyboardViews.remove(position);
|
||||
}
|
||||
if (object instanceof View) {
|
||||
container.removeView((View)object);
|
||||
} else {
|
||||
Log.w(TAG, "Warning!!! Emoji palette may be leaking. " + object);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
/*if (DEBUG_PAGER) {
|
||||
Log.d(TAG, "instantiate item: " + viewType);
|
||||
}
|
||||
final EmojiPageKeyboardView oldKeyboardView = mActiveKeyboardViews.get(viewType);
|
||||
if (oldKeyboardView != null) {
|
||||
oldKeyboardView.deallocateMemory();
|
||||
// This may be redundant but wanted to be safer..
|
||||
mActiveKeyboardViews.remove(viewType);
|
||||
}
|
||||
final Keyboard keyboard =
|
||||
mEmojiCategory.getKeyboardFromPagePosition(parent.getVerticalScrollbarPosition());*/
|
||||
final LayoutInflater inflater = LayoutInflater.from(parent.getContext());
|
||||
final EmojiPageKeyboardView keyboardView = (EmojiPageKeyboardView)inflater.inflate(
|
||||
R.layout.emoji_keyboard_page, parent, false);
|
||||
/*keyboardView.setKeyboard(keyboard);
|
||||
keyboardView.setOnKeyEventListener(mListener);
|
||||
parent.addView(keyboardView);
|
||||
mActiveKeyboardViews.put(parent.getVerticalScrollbarPosition(), keyboardView);*/
|
||||
return new ViewHolder(keyboardView);
|
||||
}
|
||||
|
||||
|
@ -170,33 +46,22 @@ final class EmojiPalettesAdapter extends RecyclerView.Adapter<EmojiPalettesAdapt
|
|||
if (DEBUG_PAGER) {
|
||||
Log.d(TAG, "instantiate item: " + position);
|
||||
}
|
||||
final EmojiPageKeyboardView oldKeyboardView = mActiveKeyboardViews.get(position);
|
||||
if (oldKeyboardView != null) {
|
||||
oldKeyboardView.deallocateMemory();
|
||||
// This may be redundant but wanted to be safer..
|
||||
mActiveKeyboardViews.remove(position);
|
||||
}
|
||||
|
||||
final Keyboard keyboard =
|
||||
mEmojiCategory.getKeyboardFromAdapterPosition(position);
|
||||
mEmojiCategory.getKeyboardFromAdapterPosition(mCategoryId, position);
|
||||
holder.getKeyboardView().setKeyboard(keyboard);
|
||||
holder.getKeyboardView().setOnKeyEventListener(mListener);
|
||||
//parent.addView(keyboardView);
|
||||
mActiveKeyboardViews.put(position, holder.getKeyboardView());
|
||||
}
|
||||
|
||||
/*if (mActivePosition == position) {
|
||||
return;
|
||||
}
|
||||
final EmojiPageKeyboardView oldKeyboardView = mActiveKeyboardViews.get(mActivePosition);
|
||||
if (oldKeyboardView != null) {
|
||||
oldKeyboardView.releaseCurrentKey(false);
|
||||
oldKeyboardView.deallocateMemory();
|
||||
}
|
||||
mActivePosition = position;*/
|
||||
@Override
|
||||
public void onViewDetachedFromWindow(@NonNull ViewHolder holder) {
|
||||
holder.getKeyboardView().releaseCurrentKey(false);
|
||||
holder.getKeyboardView().deallocateMemory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return mEmojiCategory.getCurrentCategoryPageCount();
|
||||
return mEmojiCategory.getCategoryPageCount(mCategoryId);
|
||||
}
|
||||
|
||||
static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
|
@ -210,7 +75,6 @@ final class EmojiPalettesAdapter extends RecyclerView.Adapter<EmojiPalettesAdapt
|
|||
public EmojiPageKeyboardView getKeyboardView() {
|
||||
return customView;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import android.content.Context;
|
|||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
|
@ -20,6 +21,7 @@ import android.widget.LinearLayout;
|
|||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.viewpager2.widget.ViewPager2;
|
||||
import helium314.keyboard.keyboard.Key;
|
||||
import helium314.keyboard.keyboard.Keyboard;
|
||||
import helium314.keyboard.keyboard.KeyboardActionListener;
|
||||
|
@ -41,8 +43,6 @@ import helium314.keyboard.latin.settings.Settings;
|
|||
import helium314.keyboard.latin.settings.SettingsValues;
|
||||
import helium314.keyboard.latin.utils.ResourceUtils;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import static helium314.keyboard.latin.common.Constants.NOT_A_COORDINATE;
|
||||
|
||||
/**
|
||||
|
@ -58,20 +58,132 @@ import static helium314.keyboard.latin.common.Constants.NOT_A_COORDINATE;
|
|||
*/
|
||||
public final class EmojiPalettesView extends LinearLayout
|
||||
implements View.OnClickListener, OnKeyEventListener {
|
||||
private static final class PagerViewHolder extends RecyclerView.ViewHolder {
|
||||
private long mCategoryId;
|
||||
|
||||
private PagerViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
}
|
||||
}
|
||||
|
||||
private final class PagerAdapter extends RecyclerView.Adapter<PagerViewHolder> {
|
||||
private boolean mInitialized;
|
||||
|
||||
private PagerAdapter() {
|
||||
setHasStableIds(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
|
||||
recyclerView.setItemViewCacheSize(mEmojiCategory.getShownCategories().size());
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public PagerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
var view = LayoutInflater.from(parent.getContext()).inflate(R.layout.emoji_category_view, parent, false);
|
||||
var viewHolder = new PagerViewHolder(view);
|
||||
var emojiRecyclerView = getRecyclerView(view);
|
||||
|
||||
emojiRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
|
||||
@Override
|
||||
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
|
||||
super.onScrollStateChanged(recyclerView, newState);
|
||||
// Ignore this message. Only want the actual page selected.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
|
||||
updateState(recyclerView, viewHolder);
|
||||
}
|
||||
});
|
||||
|
||||
emojiRecyclerView.setPersistentDrawingCache(PERSISTENT_NO_CACHE);
|
||||
return viewHolder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(PagerViewHolder holder, int position) {
|
||||
holder.mCategoryId = getItemId(position);
|
||||
var recyclerView = getRecyclerView(holder.itemView);
|
||||
recyclerView.setAdapter(new EmojiPalettesAdapter(mEmojiCategory, (int) holder.mCategoryId,
|
||||
EmojiPalettesView.this));
|
||||
|
||||
if (! mInitialized) {
|
||||
recyclerView.scrollToPosition(mEmojiCategory.getCurrentCategoryPageId());
|
||||
mInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return mEmojiCategory.getShownCategories().size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewAttachedToWindow(PagerViewHolder holder) {
|
||||
if (mPager.getScrollState() == ViewPager2.SCROLL_STATE_DRAGGING // swipe
|
||||
|| holder.getBindingAdapterPosition() == mPager.getCurrentItem() // tab
|
||||
) {
|
||||
setCurrentCategoryId((int) getItemId(holder.getBindingAdapterPosition()), false);
|
||||
updateState(getRecyclerView(holder.itemView), holder);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewDetachedFromWindow(PagerViewHolder holder) {
|
||||
if (holder.mCategoryId == EmojiCategory.ID_RECENTS) {
|
||||
// Needs to save pending updates for recent keys when we get out of the recents
|
||||
// category because we don't want to move the recent emojis around while the user
|
||||
// is in the recents category.
|
||||
getRecentsKeyboard().flushPendingRecentKeys();
|
||||
getRecyclerView(holder.itemView).getAdapter().notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
return mEmojiCategory.getShownCategories().get(position).mCategoryId;
|
||||
}
|
||||
|
||||
private static RecyclerView getRecyclerView(View view) {
|
||||
return view.findViewById(R.id.emoji_keyboard_list);
|
||||
}
|
||||
|
||||
private void updateState(@NonNull RecyclerView recyclerView, PagerViewHolder viewHolder) {
|
||||
if (viewHolder.mCategoryId != mEmojiCategory.getCurrentCategoryId()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final int offset = recyclerView.computeVerticalScrollOffset();
|
||||
final int extent = recyclerView.computeVerticalScrollExtent();
|
||||
final int range = recyclerView.computeVerticalScrollRange();
|
||||
final float percentage = offset / (float) (range - extent);
|
||||
|
||||
final int currentCategorySize = mEmojiCategory.getCurrentCategoryPageCount();
|
||||
final int a = (int) (percentage * currentCategorySize);
|
||||
final float b = percentage * currentCategorySize - a;
|
||||
mEmojiCategoryPageIndicatorView.setCategoryPageId(currentCategorySize, a, b);
|
||||
|
||||
LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
|
||||
final int firstCompleteVisibleBoard = layoutManager.findFirstCompletelyVisibleItemPosition();
|
||||
final int firstVisibleBoard = layoutManager.findFirstVisibleItemPosition();
|
||||
mEmojiCategory.setCurrentCategoryPageId(
|
||||
firstCompleteVisibleBoard > 0 ? firstCompleteVisibleBoard : firstVisibleBoard);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean initialized = false;
|
||||
private final Colors mColors;
|
||||
private EmojiPalettesAdapter mEmojiPalettesAdapter;
|
||||
private final EmojiLayoutParams mEmojiLayoutParams;
|
||||
private final LinearLayoutManager mEmojiLayoutManager;
|
||||
|
||||
private LinearLayout mTabStrip;
|
||||
private RecyclerView mEmojiRecyclerView;
|
||||
private EmojiCategoryPageIndicatorView mEmojiCategoryPageIndicatorView;
|
||||
|
||||
private KeyboardActionListener mKeyboardActionListener = KeyboardActionListener.EMPTY_LISTENER;
|
||||
|
||||
private final EmojiCategory mEmojiCategory;
|
||||
|
||||
private ViewPager2 mPager;
|
||||
|
||||
public EmojiPalettesView(final Context context, final AttributeSet attrs) {
|
||||
this(context, attrs, R.attr.emojiPalettesViewStyle);
|
||||
|
@ -91,7 +203,6 @@ public final class EmojiPalettesView extends LinearLayout
|
|||
R.styleable.EmojiPalettesView, defStyle, R.style.EmojiPalettesView);
|
||||
mEmojiCategory = new EmojiCategory(context, layoutSet, emojiPalettesViewAttr);
|
||||
emojiPalettesViewAttr.recycle();
|
||||
mEmojiLayoutManager = new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false);
|
||||
setFitsSystemWindows(true);
|
||||
}
|
||||
|
||||
|
@ -129,47 +240,14 @@ public final class EmojiPalettesView extends LinearLayout
|
|||
for (final EmojiCategory.CategoryProperties properties : mEmojiCategory.getShownCategories()) {
|
||||
addTab(mTabStrip, properties.mCategoryId);
|
||||
}
|
||||
mEmojiPalettesAdapter = new EmojiPalettesAdapter(mEmojiCategory, this);
|
||||
|
||||
mEmojiRecyclerView = findViewById(R.id.emoji_keyboard_list);
|
||||
mEmojiRecyclerView.setLayoutManager(mEmojiLayoutManager);
|
||||
mEmojiRecyclerView.setAdapter(mEmojiPalettesAdapter);
|
||||
mEmojiRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
|
||||
@Override
|
||||
public void onScrollStateChanged(@NonNull @NotNull RecyclerView recyclerView, int newState) {
|
||||
super.onScrollStateChanged(recyclerView, newState);
|
||||
// Ignore this message. Only want the actual page selected.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScrolled(@NonNull @NotNull RecyclerView recyclerView, int dx, int dy) {
|
||||
super.onScrolled(recyclerView, dx, dy);
|
||||
mEmojiPalettesAdapter.onPageScrolled();
|
||||
|
||||
final int offset = recyclerView.computeVerticalScrollOffset();
|
||||
final int extent = recyclerView.computeVerticalScrollExtent();
|
||||
final int range = recyclerView.computeVerticalScrollRange();
|
||||
final float percentage = offset / (float) (range - extent);
|
||||
|
||||
final int currentCategorySize = mEmojiCategory.getCurrentCategoryPageCount();
|
||||
final int a = (int) (percentage * currentCategorySize);
|
||||
final float b = percentage * currentCategorySize - a;
|
||||
mEmojiCategoryPageIndicatorView.setCategoryPageId(currentCategorySize, a, b);
|
||||
|
||||
final int firstCompleteVisibleBoard = mEmojiLayoutManager.findFirstCompletelyVisibleItemPosition();
|
||||
final int firstVisibleBoard = mEmojiLayoutManager.findFirstVisibleItemPosition();
|
||||
mEmojiCategory.setCurrentCategoryPageId(
|
||||
firstCompleteVisibleBoard > 0 ? firstCompleteVisibleBoard : firstVisibleBoard);
|
||||
}
|
||||
});
|
||||
|
||||
mEmojiRecyclerView.setPersistentDrawingCache(PERSISTENT_NO_CACHE);
|
||||
mEmojiLayoutParams.setEmojiListProperties(mEmojiRecyclerView);
|
||||
|
||||
mPager = findViewById(R.id.emoji_pager);
|
||||
mPager.setAdapter(new PagerAdapter());
|
||||
mEmojiLayoutParams.setEmojiListProperties(mPager);
|
||||
mEmojiCategoryPageIndicatorView = findViewById(R.id.emoji_category_page_id_view);
|
||||
mEmojiLayoutParams.setCategoryPageIdViewProperties(mEmojiCategoryPageIndicatorView);
|
||||
|
||||
setCurrentCategoryAndPageId(mEmojiCategory.getCurrentCategoryId(), mEmojiCategory.getCurrentCategoryPageId(), true);
|
||||
setCurrentCategoryId(mEmojiCategory.getCurrentCategoryId(), true);
|
||||
|
||||
mEmojiCategoryPageIndicatorView.setColors(mColors.get(ColorType.EMOJI_CATEGORY_SELECTED), mColors.get(ColorType.STRIP_BACKGROUND));
|
||||
initialized = true;
|
||||
|
@ -187,7 +265,7 @@ public final class EmojiPalettesView extends LinearLayout
|
|||
AudioAndHapticFeedbackManager.getInstance().performHapticAndAudioFeedback(KeyCode.NOT_SPECIFIED, this);
|
||||
final int categoryId = ((Long) tag).intValue();
|
||||
if (categoryId != mEmojiCategory.getCurrentCategoryId()) {
|
||||
setCurrentCategoryAndPageId(categoryId, 0, false);
|
||||
setCurrentCategoryId(categoryId, false);
|
||||
updateEmojiCategoryPageIdView();
|
||||
}
|
||||
}
|
||||
|
@ -212,7 +290,7 @@ public final class EmojiPalettesView extends LinearLayout
|
|||
*/
|
||||
@Override
|
||||
public void onReleaseKey(final Key key) {
|
||||
mEmojiPalettesAdapter.addRecentKey(key);
|
||||
addRecentKey(key);
|
||||
final int code = key.getCode();
|
||||
if (code == KeyCode.MULTIPLE_CODE_POINTS) {
|
||||
mKeyboardActionListener.onTextInput(key.getOutputText());
|
||||
|
@ -237,13 +315,22 @@ public final class EmojiPalettesView extends LinearLayout
|
|||
setupBottomRowKeyboard(editorInfo, keyboardActionListener);
|
||||
final KeyDrawParams params = new KeyDrawParams();
|
||||
params.updateParams(mEmojiLayoutParams.getBottomRowKeyboardHeight(), keyVisualAttr);
|
||||
if (mEmojiRecyclerView.getAdapter() == null) {
|
||||
mEmojiRecyclerView.setAdapter(mEmojiPalettesAdapter);
|
||||
setCurrentCategoryAndPageId(mEmojiCategory.getCurrentCategoryId(), mEmojiCategory.getCurrentCategoryPageId(), true);
|
||||
}
|
||||
setupSidePadding();
|
||||
}
|
||||
|
||||
private void addRecentKey(final Key key) {
|
||||
if (Settings.getValues().mIncognitoModeEnabled) {
|
||||
// We do not want to log recent keys while being in incognito
|
||||
return;
|
||||
}
|
||||
if (mEmojiCategory.isInRecentTab()) {
|
||||
getRecentsKeyboard().addPendingKey(key);
|
||||
return;
|
||||
}
|
||||
getRecentsKeyboard().addKeyFirst(key);
|
||||
mPager.getAdapter().notifyItemChanged(mEmojiCategory.getRecentTabId());
|
||||
}
|
||||
|
||||
private void setupBottomRowKeyboard(final EditorInfo editorInfo, final KeyboardActionListener keyboardActionListener) {
|
||||
MainKeyboardView keyboardView = findViewById(R.id.bottom_row_keyboard);
|
||||
keyboardView.setKeyboardActionListener(keyboardActionListener);
|
||||
|
@ -263,11 +350,11 @@ public final class EmojiPalettesView extends LinearLayout
|
|||
final float rightPadding = keyboardAttr.getFraction(R.styleable.Keyboard_keyboardRightPadding,
|
||||
keyboardWidth, keyboardWidth, 0f) * sv.mSidePaddingScale;
|
||||
keyboardAttr.recycle();
|
||||
mEmojiRecyclerView.setPadding(
|
||||
mPager.setPadding(
|
||||
(int) leftPadding,
|
||||
mEmojiRecyclerView.getPaddingTop(),
|
||||
mPager.getPaddingTop(),
|
||||
(int) rightPadding,
|
||||
mEmojiRecyclerView.getPaddingBottom()
|
||||
mPager.getPaddingBottom()
|
||||
);
|
||||
mEmojiCategoryPageIndicatorView.setPadding(
|
||||
(int) leftPadding,
|
||||
|
@ -280,9 +367,11 @@ public final class EmojiPalettesView extends LinearLayout
|
|||
|
||||
public void stopEmojiPalettes() {
|
||||
if (!initialized) return;
|
||||
mEmojiPalettesAdapter.releaseCurrentKey(true);
|
||||
mEmojiPalettesAdapter.flushPendingRecentKeys();
|
||||
mEmojiRecyclerView.setAdapter(null);
|
||||
getRecentsKeyboard().flushPendingRecentKeys();
|
||||
}
|
||||
|
||||
private DynamicGridKeyboard getRecentsKeyboard() {
|
||||
return mEmojiCategory.getKeyboard(EmojiCategory.ID_RECENTS, 0);
|
||||
}
|
||||
|
||||
public void setKeyboardActionListener(final KeyboardActionListener listener) {
|
||||
|
@ -298,34 +387,33 @@ public final class EmojiPalettesView extends LinearLayout
|
|||
mEmojiCategory.getCurrentCategoryPageId(), 0.0f);
|
||||
}
|
||||
|
||||
private void setCurrentCategoryAndPageId(final int categoryId, final int categoryPageId, final boolean force) {
|
||||
private void setCurrentCategoryId(final int categoryId, final boolean initial) {
|
||||
final int oldCategoryId = mEmojiCategory.getCurrentCategoryId();
|
||||
final int oldCategoryPageId = mEmojiCategory.getCurrentCategoryPageId();
|
||||
|
||||
if (oldCategoryId == EmojiCategory.ID_RECENTS && categoryId != EmojiCategory.ID_RECENTS) {
|
||||
// Needs to save pending updates for recent keys when we get out of the recents
|
||||
// category because we don't want to move the recent emojis around while the user
|
||||
// is in the recents category.
|
||||
mEmojiPalettesAdapter.flushPendingRecentKeys();
|
||||
}
|
||||
|
||||
if (force || oldCategoryId != categoryId || oldCategoryPageId != categoryPageId) {
|
||||
if (initial || oldCategoryId != categoryId) {
|
||||
mEmojiCategory.setCurrentCategoryId(categoryId);
|
||||
mEmojiCategory.setCurrentCategoryPageId(categoryPageId);
|
||||
mEmojiPalettesAdapter.notifyDataSetChanged();
|
||||
mEmojiRecyclerView.scrollToPosition(categoryPageId);
|
||||
|
||||
if (mPager.getScrollState() != ViewPager2.SCROLL_STATE_DRAGGING) {
|
||||
// Not swiping
|
||||
mPager.setCurrentItem(mEmojiCategory.getTabIdFromCategoryId(
|
||||
mEmojiCategory.getCurrentCategoryId()), ! initial);
|
||||
}
|
||||
|
||||
final View old = mTabStrip.findViewWithTag((long) oldCategoryId);
|
||||
final View current = mTabStrip.findViewWithTag((long) categoryId);
|
||||
|
||||
if (old instanceof ImageView)
|
||||
Settings.getValues().mColors.setColor((ImageView) old, ColorType.EMOJI_CATEGORY);
|
||||
if (current instanceof ImageView)
|
||||
Settings.getValues().mColors.setColor((ImageView) current, ColorType.EMOJI_CATEGORY_SELECTED);
|
||||
}
|
||||
|
||||
final View old = mTabStrip.findViewWithTag((long) oldCategoryId);
|
||||
final View current = mTabStrip.findViewWithTag((long) categoryId);
|
||||
|
||||
if (old instanceof ImageView)
|
||||
Settings.getValues().mColors.setColor((ImageView) old, ColorType.EMOJI_CATEGORY);
|
||||
if (current instanceof ImageView)
|
||||
Settings.getValues().mColors.setColor((ImageView) current, ColorType.EMOJI_CATEGORY_SELECTED);
|
||||
}
|
||||
|
||||
public void clearKeyboardCache() {
|
||||
if (!initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
mEmojiCategory.clearKeyboardCache();
|
||||
mPager.getAdapter().notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2022,8 +2022,10 @@ public class LatinIME extends InputMethodService implements
|
|||
public void onTrimMemory(int level) {
|
||||
super.onTrimMemory(level);
|
||||
switch (level) {
|
||||
case TRIM_MEMORY_RUNNING_LOW, TRIM_MEMORY_RUNNING_CRITICAL, TRIM_MEMORY_COMPLETE ->
|
||||
KeyboardLayoutSet.onSystemLocaleChanged(); // clears caches, nothing else
|
||||
case TRIM_MEMORY_RUNNING_LOW, TRIM_MEMORY_RUNNING_CRITICAL, TRIM_MEMORY_COMPLETE -> {
|
||||
KeyboardLayoutSet.onSystemLocaleChanged(); // clears caches, nothing else
|
||||
mKeyboardSwitcher.trimMemory();
|
||||
}
|
||||
// deallocateMemory always called on hiding, and should not be called when showing
|
||||
}
|
||||
}
|
||||
|
|
20
app/src/main/res/layout/emoji_category_view.xml
Normal file
20
app/src/main/res/layout/emoji_category_view.xml
Normal file
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2013 The Android Open Source Project
|
||||
modified
|
||||
SPDX-License-Identifier: Apache-2.0 AND GPL-3.0-only
|
||||
-->
|
||||
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@android:color/transparent"
|
||||
style="?attr/emojiPalettesViewStyle">
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/emoji_keyboard_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
android:orientation="vertical" />
|
||||
</FrameLayout>
|
|
@ -15,11 +15,10 @@
|
|||
android:background="@android:color/transparent"
|
||||
style="?attr/emojiPalettesViewStyle"
|
||||
>
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/emoji_keyboard_list"
|
||||
<androidx.viewpager2.widget.ViewPager2
|
||||
android:id="@+id/emoji_pager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical" />
|
||||
android:layout_height="wrap_content" />
|
||||
<helium314.keyboard.keyboard.emoji.EmojiCategoryPageIndicatorView
|
||||
android:id="@+id/emoji_category_page_id_view"
|
||||
android:layout_width="match_parent"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue