diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/compat/TabHostCompat.java b/app/src/main/java/org/dslul/openboard/inputmethod/compat/TabHostCompat.java new file mode 100644 index 000000000..9a07d0324 --- /dev/null +++ b/app/src/main/java/org/dslul/openboard/inputmethod/compat/TabHostCompat.java @@ -0,0 +1,52 @@ +package org.dslul.openboard.inputmethod.compat; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.TabHost; + +/* + * Custom version of {@link TabHost} that triggers its {@link TabHost.OnTabChangeListener} when + * a tab is reselected. It is hacky but it avoids importing material widgets lib. + * See https://github.com/aosp-mirror/platform_frameworks_base/blob/8551ec363dcd7c2d7c82c45e89db4922156766ab/core/java/android/widget/TabHost.java#L428 + */ +public class TabHostCompat extends TabHost implements TabHost.OnTabChangeListener { + + private boolean mFireOnTabChangeListenerOnReselection; + private OnTabChangeListener mOnTabChangeListener; + + public TabHostCompat(Context context) { + super(context); + } + + public TabHostCompat(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + public void setOnTabChangedListener(OnTabChangeListener l) { + super.setOnTabChangedListener(l != null ? this : null); + mOnTabChangeListener = l; + } + + @Override + public void setCurrentTab(int index) { + super.setCurrentTab(index); + if (index < 0 || index >= getTabWidget().getTabCount()) { + return; + } + if (mOnTabChangeListener != null) { + if (getCurrentTab() != index || mFireOnTabChangeListenerOnReselection) { + mOnTabChangeListener.onTabChanged(getCurrentTabTag()); + } + } + } + + @Override + public void onTabChanged(String s) { + // Ignored + } + + public void setFireOnTabChangeListenerOnReselection(boolean whether) { + mFireOnTabChangeListenerOnReselection = whether; + } +} diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/emoji/EmojiCategory.java b/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/emoji/EmojiCategory.java index 261972613..c7b886bc4 100644 --- a/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/emoji/EmojiCategory.java +++ b/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/emoji/EmojiCategory.java @@ -142,19 +142,18 @@ final class EmojiCategory { sCategoryTabIconAttr[i], 0); } - int defaultCategoryId = EmojiCategory.ID_SYMBOLS; + int defaultCategoryId = EmojiCategory.ID_SMILEYS_EMOTION; addShownCategoryId(EmojiCategory.ID_RECENTS); - defaultCategoryId = EmojiCategory.ID_SMILEYS_EMOTION; - addShownCategoryId(ID_SMILEYS_EMOTION); - addShownCategoryId(ID_PEOPLE_BODY); - addShownCategoryId(ID_ANIMALS_NATURE); - addShownCategoryId(ID_FOOD_DRINK); - addShownCategoryId(ID_TRAVEL_PLACES); - addShownCategoryId(ID_ACTIVITIES); - addShownCategoryId(ID_OBJECTS); - addShownCategoryId(ID_SYMBOLS); + addShownCategoryId(EmojiCategory.ID_SMILEYS_EMOTION); + addShownCategoryId(EmojiCategory.ID_PEOPLE_BODY); + addShownCategoryId(EmojiCategory.ID_ANIMALS_NATURE); + addShownCategoryId(EmojiCategory.ID_FOOD_DRINK); + addShownCategoryId(EmojiCategory.ID_TRAVEL_PLACES); + addShownCategoryId(EmojiCategory.ID_ACTIVITIES); + addShownCategoryId(EmojiCategory.ID_OBJECTS); + addShownCategoryId(EmojiCategory.ID_SYMBOLS); if (canShowFlagEmoji()) { - addShownCategoryId(ID_FLAGS); + addShownCategoryId(EmojiCategory.ID_FLAGS); } addShownCategoryId(EmojiCategory.ID_EMOTICONS); @@ -163,6 +162,7 @@ final class EmojiCategory { recentsKbd.loadRecentKeys(mCategoryKeyboardMap.values()); mCurrentCategoryId = Settings.readLastShownEmojiCategoryId(mPrefs, defaultCategoryId); + mCurrentCategoryPageId = Settings.readLastShownEmojiCategoryPageId(mPrefs, 0); Log.i(TAG, "Last Emoji category id is " + mCurrentCategoryId); if (!isShownCategoryId(mCurrentCategoryId)) { Log.i(TAG, "Last emoji category " + mCurrentCategoryId + @@ -173,6 +173,10 @@ final class EmojiCategory { Log.i(TAG, "No recent emojis found, starting in category " + defaultCategoryId); mCurrentCategoryId = defaultCategoryId; } + + if (mCurrentCategoryPageId >= getCategoryPageCount(mCurrentCategoryId)) { + mCurrentCategoryPageId = 0; + } } private void addShownCategoryId(final int categoryId) { @@ -239,6 +243,7 @@ final class EmojiCategory { public void setCurrentCategoryPageId(final int id) { mCurrentCategoryPageId = id; + Settings.writeLastShownEmojiCategoryPageId(mPrefs, id); } public int getCurrentCategoryPageId() { @@ -265,14 +270,12 @@ final class EmojiCategory { } // Returns the view pager's page position for the categoryId - public int getPageIdFromCategoryId(final int categoryId) { - final int lastSavedCategoryPageId = - Settings.readLastTypedEmojiCategoryPageId(mPrefs, 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 + lastSavedCategoryPageId; + return sum + categoryPageId; } sum += props.mPageCount; } diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/emoji/EmojiPalettesView.java b/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/emoji/EmojiPalettesView.java index 342a8ea05..5e9e039e3 100644 --- a/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/emoji/EmojiPalettesView.java +++ b/app/src/main/java/org/dslul/openboard/inputmethod/keyboard/emoji/EmojiPalettesView.java @@ -35,6 +35,7 @@ import android.widget.TabHost.OnTabChangeListener; import android.widget.TabWidget; import android.widget.TextView; +import org.dslul.openboard.inputmethod.compat.TabHostCompat; import org.dslul.openboard.inputmethod.keyboard.Key; import org.dslul.openboard.inputmethod.keyboard.KeyboardActionListener; import org.dslul.openboard.inputmethod.keyboard.KeyboardLayoutSet; @@ -48,7 +49,6 @@ import org.dslul.openboard.inputmethod.latin.RichInputMethodSubtype; import org.dslul.openboard.inputmethod.latin.common.Constants; import org.dslul.openboard.inputmethod.latin.utils.ResourceUtils; -import androidx.viewpager.widget.ViewPager; import androidx.viewpager2.widget.ViewPager2; import static org.dslul.openboard.inputmethod.latin.common.Constants.NOT_A_COORDINATE; @@ -64,9 +64,10 @@ import static org.dslul.openboard.inputmethod.latin.common.Constants.NOT_A_COORD * * Because of the above reasons, this class doesn't extend {@link KeyboardView}. */ +@SuppressWarnings("deprecation") public final class EmojiPalettesView extends LinearLayout implements OnTabChangeListener, View.OnClickListener, View.OnTouchListener, - OnKeyEventListener{ + OnKeyEventListener { private final int mFunctionalKeyBackgroundId; private final int mSpacebarBackgroundId; private final boolean mCategoryIndicatorEnabled; @@ -83,7 +84,7 @@ public final class EmojiPalettesView extends LinearLayout private View mSpacebar; // TODO: Remove this workaround. private View mSpacebarIcon; - private TabHost mTabHost; + private TabHostCompat mTabHost; private ViewPager2 mEmojiPager; private int mCurrentPagerPosition = 0; private EmojiCategoryPageIndicatorView mEmojiCategoryPageIndicatorView; @@ -150,7 +151,7 @@ public final class EmojiPalettesView extends LinearLayout final String tabId = EmojiCategory.getCategoryName(categoryId, 0 /* categoryPageId */); final TabHost.TabSpec tspec = host.newTabSpec(tabId); tspec.setContent(R.id.emoji_keyboard_dummy); - final ImageView iconView = (ImageView)LayoutInflater.from(getContext()).inflate( + final ImageView iconView = (ImageView) LayoutInflater.from(getContext()).inflate( R.layout.emoji_keyboard_tab_icon, null); // TODO: Replace background color with its own setting rather than using the // category page indicator background as a workaround. @@ -187,7 +188,8 @@ public final class EmojiPalettesView extends LinearLayout mEmojiPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() { @Override - public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {mEmojiPalettesAdapter.onPageScrolled(); + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + mEmojiPalettesAdapter.onPageScrolled(); final Pair newPos = mEmojiCategory.getCategoryIdAndPageIdFromPagePosition(position); final int newCategoryId = newPos.first; @@ -211,8 +213,8 @@ public final class EmojiPalettesView extends LinearLayout public void onPageSelected(int position) { final Pair newPos = mEmojiCategory.getCategoryIdAndPageIdFromPagePosition(position); - setCurrentCategoryId(newPos.first /* categoryId */, false /* force */); - mEmojiCategory.setCurrentCategoryPageId(newPos.second /* categoryPageId */); + setCurrentCategoryAndPageId(newPos.first /* categoryId */, newPos.second /* categoryPageId */, + false /* force */); updateEmojiCategoryPageIdView(); mCurrentPagerPosition = position; } @@ -233,7 +235,10 @@ public final class EmojiPalettesView extends LinearLayout mCategoryPageIndicatorColor, mCategoryPageIndicatorBackground); mEmojiLayoutParams.setCategoryPageIdViewProperties(mEmojiCategoryPageIndicatorView); - setCurrentCategoryId(mEmojiCategory.getCurrentCategoryId(), true /* force */); + setCurrentCategoryAndPageId(mEmojiCategory.getCurrentCategoryId(), mEmojiCategory.getCurrentCategoryPageId(), + true /* force */); + // Enable reselection after the first setCurrentCategoryAndPageId() init call + mTabHost.setFireOnTabChangeListenerOnReselection(true); final LinearLayout actionBar = findViewById(R.id.emoji_action_bar); mEmojiLayoutParams.setActionBarProperties(actionBar); @@ -278,7 +283,7 @@ public final class EmojiPalettesView extends LinearLayout AudioAndHapticFeedbackManager.getInstance().performHapticAndAudioFeedback( Constants.CODE_UNSPECIFIED, this); final int categoryId = mEmojiCategory.getCategoryId(tabId); - setCurrentCategoryId(categoryId, false /* force */); + setCurrentCategoryAndPageId(categoryId, 0, false /* force */); updateEmojiCategoryPageIdView(); } @@ -384,7 +389,7 @@ public final class EmojiPalettesView extends LinearLayout params.updateParams(mEmojiLayoutParams.getActionBarHeight(), keyVisualAttr); setupAlphabetKey(mAlphabetKeyLeft, switchToAlphaLabel, params); mEmojiPager.setAdapter(mEmojiPalettesAdapter); - mEmojiPager.setCurrentItem(mCurrentPagerPosition); + mEmojiPager.setCurrentItem(mCurrentPagerPosition, false); } public void stopEmojiPalettes() { @@ -407,13 +412,17 @@ public final class EmojiPalettesView extends LinearLayout mEmojiCategory.getCurrentCategoryPageId(), 0.0f /* offset */); } - private void setCurrentCategoryId(final int categoryId, final boolean force) { + private void setCurrentCategoryAndPageId(final int categoryId, final int categoryPageId, + final boolean force) { final int oldCategoryId = mEmojiCategory.getCurrentCategoryId(); - if (oldCategoryId == categoryId && !force) { + final int oldPageId = mEmojiCategory.getCurrentCategoryPageId(); + final boolean firstPage = categoryPageId == 0; + mEmojiCategory.setCurrentCategoryPageId(categoryPageId); + if (oldCategoryId == categoryId && (!firstPage || oldPageId == 0) && !force) { return; } - if (oldCategoryId == EmojiCategory.ID_RECENTS) { + 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. @@ -421,12 +430,15 @@ public final class EmojiPalettesView extends LinearLayout } mEmojiCategory.setCurrentCategoryId(categoryId); - final int newTabId = mEmojiCategory.getTabIdFromCategoryId(categoryId); - final int newCategoryPageId = mEmojiCategory.getPageIdFromCategoryId(categoryId); - if (force || mEmojiCategory.getCategoryIdAndPageIdFromPagePosition( - mEmojiPager.getCurrentItem()).first != categoryId) { - mEmojiPager.setCurrentItem(newCategoryPageId, false /* smoothScroll */); + final Pair pagerIds = mEmojiCategory.getCategoryIdAndPageIdFromPagePosition( + mEmojiPager.getCurrentItem()); + if (force || pagerIds.first != categoryId || (firstPage && pagerIds.second != 0)) { + final int newPagerPageId = mEmojiCategory.getPagerPageIdFromCategoryAndPageId(categoryId, categoryPageId); + final boolean smooth = pagerIds.first == categoryId && firstPage && pagerIds.second != 0; + mEmojiPager.setCurrentItem(newPagerPageId, smooth /* smoothScroll */); } + + final int newTabId = mEmojiCategory.getTabIdFromCategoryId(categoryId); if (force || mTabHost.getCurrentTab() != newTabId) { mTabHost.setCurrentTab(newTabId); } diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/Settings.java b/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/Settings.java index 0eab54c55..5f8b40e71 100644 --- a/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/Settings.java +++ b/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/Settings.java @@ -122,6 +122,7 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang public static final String PREF_EMOJI_RECENT_KEYS = "emoji_recent_keys"; public static final String PREF_EMOJI_CATEGORY_LAST_TYPED_ID = "emoji_category_last_typed_id"; public static final String PREF_LAST_SHOWN_EMOJI_CATEGORY_ID = "last_shown_emoji_category_id"; + public static final String PREF_LAST_SHOWN_EMOJI_CATEGORY_PAGE_ID = "last_shown_emoji_category_page_id"; private static final float UNDEFINED_PREFERENCE_VALUE_FLOAT = -1.0f; private static final int UNDEFINED_PREFERENCE_VALUE_INT = -1; @@ -445,6 +446,16 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang return prefs.getInt(PREF_LAST_SHOWN_EMOJI_CATEGORY_ID, defValue); } + public static void writeLastShownEmojiCategoryPageId( + final SharedPreferences prefs, final int categoryId) { + prefs.edit().putInt(PREF_LAST_SHOWN_EMOJI_CATEGORY_PAGE_ID, categoryId).apply(); + } + + public static int readLastShownEmojiCategoryPageId( + final SharedPreferences prefs, final int defValue) { + return prefs.getInt(PREF_LAST_SHOWN_EMOJI_CATEGORY_PAGE_ID, defValue); + } + private void upgradeAutocorrectionSettings(final SharedPreferences prefs, final Resources res) { final String thresholdSetting = prefs.getString(PREF_AUTO_CORRECTION_THRESHOLD_OBSOLETE, null); diff --git a/app/src/main/res/layout/emoji_palettes_view.xml b/app/src/main/res/layout/emoji_palettes_view.xml index bb66d15fa..4acb07f6f 100644 --- a/app/src/main/res/layout/emoji_palettes_view.xml +++ b/app/src/main/res/layout/emoji_palettes_view.xml @@ -32,7 +32,7 @@ android:layout_height="@dimen/config_suggestions_strip_height" style="?attr/suggestionStripViewStyle" > - - +