Allow resizing emoji and clipboard views in one-handed mode (#337)

This commit is contained in:
Helium314 2023-12-20 19:46:18 +01:00 committed by GitHub
parent 9a62d85dbf
commit 9f21f540af
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 195 additions and 146 deletions

View file

@ -7,9 +7,13 @@
package org.dslul.openboard.inputmethod.compat; package org.dslul.openboard.inputmethod.compat;
import android.content.Context; import android.content.Context;
import android.content.res.Resources;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.widget.TabHost; import android.widget.TabHost;
import org.dslul.openboard.inputmethod.latin.R;
import org.dslul.openboard.inputmethod.latin.utils.ResourceUtils;
/* /*
* Custom version of {@link TabHost} that triggers its {@link TabHost.OnTabChangeListener} when * 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. * a tab is reselected. It is hacky but it avoids importing material widgets lib.
@ -55,4 +59,13 @@ public class TabHostCompat extends TabHost implements TabHost.OnTabChangeListene
public void setFireOnTabChangeListenerOnReselection(boolean whether) { public void setFireOnTabChangeListenerOnReselection(boolean whether) {
mFireOnTabChangeListenerOnReselection = whether; mFireOnTabChangeListenerOnReselection = whether;
} }
@Override public void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
final Resources res = getContext().getResources();
// fill full width, otherwise the layout is messed up
final int width = ResourceUtils.getDefaultKeyboardWidth(res);
final int height = res.getDimensionPixelSize(R.dimen.config_suggestions_strip_height);
setMeasuredDimension(width, height);
}
} }

View file

@ -49,12 +49,12 @@ public class Keyboard {
/** Total height of the keyboard, including the padding and keys */ /** Total height of the keyboard, including the padding and keys */
public final int mOccupiedHeight; public final int mOccupiedHeight;
/** Total width of the keyboard, including the padding and keys */ /** Total width of the keyboard, including the padding and keys */
public final int mOccupiedWidth; public int mOccupiedWidth;
/** Base height of the keyboard, used to calculate rows' height */ /** Base height of the keyboard, used to calculate rows' height */
public final int mBaseHeight; public final int mBaseHeight;
/** Base width of the keyboard, used to calculate keys' width */ /** Base width of the keyboard, used to calculate keys' width */
public final int mBaseWidth; public int mBaseWidth;
/** The padding above the keyboard */ /** The padding above the keyboard */
public final int mTopPadding; public final int mTopPadding;

View file

@ -46,6 +46,8 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
private View mMainKeyboardFrame; private View mMainKeyboardFrame;
private MainKeyboardView mKeyboardView; private MainKeyboardView mKeyboardView;
private EmojiPalettesView mEmojiPalettesView; private EmojiPalettesView mEmojiPalettesView;
private View mEmojiTabStripView;
private View mSuggestionStripView;
private ClipboardHistoryView mClipboardHistoryView; private ClipboardHistoryView mClipboardHistoryView;
private LatinIME mLatinIME; private LatinIME mLatinIME;
private RichInputMethodManager mRichImm; private RichInputMethodManager mRichImm;
@ -272,8 +274,7 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
private void setMainKeyboardFrame( private void setMainKeyboardFrame(
@NonNull final SettingsValues settingsValues, @NonNull final SettingsValues settingsValues,
@NonNull final KeyboardSwitchState toggleState) { @NonNull final KeyboardSwitchState toggleState) {
final int visibility = isImeSuppressedByHardwareKeyboard(settingsValues, toggleState) final int visibility = isImeSuppressedByHardwareKeyboard(settingsValues, toggleState) ? View.GONE : View.VISIBLE;
? View.GONE : View.VISIBLE;
mKeyboardView.setVisibility(visibility); mKeyboardView.setVisibility(visibility);
// The visibility of {@link #mKeyboardView} must be aligned with {@link #MainKeyboardFrame}. // The visibility of {@link #mKeyboardView} must be aligned with {@link #MainKeyboardFrame}.
// @see #getVisibleKeyboardView() and // @see #getVisibleKeyboardView() and
@ -281,6 +282,8 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
mMainKeyboardFrame.setVisibility(visibility); mMainKeyboardFrame.setVisibility(visibility);
mEmojiPalettesView.setVisibility(View.GONE); mEmojiPalettesView.setVisibility(View.GONE);
mEmojiPalettesView.stopEmojiPalettes(); mEmojiPalettesView.stopEmojiPalettes();
mEmojiTabStripView.setVisibility(View.GONE);
mSuggestionStripView.setVisibility(View.VISIBLE);
mClipboardHistoryView.setVisibility(View.GONE); mClipboardHistoryView.setVisibility(View.GONE);
mClipboardHistoryView.stopClipboardHistory(); mClipboardHistoryView.stopClipboardHistory();
} }
@ -292,11 +295,14 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
Log.d(TAG, "setEmojiKeyboard"); Log.d(TAG, "setEmojiKeyboard");
} }
final Keyboard keyboard = mKeyboardLayoutSet.getKeyboard(KeyboardId.ELEMENT_ALPHABET); final Keyboard keyboard = mKeyboardLayoutSet.getKeyboard(KeyboardId.ELEMENT_ALPHABET);
mMainKeyboardFrame.setVisibility(View.GONE); mMainKeyboardFrame.setVisibility(View.VISIBLE);
// The visibility of {@link #mKeyboardView} must be aligned with {@link #MainKeyboardFrame}. // The visibility of {@link #mKeyboardView} must be aligned with {@link #MainKeyboardFrame}.
// @see #getVisibleKeyboardView() and // @see #getVisibleKeyboardView() and
// @see LatinIME#onComputeInset(android.inputmethodservice.InputMethodService.Insets) // @see LatinIME#onComputeInset(android.inputmethodservice.InputMethodService.Insets)
mKeyboardView.setVisibility(View.GONE); mKeyboardView.setVisibility(View.GONE);
mSuggestionStripView.setVisibility(View.GONE);
mEmojiTabStripView.setVisibility(View.VISIBLE);
mClipboardHistoryView.setVisibility(View.GONE);
mEmojiPalettesView.startEmojiPalettes( mEmojiPalettesView.startEmojiPalettes(
mKeyboardLayoutSet.mLocaleKeyTexts.getLabelAlphabet(), mKeyboardLayoutSet.mLocaleKeyTexts.getLabelAlphabet(),
mKeyboardView.getKeyVisualAttribute(), keyboard.mIconsSet); mKeyboardView.getKeyVisualAttribute(), keyboard.mIconsSet);
@ -310,11 +316,14 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
Log.d(TAG, "setClipboardKeyboard"); Log.d(TAG, "setClipboardKeyboard");
} }
final Keyboard keyboard = mKeyboardLayoutSet.getKeyboard(KeyboardId.ELEMENT_ALPHABET); final Keyboard keyboard = mKeyboardLayoutSet.getKeyboard(KeyboardId.ELEMENT_ALPHABET);
mMainKeyboardFrame.setVisibility(View.GONE); mMainKeyboardFrame.setVisibility(View.VISIBLE);
// The visibility of {@link #mKeyboardView} must be aligned with {@link #MainKeyboardFrame}. // The visibility of {@link #mKeyboardView} must be aligned with {@link #MainKeyboardFrame}.
// @see #getVisibleKeyboardView() and // @see #getVisibleKeyboardView() and
// @see LatinIME#onComputeInset(android.inputmethodservice.InputMethodService.Insets) // @see LatinIME#onComputeInset(android.inputmethodservice.InputMethodService.Insets)
mKeyboardView.setVisibility(View.GONE); mKeyboardView.setVisibility(View.GONE);
mEmojiTabStripView.setVisibility(View.GONE);
mSuggestionStripView.setVisibility(View.VISIBLE);
mEmojiPalettesView.setVisibility(View.GONE);
mClipboardHistoryView.startClipboardHistory( mClipboardHistoryView.startClipboardHistory(
mLatinIME.getClipboardHistoryManager(), mLatinIME.getClipboardHistoryManager(),
mKeyboardLayoutSet.mLocaleKeyTexts.getLabelAlphabet(), mKeyboardLayoutSet.mLocaleKeyTexts.getLabelAlphabet(),
@ -429,15 +438,23 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
if (mKeyboardViewWrapper.getOneHandedModeEnabled() == enabled) { if (mKeyboardViewWrapper.getOneHandedModeEnabled() == enabled) {
return; return;
} }
mEmojiPalettesView.clearKeyboardCache();
final Settings settings = Settings.getInstance(); final Settings settings = Settings.getInstance();
mKeyboardViewWrapper.setOneHandedModeEnabled(enabled); mKeyboardViewWrapper.setOneHandedModeEnabled(enabled);
mKeyboardViewWrapper.setOneHandedGravity(settings.getCurrent().mOneHandedModeGravity); mKeyboardViewWrapper.setOneHandedGravity(settings.getCurrent().mOneHandedModeGravity);
settings.writeOneHandedModeEnabled(enabled); settings.writeOneHandedModeEnabled(enabled);
// Reload the entire keyboard set with the same parameters // Reload the entire keyboard set with the same parameters, and switch to the previous layout
boolean wasEmoji = isShowingEmojiPalettes();
boolean wasClipboard = isShowingClipboardHistory();
loadKeyboard(mLatinIME.getCurrentInputEditorInfo(), settings.getCurrent(), loadKeyboard(mLatinIME.getCurrentInputEditorInfo(), settings.getCurrent(),
mLatinIME.getCurrentAutoCapsState(), mLatinIME.getCurrentRecapitalizeState()); mLatinIME.getCurrentAutoCapsState(), mLatinIME.getCurrentRecapitalizeState());
if (wasEmoji)
setEmojiKeyboard();
else if (wasClipboard) {
setClipboardKeyboard();
}
} }
// Implements {@link KeyboardState.SwitchActions}. // Implements {@link KeyboardState.SwitchActions}.
@ -499,9 +516,17 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
} else if (isShowingClipboardHistory()) { } else if (isShowingClipboardHistory()) {
return mClipboardHistoryView; return mClipboardHistoryView;
} }
return mKeyboardView;
}
public View getWrapperView() {
return mKeyboardViewWrapper; return mKeyboardViewWrapper;
} }
public View getEmojiTabStrip() {
return mEmojiTabStripView;
}
public MainKeyboardView getMainKeyboardView() { public MainKeyboardView getMainKeyboardView() {
return mKeyboardView; return mKeyboardView;
} }
@ -540,6 +565,9 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
mEmojiPalettesView.setKeyboardActionListener(mLatinIME); mEmojiPalettesView.setKeyboardActionListener(mLatinIME);
mClipboardHistoryView.setHardwareAcceleratedDrawingEnabled(isHardwareAcceleratedDrawingEnabled); mClipboardHistoryView.setHardwareAcceleratedDrawingEnabled(isHardwareAcceleratedDrawingEnabled);
mClipboardHistoryView.setKeyboardActionListener(mLatinIME); mClipboardHistoryView.setKeyboardActionListener(mLatinIME);
mEmojiTabStripView = mCurrentInputView.findViewById(R.id.emoji_tab_strip);
mSuggestionStripView = mCurrentInputView.findViewById(R.id.suggestion_strip_view);
mEmojiPalettesView.initialStart();
return mCurrentInputView; return mCurrentInputView;
} }

View file

@ -213,12 +213,7 @@ public class KeyboardView extends View {
} }
mKeyboard = keyboard; mKeyboard = keyboard;
final SettingsValues sv = Settings.getInstance().getCurrent(); mKeyScaleForText = (float) Math.sqrt(1 / Settings.getInstance().getCurrent().mKeyboardHeightScale);
// scale should not depend on mOneHandedModeScale for emoji and clipboard, because those views are not affected by one-handed mode (yet)
if (keyboard.mId.isEmojiKeyboard() || keyboard.mId.mElementId == KeyboardId.ELEMENT_CLIPBOARD)
mKeyScaleForText = (float) Math.sqrt(1 / sv.mKeyboardHeightScale);
else
mKeyScaleForText = (float) Math.sqrt(sv.mOneHandedModeScale / sv.mKeyboardHeightScale);
final int scaledKeyHeight = (int) ((keyboard.mMostCommonKeyHeight - keyboard.mVerticalGap) * mKeyScaleForText); final int scaledKeyHeight = (int) ((keyboard.mMostCommonKeyHeight - keyboard.mVerticalGap) * mKeyScaleForText);
mKeyDrawParams.updateParams(scaledKeyHeight, mKeyVisualAttributes); mKeyDrawParams.updateParams(scaledKeyHeight, mKeyVisualAttributes);
mKeyDrawParams.updateParams(scaledKeyHeight, keyboard.mKeyVisualAttributes); mKeyDrawParams.updateParams(scaledKeyHeight, keyboard.mKeyVisualAttributes);
@ -362,6 +357,7 @@ public class KeyboardView extends View {
canvas.translate(keyDrawX, keyDrawY); canvas.translate(keyDrawX, keyDrawY);
final KeyVisualAttributes attr = key.getVisualAttributes(); final KeyVisualAttributes attr = key.getVisualAttributes();
// don't use the raw key height, linear font scaling with height is too extreme
final KeyDrawParams params = mKeyDrawParams.mayCloneAndUpdateParams((int) (key.getHeight() * mKeyScaleForText), attr); final KeyDrawParams params = mKeyDrawParams.mayCloneAndUpdateParams((int) (key.getHeight() * mKeyScaleForText), attr);
params.mAnimAlpha = Constants.Color.ALPHA_OPAQUE; params.mAnimAlpha = Constants.Color.ALPHA_OPAQUE;

View file

@ -56,14 +56,16 @@ class ClipboardHistoryView @JvmOverloads constructor(
keyboardViewAttr.recycle() keyboardViewAttr.recycle()
} }
// todo: add another strip to clipboard, with select all, arrow keys, select, copy, clear buttons
// at the bottom, remove the clear button and add the keys like in the emoji view (abc, space, delete)
// also allow swipe to remove a word from clipboard history (except current clip and pinned clips)
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec) super.onMeasure(widthMeasureSpec, heightMeasureSpec)
val res = context.resources val res = context.resources
// The main keyboard expands to the entire this {@link KeyboardView}. // The main keyboard expands to the entire this {@link KeyboardView}.
val width = (ResourceUtils.getDefaultKeyboardWidth(res) + paddingLeft + paddingRight) val width = ResourceUtils.getKeyboardWidth(res, Settings.getInstance().current) + paddingLeft + paddingRight
val height = (ResourceUtils.getKeyboardHeight(res, Settings.getInstance().current) val height = ResourceUtils.getKeyboardHeight(res, Settings.getInstance().current) + paddingTop + paddingBottom
+ res.getDimensionPixelSize(R.dimen.config_suggestions_strip_height) findViewById<FrameLayout>(R.id.clipboard_action_bar)?.layoutParams?.width = width
+ paddingTop + paddingBottom)
setMeasuredDimension(width, height) setMeasuredDimension(width, height)
} }
@ -154,6 +156,7 @@ class ClipboardHistoryView @JvmOverloads constructor(
} }
clipboardRecyclerView.apply { clipboardRecyclerView.apply {
adapter = clipboardAdapter adapter = clipboardAdapter
layoutParams.width = ResourceUtils.getKeyboardWidth(context.resources, Settings.getInstance().current)
} }
Settings.getInstance().current.mColors.setBackground(this, ColorType.CLIPBOARD_BACKGROUND) Settings.getInstance().current.mColors.setBackground(this, ColorType.CLIPBOARD_BACKGROUND)
} }

View file

@ -26,8 +26,7 @@ class ClipboardLayoutParams(res: Resources) {
init { init {
val defaultKeyboardHeight = ResourceUtils.getKeyboardHeight(res, Settings.getInstance().current) val defaultKeyboardHeight = ResourceUtils.getKeyboardHeight(res, Settings.getInstance().current)
val suggestionStripHeight = res.getDimensionPixelSize(R.dimen.config_suggestions_strip_height) val defaultKeyboardWidth = ResourceUtils.getKeyboardWidth(res, Settings.getInstance().current)
val defaultKeyboardWidth = ResourceUtils.getDefaultKeyboardWidth(res)
if (Settings.getInstance().current.mNarrowKeyGaps) { if (Settings.getInstance().current.mNarrowKeyGaps) {
keyVerticalGap = res.getFraction(R.fraction.config_key_vertical_gap_holo_narrow, keyVerticalGap = res.getFraction(R.fraction.config_key_vertical_gap_holo_narrow,
@ -45,8 +44,9 @@ class ClipboardLayoutParams(res: Resources) {
topPadding = res.getFraction(R.fraction.config_keyboard_top_padding_holo, topPadding = res.getFraction(R.fraction.config_keyboard_top_padding_holo,
defaultKeyboardHeight, defaultKeyboardHeight).toInt() defaultKeyboardHeight, defaultKeyboardHeight).toInt()
actionBarHeight = (defaultKeyboardHeight - bottomPadding - topPadding) / DEFAULT_KEYBOARD_ROWS - keyVerticalGap / 2 val rowCount = DEFAULT_KEYBOARD_ROWS + if (Settings.getInstance().current.mShowsNumberRow) 1 else 0
listHeight = defaultKeyboardHeight + suggestionStripHeight - actionBarHeight - bottomPadding actionBarHeight = (defaultKeyboardHeight - bottomPadding - topPadding) / rowCount - keyVerticalGap / 2
listHeight = defaultKeyboardHeight - actionBarHeight - bottomPadding
} }
fun setListProperties(recycler: RecyclerView) { fun setListProperties(recycler: RecyclerView) {

View file

@ -49,19 +49,33 @@ final class DynamicGridKeyboard extends Keyboard {
private List<Key> mCachedGridKeys; private List<Key> mCachedGridKeys;
public DynamicGridKeyboard(final SharedPreferences prefs, final Keyboard templateKeyboard, public DynamicGridKeyboard(final SharedPreferences prefs, final Keyboard templateKeyboard,
final int maxKeyCount, final int categoryId) { final int maxKeyCount, final int categoryId, final int width) {
super(templateKeyboard); super(templateKeyboard);
// todo: would be better to keep them final and not require width, but how to properly set width of the template keyboard?
// an alternative would be to always create the templateKeyboard with full width
final int paddingWidth = mOccupiedWidth - mBaseWidth;
mBaseWidth = width - paddingWidth;
mOccupiedWidth = width;
final Key key0 = getTemplateKey(TEMPLATE_KEY_CODE_0); final Key key0 = getTemplateKey(TEMPLATE_KEY_CODE_0);
final Key key1 = getTemplateKey(TEMPLATE_KEY_CODE_1); final Key key1 = getTemplateKey(TEMPLATE_KEY_CODE_1);
mHorizontalGap = Math.abs(key1.getX() - key0.getX()) - key0.getWidth(); final int horizontalGap = Math.abs(key1.getX() - key0.getX()) - key0.getWidth();
mHorizontalStep = key0.getWidth() + mHorizontalGap; final float widthScale = determineWidthScale(key0.getWidth() + horizontalGap);
mVerticalStep = key0.getHeight() + mVerticalGap; mHorizontalGap = (int) (horizontalGap * widthScale);
mHorizontalStep = (int) ((key0.getWidth() + horizontalGap) * widthScale);
mVerticalStep = (int) ((key0.getHeight() + mVerticalGap) / Math.sqrt(Settings.getInstance().getCurrent().mKeyboardHeightScale));
mColumnsNum = mBaseWidth / mHorizontalStep; mColumnsNum = mBaseWidth / mHorizontalStep;
mMaxKeyCount = maxKeyCount; mMaxKeyCount = maxKeyCount;
mIsRecents = categoryId == EmojiCategory.ID_RECENTS; mIsRecents = categoryId == EmojiCategory.ID_RECENTS;
mPrefs = prefs; mPrefs = prefs;
} }
// determine a width scale so emojis evenly fill the entire width
private float determineWidthScale(final float horizontalStep) {
final float columnsNumRaw = mBaseWidth / horizontalStep;
final float columnsNum = Math.round(columnsNumRaw);
return columnsNumRaw / columnsNum;
}
private Key getTemplateKey(final int code) { private Key getTemplateKey(final int code) {
for (final Key key : super.getSortedKeys()) { for (final Key key : super.getSortedKeys()) {
if (key.getCode() == code) { if (key.getCode() == code) {

View file

@ -20,6 +20,7 @@ import org.dslul.openboard.inputmethod.keyboard.KeyboardId;
import org.dslul.openboard.inputmethod.keyboard.KeyboardLayoutSet; import org.dslul.openboard.inputmethod.keyboard.KeyboardLayoutSet;
import org.dslul.openboard.inputmethod.latin.R; import org.dslul.openboard.inputmethod.latin.R;
import org.dslul.openboard.inputmethod.latin.settings.Settings; import org.dslul.openboard.inputmethod.latin.settings.Settings;
import org.dslul.openboard.inputmethod.latin.utils.ResourceUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -118,8 +119,7 @@ final class EmojiCategory {
private final HashMap<String, Integer> mCategoryNameToIdMap = new HashMap<>(); private final HashMap<String, Integer> mCategoryNameToIdMap = new HashMap<>();
private final int[] mCategoryTabIconId = new int[sCategoryName.length]; private final int[] mCategoryTabIconId = new int[sCategoryName.length];
private final ArrayList<CategoryProperties> mShownCategories = new ArrayList<>(); private final ArrayList<CategoryProperties> mShownCategories = new ArrayList<>();
private final ConcurrentHashMap<Long, DynamicGridKeyboard> mCategoryKeyboardMap = private final ConcurrentHashMap<Long, DynamicGridKeyboard> mCategoryKeyboardMap = new ConcurrentHashMap<>();
new ConcurrentHashMap<>();
private int mCurrentCategoryId = EmojiCategory.ID_UNSPECIFIED; private int mCurrentCategoryId = EmojiCategory.ID_UNSPECIFIED;
private int mCurrentCategoryPageId = 0; private int mCurrentCategoryPageId = 0;
@ -132,8 +132,7 @@ final class EmojiCategory {
mLayoutSet = layoutSet; mLayoutSet = layoutSet;
for (int i = 0; i < sCategoryName.length; ++i) { for (int i = 0; i < sCategoryName.length; ++i) {
mCategoryNameToIdMap.put(sCategoryName[i], i); mCategoryNameToIdMap.put(sCategoryName[i], i);
mCategoryTabIconId[i] = emojiPaletteViewAttr.getResourceId( mCategoryTabIconId[i] = emojiPaletteViewAttr.getResourceId(sCategoryTabIconAttr[i], 0);
sCategoryTabIconAttr[i], 0);
} }
int defaultCategoryId = EmojiCategory.ID_SMILEYS_EMOTION; int defaultCategoryId = EmojiCategory.ID_SMILEYS_EMOTION;
@ -168,6 +167,10 @@ final class EmojiCategory {
} }
} }
public void clearKeyboardCache() {
mCategoryKeyboardMap.clear();
}
private void addShownCategoryId(final int categoryId) { private void addShownCategoryId(final int categoryId) {
// Load a keyboard of categoryId // Load a keyboard of categoryId
final CategoryProperties properties = new CategoryProperties(categoryId); final CategoryProperties properties = new CategoryProperties(categoryId);
@ -294,10 +297,11 @@ final class EmojiCategory {
return mCategoryKeyboardMap.get(categoryKeyboardMapKey); return mCategoryKeyboardMap.get(categoryKeyboardMapKey);
} }
final int currentWidth = ResourceUtils.getKeyboardWidth(mRes, Settings.getInstance().getCurrent());
if (categoryId == EmojiCategory.ID_RECENTS) { if (categoryId == EmojiCategory.ID_RECENTS) {
final DynamicGridKeyboard kbd = new DynamicGridKeyboard(mPrefs, final DynamicGridKeyboard kbd = new DynamicGridKeyboard(mPrefs,
mLayoutSet.getKeyboard(KeyboardId.ELEMENT_EMOJI_RECENTS), mLayoutSet.getKeyboard(KeyboardId.ELEMENT_EMOJI_RECENTS),
mMaxRecentsKeyCount, categoryId); mMaxRecentsKeyCount, categoryId, currentWidth);
mCategoryKeyboardMap.put(categoryKeyboardMapKey, kbd); mCategoryKeyboardMap.put(categoryKeyboardMapKey, kbd);
return kbd; return kbd;
} }
@ -309,15 +313,14 @@ final class EmojiCategory {
for (int pageId = 0; pageId < sortedKeysPages.length; ++pageId) { for (int pageId = 0; pageId < sortedKeysPages.length; ++pageId) {
final DynamicGridKeyboard tempKeyboard = new DynamicGridKeyboard(mPrefs, final DynamicGridKeyboard tempKeyboard = new DynamicGridKeyboard(mPrefs,
mLayoutSet.getKeyboard(KeyboardId.ELEMENT_EMOJI_RECENTS), mLayoutSet.getKeyboard(KeyboardId.ELEMENT_EMOJI_RECENTS),
keyCountPerPage, categoryId); keyCountPerPage, categoryId, currentWidth);
for (final Key emojiKey : sortedKeysPages[pageId]) { for (final Key emojiKey : sortedKeysPages[pageId]) {
if (emojiKey == null) { if (emojiKey == null) {
break; break;
} }
tempKeyboard.addKeyLast(emojiKey); tempKeyboard.addKeyLast(emojiKey);
} }
mCategoryKeyboardMap.put( mCategoryKeyboardMap.put(getCategoryKeyboardMapKey(categoryId, pageId), tempKeyboard);
getCategoryKeyboardMapKey(categoryId, pageId), tempKeyboard);
} }
return mCategoryKeyboardMap.get(categoryKeyboardMapKey); return mCategoryKeyboardMap.get(categoryKeyboardMapKey);
} }
@ -326,7 +329,7 @@ final class EmojiCategory {
private int computeMaxKeyCountPerPage() { private int computeMaxKeyCountPerPage() {
final DynamicGridKeyboard tempKeyboard = new DynamicGridKeyboard(mPrefs, final DynamicGridKeyboard tempKeyboard = new DynamicGridKeyboard(mPrefs,
mLayoutSet.getKeyboard(KeyboardId.ELEMENT_EMOJI_RECENTS), mLayoutSet.getKeyboard(KeyboardId.ELEMENT_EMOJI_RECENTS),
0, 0); 0, 0, ResourceUtils.getKeyboardWidth(mRes, Settings.getInstance().getCurrent()));
return MAX_LINE_COUNT_PER_PAGE * tempKeyboard.getColumnsCount(); return MAX_LINE_COUNT_PER_PAGE * tempKeyboard.getColumnsCount();
} }

View file

@ -32,7 +32,7 @@ final class EmojiLayoutParams {
public EmojiLayoutParams(final Resources res) { public EmojiLayoutParams(final Resources res) {
final SettingsValues settingsValues = Settings.getInstance().getCurrent(); final SettingsValues settingsValues = Settings.getInstance().getCurrent();
final int defaultKeyboardHeight = ResourceUtils.getKeyboardHeight(res, settingsValues); final int defaultKeyboardHeight = ResourceUtils.getKeyboardHeight(res, settingsValues);
final int defaultKeyboardWidth = ResourceUtils.getDefaultKeyboardWidth(res); final int defaultKeyboardWidth = ResourceUtils.getKeyboardWidth(res, settingsValues);
if (settingsValues.mNarrowKeyGaps) { if (settingsValues.mNarrowKeyGaps) {
mKeyVerticalGap = (int) res.getFraction(R.fraction.config_key_vertical_gap_holo_narrow, mKeyVerticalGap = (int) res.getFraction(R.fraction.config_key_vertical_gap_holo_narrow,
defaultKeyboardHeight, defaultKeyboardHeight); defaultKeyboardHeight, defaultKeyboardHeight);
@ -77,6 +77,7 @@ final class EmojiLayoutParams {
public void setActionBarProperties(final LinearLayout ll) { public void setActionBarProperties(final LinearLayout ll) {
final LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) ll.getLayoutParams(); final LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) ll.getLayoutParams();
lp.height = getActionBarHeight(); lp.height = getActionBarHeight();
lp.width = ResourceUtils.getKeyboardWidth(ll.getResources(), Settings.getInstance().getCurrent());
ll.setLayoutParams(lp); ll.setLayoutParams(lp);
} }

View file

@ -110,8 +110,7 @@ public final class EmojiPageKeyboardView extends KeyboardView implements
final Keyboard keyboard = getKeyboard(); final Keyboard keyboard = getKeyboard();
if (keyboard instanceof DynamicGridKeyboard) { if (keyboard instanceof DynamicGridKeyboard) {
final int width = keyboard.mOccupiedWidth + getPaddingLeft() + getPaddingRight(); final int width = keyboard.mOccupiedWidth + getPaddingLeft() + getPaddingRight();
final int occupiedHeight = final int occupiedHeight = ((DynamicGridKeyboard) keyboard).getDynamicOccupiedHeight();
((DynamicGridKeyboard) keyboard).getDynamicOccupiedHeight();
final int height = occupiedHeight + getPaddingTop() + getPaddingBottom(); final int height = occupiedHeight + getPaddingTop() + getPaddingBottom();
setMeasuredDimension(width, height); setMeasuredDimension(width, height);
return; return;
@ -185,8 +184,7 @@ public final class EmojiPageKeyboardView extends KeyboardView implements
} }
final View container = mMoreKeysKeyboardContainer; final View container = mMoreKeysKeyboardContainer;
final MoreKeysKeyboardView moreKeysKeyboardView = final MoreKeysKeyboardView moreKeysKeyboardView = container.findViewById(R.id.more_keys_keyboard_view);
container.findViewById(R.id.more_keys_keyboard_view);
moreKeysKeyboardView.setKeyboard(moreKeysKeyboard); moreKeysKeyboardView.setKeyboard(moreKeysKeyboard);
container.measure(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); container.measure(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
@ -198,8 +196,7 @@ public final class EmojiPageKeyboardView extends KeyboardView implements
? CoordinateUtils.x(lastCoords) ? CoordinateUtils.x(lastCoords)
: key.getX() + key.getWidth() / 2; : key.getX() + key.getWidth() / 2;
final int pointY = key.getY(); final int pointY = key.getY();
moreKeysKeyboardView.showMoreKeysPanel(this, this, moreKeysKeyboardView.showMoreKeysPanel(this, this, pointX, pointY, mListener);
pointX, pointY, mListener);
return moreKeysKeyboardView; return moreKeysKeyboardView;
} }
@ -253,10 +250,8 @@ public final class EmojiPageKeyboardView extends KeyboardView implements
*/ */
@Override @Override
public boolean onHoverEvent(final MotionEvent event) { public boolean onHoverEvent(final MotionEvent event) {
final KeyboardAccessibilityDelegate<EmojiPageKeyboardView> accessibilityDelegate = final KeyboardAccessibilityDelegate<EmojiPageKeyboardView> accessibilityDelegate = mAccessibilityDelegate;
mAccessibilityDelegate; if (accessibilityDelegate != null && AccessibilityUtils.Companion.getInstance().isTouchExplorationEnabled()) {
if (accessibilityDelegate != null
&& AccessibilityUtils.Companion.getInstance().isTouchExplorationEnabled()) {
return accessibilityDelegate.onHoverEvent(event); return accessibilityDelegate.onHoverEvent(event);
} }
return super.onHoverEvent(event); return super.onHoverEvent(event);
@ -387,12 +382,7 @@ public final class EmojiPageKeyboardView extends KeyboardView implements
} else if (key == currentKey && pendingKeyDown != null) { } else if (key == currentKey && pendingKeyDown != null) {
pendingKeyDown.run(); pendingKeyDown.run();
// Trigger key-release event a little later so that a user can see visual feedback. // Trigger key-release event a little later so that a user can see visual feedback.
mHandler.postDelayed(new Runnable() { mHandler.postDelayed(() -> callListenerOnReleaseKey(key, true), KEY_RELEASE_DELAY_TIME);
@Override
public void run() {
callListenerOnReleaseKey(key, true /* withRegistering */);
}
}, KEY_RELEASE_DELAY_TIME);
} else if (key != null) { } else if (key != null) {
callListenerOnReleaseKey(key, true /* withRegistering */); callListenerOnReleaseKey(key, true /* withRegistering */);
} }
@ -402,7 +392,7 @@ public final class EmojiPageKeyboardView extends KeyboardView implements
} }
public boolean onCancel(final MotionEvent e) { public boolean onCancel(final MotionEvent e) {
releaseCurrentKey(false /* withKeyRegistering */); releaseCurrentKey(false);
dismissMoreKeysPanel(); dismissMoreKeysPanel();
cancelLongPress(); cancelLongPress();
return true; return true;
@ -417,7 +407,7 @@ public final class EmojiPageKeyboardView extends KeyboardView implements
// Touched key has changed, release previous key's callbacks and // Touched key has changed, release previous key's callbacks and
// re-register them for the new key. // re-register them for the new key.
if (key != mCurrentKey && !isShowingMoreKeysPanel) { if (key != mCurrentKey && !isShowingMoreKeysPanel) {
releaseCurrentKey(false /* withKeyRegistering */); releaseCurrentKey(false);
mCurrentKey = key; mCurrentKey = key;
if (key == null) { if (key == null) {
return false; return false;

View file

@ -30,6 +30,7 @@ import org.dslul.openboard.inputmethod.compat.TabHostCompat;
import org.dslul.openboard.inputmethod.keyboard.Key; import org.dslul.openboard.inputmethod.keyboard.Key;
import org.dslul.openboard.inputmethod.keyboard.KeyboardActionListener; import org.dslul.openboard.inputmethod.keyboard.KeyboardActionListener;
import org.dslul.openboard.inputmethod.keyboard.KeyboardLayoutSet; import org.dslul.openboard.inputmethod.keyboard.KeyboardLayoutSet;
import org.dslul.openboard.inputmethod.keyboard.KeyboardSwitcher;
import org.dslul.openboard.inputmethod.keyboard.KeyboardView; import org.dslul.openboard.inputmethod.keyboard.KeyboardView;
import org.dslul.openboard.inputmethod.keyboard.internal.KeyDrawParams; import org.dslul.openboard.inputmethod.keyboard.internal.KeyDrawParams;
import org.dslul.openboard.inputmethod.keyboard.internal.KeyVisualAttributes; import org.dslul.openboard.inputmethod.keyboard.internal.KeyVisualAttributes;
@ -108,7 +109,7 @@ public final class EmojiPalettesView extends LinearLayout
final Resources res = context.getResources(); final Resources res = context.getResources();
mEmojiLayoutParams = new EmojiLayoutParams(res); mEmojiLayoutParams = new EmojiLayoutParams(res);
builder.setSubtype(RichInputMethodSubtype.getEmojiSubtype()); builder.setSubtype(RichInputMethodSubtype.getEmojiSubtype());
builder.setKeyboardGeometry(ResourceUtils.getDefaultKeyboardWidth(res), builder.setKeyboardGeometry(ResourceUtils.getKeyboardWidth(res, Settings.getInstance().getCurrent()),
mEmojiLayoutParams.mEmojiKeyboardHeight); mEmojiLayoutParams.mEmojiKeyboardHeight);
final KeyboardLayoutSet layoutSet = builder.build(); final KeyboardLayoutSet layoutSet = builder.build();
final TypedArray emojiPalettesViewAttr = context.obtainStyledAttributes(attrs, final TypedArray emojiPalettesViewAttr = context.obtainStyledAttributes(attrs,
@ -133,10 +134,9 @@ public final class EmojiPalettesView extends LinearLayout
super.onMeasure(widthMeasureSpec, heightMeasureSpec); super.onMeasure(widthMeasureSpec, heightMeasureSpec);
final Resources res = getContext().getResources(); final Resources res = getContext().getResources();
// The main keyboard expands to the entire this {@link KeyboardView}. // The main keyboard expands to the entire this {@link KeyboardView}.
final int width = ResourceUtils.getDefaultKeyboardWidth(res) final int width = ResourceUtils.getKeyboardWidth(res, Settings.getInstance().getCurrent())
+ getPaddingLeft() + getPaddingRight(); + getPaddingLeft() + getPaddingRight();
final int height = ResourceUtils.getKeyboardHeight(res, Settings.getInstance().getCurrent()) final int height = ResourceUtils.getKeyboardHeight(res, Settings.getInstance().getCurrent())
+ res.getDimensionPixelSize(R.dimen.config_suggestions_strip_height)
+ getPaddingTop() + getPaddingBottom(); + getPaddingTop() + getPaddingBottom();
setMeasuredDimension(width, height); setMeasuredDimension(width, height);
} }
@ -155,14 +155,10 @@ public final class EmojiPalettesView extends LinearLayout
host.addTab(tspec); host.addTab(tspec);
} }
@Override public void initialStart() { // needs to be delayed for access to EmojiTabStrip, which is not a child of this view
protected void onFinishInflate() { mTabHost = KeyboardSwitcher.getInstance().getEmojiTabStrip().findViewById(R.id.emoji_category_tabhost);
super.onFinishInflate();
mTabHost = findViewById(R.id.emoji_category_tabhost);
mTabHost.setup(); mTabHost.setup();
for (final EmojiCategory.CategoryProperties properties for (final EmojiCategory.CategoryProperties properties : mEmojiCategory.getShownCategories()) {
: mEmojiCategory.getShownCategories()) {
addTab(mTabHost, properties.mCategoryId); addTab(mTabHost, properties.mCategoryId);
} }
mTabHost.setOnTabChangedListener(this); mTabHost.setOnTabChangedListener(this);
@ -226,9 +222,6 @@ public final class EmojiPalettesView extends LinearLayout
// Enable reselection after the first setCurrentCategoryAndPageId() init call // Enable reselection after the first setCurrentCategoryAndPageId() init call
mTabHost.setFireOnTabChangeListenerOnReselection(true); mTabHost.setFireOnTabChangeListenerOnReselection(true);
final LinearLayout actionBar = findViewById(R.id.emoji_action_bar);
mEmojiLayoutParams.setActionBarProperties(actionBar);
// deleteKey depends only on OnTouchListener. // deleteKey depends only on OnTouchListener.
mDeleteKey = findViewById(R.id.emoji_keyboard_delete); mDeleteKey = findViewById(R.id.emoji_keyboard_delete);
mDeleteKey.setBackgroundResource(mFunctionalKeyBackgroundId); mDeleteKey.setBackgroundResource(mFunctionalKeyBackgroundId);
@ -378,6 +371,7 @@ public final class EmojiPalettesView extends LinearLayout
if (deleteIconResId != 0) { if (deleteIconResId != 0) {
mDeleteKey.setImageResource(deleteIconResId); mDeleteKey.setImageResource(deleteIconResId);
} }
mEmojiLayoutParams.setActionBarProperties(findViewById(R.id.emoji_action_bar));
final KeyDrawParams params = new KeyDrawParams(); final KeyDrawParams params = new KeyDrawParams();
params.updateParams(mEmojiLayoutParams.getActionBarHeight(), keyVisualAttr); params.updateParams(mEmojiLayoutParams.getActionBarHeight(), keyVisualAttr);
setupAlphabetKey(mAlphabetKeyLeft, switchToAlphaLabel, params); setupAlphabetKey(mAlphabetKeyLeft, switchToAlphaLabel, params);
@ -480,4 +474,8 @@ public final class EmojiPalettesView extends LinearLayout
v.setPressed(false); v.setPressed(false);
} }
} }
public void clearKeyboardCache() {
mEmojiCategory.clearKeyboardCache();
}
} }

View file

@ -11,7 +11,7 @@ import org.dslul.openboard.inputmethod.latin.R
import org.dslul.openboard.inputmethod.latin.common.Constants import org.dslul.openboard.inputmethod.latin.common.Constants
import org.dslul.openboard.inputmethod.latin.common.StringUtils import org.dslul.openboard.inputmethod.latin.common.StringUtils
import org.dslul.openboard.inputmethod.latin.settings.Settings import org.dslul.openboard.inputmethod.latin.settings.Settings
import kotlin.math.round import org.dslul.openboard.inputmethod.latin.utils.ResourceUtils
import kotlin.math.sqrt import kotlin.math.sqrt
class EmojiParser(private val params: KeyboardParams, private val context: Context) { class EmojiParser(private val params: KeyboardParams, private val context: Context) {
@ -62,18 +62,23 @@ class EmojiParser(private val params: KeyboardParams, private val context: Conte
*/ */
val row = ArrayList<KeyParams>(emojiArray.size) val row = ArrayList<KeyParams>(emojiArray.size)
var currentX = params.mLeftPadding.toFloat() var currentX = params.mLeftPadding.toFloat()
val currentY = params.mTopPadding.toFloat() val currentY = params.mTopPadding.toFloat() // no need to ever change, assignment to rows into rows is done in DynamicGridKeyboard
val widthScale = getWidthScale() // determine key width for default settings (no number row, no one-handed mode, 100% height and bottom padding scale)
// extra scale for height only, to undo the effect of number row increasing absolute key height // this is a bit long, but ensures that emoji size stays the same, independent of these settings
// todo: with this things look ok, but number row still slightly affects emoji size (which it should not) val defaultKeyWidth = (ResourceUtils.getDefaultKeyboardWidth(context.resources) - params.mLeftPadding - params.mRightPadding) * params.mDefaultRelativeKeyWidth
val numScale = if (Settings.getInstance().current.mShowsNumberRow) 1.25f else 1f val keyWidth = defaultKeyWidth * sqrt(Settings.getInstance().current.mKeyboardHeightScale)
val defaultKeyboardHeight = ResourceUtils.getDefaultKeyboardHeight(context.resources, false)
val defaultBottomPadding = context.resources.getFraction(R.fraction.config_keyboard_bottom_padding_holo, defaultKeyboardHeight, defaultKeyboardHeight);
val emojiKeyboardHeight = ResourceUtils.getDefaultKeyboardHeight(context.resources, false) * 0.75f + params.mVerticalGap - defaultBottomPadding - context.resources.getDimensionPixelSize(R.dimen.config_emoji_category_page_id_height)
val keyHeight = emojiKeyboardHeight * params.mDefaultRelativeRowHeight * Settings.getInstance().current.mKeyboardHeightScale // still apply height scale to key
emojiArray.forEachIndexed { i, codeArraySpec -> emojiArray.forEachIndexed { i, codeArraySpec ->
val keyParams = parseEmojiKey(codeArraySpec, moreEmojisArray?.get(i)?.takeIf { it.isNotEmpty() }) ?: return@forEachIndexed val keyParams = parseEmojiKey(codeArraySpec, moreEmojisArray?.get(i)?.takeIf { it.isNotEmpty() }) ?: return@forEachIndexed
keyParams.setDimensionsFromRelativeSize(currentX, currentY) keyParams.xPos = currentX
keyParams.mFullHeight /= numScale keyParams.yPos = currentY
keyParams.mFullWidth *= widthScale keyParams.mFullWidth = keyWidth
keyParams.mFullHeight = keyHeight
currentX += keyParams.mFullWidth currentX += keyParams.mFullWidth
row.add(keyParams) row.add(keyParams)
// if (row.size % numColumns == spacerIndex) { // also removed for now (would be missing setting the size and updating x // if (row.size % numColumns == spacerIndex) { // also removed for now (would be missing setting the size and updating x
@ -83,18 +88,6 @@ class EmojiParser(private val params: KeyboardParams, private val context: Conte
return arrayListOf(row) return arrayListOf(row)
} }
private fun getWidthScale(): Float {
// height scale affects emoji size, but then emojis may be too wide or too narrow
// so we re-scale width too
// but not with exactly the same factor, adjust it a little so emojis fill the entire available width
// this looks much better than setting some offset in DynamicGridKeyboard (to center the rows)
val numColumnsNew = round(1f / (params.mDefaultRelativeKeyWidth * sqrt(Settings.getInstance().current.mKeyboardHeightScale)))
val numColumnsOld = round(1f / params.mDefaultRelativeKeyWidth)
return numColumnsOld / numColumnsNew - 0.0001f // small offset to have more emojis in a row in edge cases
}
// private fun Float.roundTo(even: Boolean) = if (toInt() % 2 == if (even) 0 else 1) toInt() else toInt() + 1
private fun getLabelAndCode(spec: String): Pair<String, Int>? { private fun getLabelAndCode(spec: String): Pair<String, Int>? {
val specAndSdk = spec.split("||") val specAndSdk = spec.split("||")
if (specAndSdk.getOrNull(1)?.toIntOrNull()?.let { it > Build.VERSION.SDK_INT } == true) return null if (specAndSdk.getOrNull(1)?.toIntOrNull()?.let { it > Build.VERSION.SDK_INT } == true) return null

View file

@ -5,7 +5,6 @@ package org.dslul.openboard.inputmethod.latin
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.content.res.Configuration import android.content.res.Configuration
import android.graphics.Color
import android.util.AttributeSet import android.util.AttributeSet
import android.view.Gravity import android.view.Gravity
import android.view.MotionEvent import android.view.MotionEvent
@ -13,6 +12,7 @@ import android.view.View
import android.widget.FrameLayout import android.widget.FrameLayout
import android.widget.ImageButton import android.widget.ImageButton
import org.dslul.openboard.inputmethod.keyboard.KeyboardActionListener import org.dslul.openboard.inputmethod.keyboard.KeyboardActionListener
import org.dslul.openboard.inputmethod.keyboard.KeyboardSwitcher
import org.dslul.openboard.inputmethod.latin.common.ColorType import org.dslul.openboard.inputmethod.latin.common.ColorType
import org.dslul.openboard.inputmethod.latin.common.Constants import org.dslul.openboard.inputmethod.latin.common.Constants
import org.dslul.openboard.inputmethod.latin.settings.Settings import org.dslul.openboard.inputmethod.latin.settings.Settings
@ -29,7 +29,6 @@ class KeyboardWrapperView @JvmOverloads constructor(
private lateinit var stopOneHandedModeBtn: ImageButton private lateinit var stopOneHandedModeBtn: ImageButton
private lateinit var switchOneHandedModeBtn: ImageButton private lateinit var switchOneHandedModeBtn: ImageButton
private lateinit var keyboardView: View
private lateinit var resizeOneHandedModeBtn: ImageButton private lateinit var resizeOneHandedModeBtn: ImageButton
private val iconStopOneHandedModeId: Int private val iconStopOneHandedModeId: Int
private val iconSwitchOneHandedModeId: Int private val iconSwitchOneHandedModeId: Int
@ -62,7 +61,6 @@ class KeyboardWrapperView @JvmOverloads constructor(
resizeOneHandedModeBtn = findViewById(R.id.btn_resize_one_handed_mode) resizeOneHandedModeBtn = findViewById(R.id.btn_resize_one_handed_mode)
resizeOneHandedModeBtn.setImageResource(iconResizeOneHandedModeId) resizeOneHandedModeBtn.setImageResource(iconResizeOneHandedModeId)
resizeOneHandedModeBtn.visibility = GONE resizeOneHandedModeBtn.visibility = GONE
keyboardView = findViewById(R.id.keyboard_view)
stopOneHandedModeBtn.setOnClickListener(this) stopOneHandedModeBtn.setOnClickListener(this)
switchOneHandedModeBtn.setOnClickListener(this) switchOneHandedModeBtn.setOnClickListener(this)
@ -141,6 +139,7 @@ class KeyboardWrapperView @JvmOverloads constructor(
val isLeftGravity = oneHandedGravity == Gravity.LEFT val isLeftGravity = oneHandedGravity == Gravity.LEFT
val width = right - left val width = right - left
val keyboardView = KeyboardSwitcher.getInstance().visibleKeyboardView
val spareWidth = width - keyboardView.measuredWidth val spareWidth = width - keyboardView.measuredWidth
val keyboardLeft = if (isLeftGravity) 0 else spareWidth val keyboardLeft = if (isLeftGravity) 0 else spareWidth

View file

@ -1248,7 +1248,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (mInputView == null) { if (mInputView == null) {
return; return;
} }
final View visibleKeyboardView = mKeyboardSwitcher.getVisibleKeyboardView(); final View visibleKeyboardView = mKeyboardSwitcher.getWrapperView();
if (visibleKeyboardView == null || !hasSuggestionStripView()) { if (visibleKeyboardView == null || !hasSuggestionStripView()) {
return; return;
} }
@ -1261,11 +1261,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mInsetsUpdater.setInsets(outInsets); mInsetsUpdater.setInsets(outInsets);
return; return;
} }
final int suggestionsHeight = (!mKeyboardSwitcher.isShowingEmojiPalettes() final int visibleTopY = inputHeight - visibleKeyboardView.getHeight() - mSuggestionStripView.getHeight();
&& !mKeyboardSwitcher.isShowingClipboardHistory()
&& mSuggestionStripView.getVisibility() == View.VISIBLE)
? mSuggestionStripView.getHeight() : 0;
final int visibleTopY = inputHeight - visibleKeyboardView.getHeight() - suggestionsHeight;
mSuggestionStripView.setMoreSuggestionsHeight(visibleTopY); mSuggestionStripView.setMoreSuggestionsHeight(visibleTopY);
// Need to set expanded touchable region only if a keyboard view is being shown. // Need to set expanded touchable region only if a keyboard view is being shown.
if (visibleKeyboardView.isShown()) { if (visibleKeyboardView.isShown()) {

View file

@ -192,7 +192,7 @@ public final class ResourceUtils {
return (int)(defaultKeyboardHeight * settingsValues.mKeyboardHeightScale); return (int)(defaultKeyboardHeight * settingsValues.mKeyboardHeightScale);
} }
private static int getDefaultKeyboardHeight(final Resources res, final boolean showsNumberRow) { public static int getDefaultKeyboardHeight(final Resources res, final boolean showsNumberRow) {
final DisplayMetrics dm = res.getDisplayMetrics(); final DisplayMetrics dm = res.getDisplayMetrics();
final float keyboardHeight = res.getDimension(R.dimen.config_default_keyboard_height) * (showsNumberRow ? 1.25f : 1f); final float keyboardHeight = res.getDimension(R.dimen.config_default_keyboard_height) * (showsNumberRow ? 1.25f : 1f);
final float maxKeyboardHeight = res.getFraction( final float maxKeyboardHeight = res.getFraction(

View file

@ -14,40 +14,6 @@
android:visibility="gone" android:visibility="gone"
style="?attr/emojiPalettesViewStyle" style="?attr/emojiPalettesViewStyle"
> >
<LinearLayout
android:id="@+id/emoji_tab_strip"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="@dimen/config_suggestions_strip_height"
style="?attr/suggestionStripViewStyle"
>
<org.dslul.openboard.inputmethod.compat.TabHostCompat
android:id="@+id/emoji_category_tabhost"
android:layout_width="0dip"
android:layout_weight="87.5"
android:layout_height="match_parent"
>
<TabWidget
android:id="@android:id/tabs"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="@null" />
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="0dip"
android:layout_height="0dip"
>
<!-- Empty placeholder that TabHost requires. But we don't use it to actually
display anything. We monitor the tab changes and change the ViewPager.
Similarly the ViewPager swipes are intercepted and passed to the TabHost. -->
<View
android:id="@+id/emoji_keyboard_dummy"
android:layout_width="0dip"
android:layout_height="0dip"
android:visibility="gone" />
</FrameLayout>
</org.dslul.openboard.inputmethod.compat.TabHostCompat>
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/emoji_keyboard_list" android:id="@+id/emoji_keyboard_list"
android:layout_width="match_parent" android:layout_width="match_parent"

View file

@ -13,10 +13,4 @@
<include <include
android:id="@+id/main_keyboard_frame" android:id="@+id/main_keyboard_frame"
layout="@layout/main_keyboard_frame" /> layout="@layout/main_keyboard_frame" />
<include
android:id="@+id/emoji_palettes_view"
layout="@layout/emoji_palettes_view" />
<include
android:id="@+id/clipboard_history_view"
layout="@layout/clipboard_history_view" />
</org.dslul.openboard.inputmethod.latin.InputView> </org.dslul.openboard.inputmethod.latin.InputView>

View file

@ -12,15 +12,9 @@
android:layout_gravity="bottom" android:layout_gravity="bottom"
android:orientation="vertical" > android:orientation="vertical" >
<!-- To ensure that key preview popup is correctly placed when the current system locale is <include
one of RTL locales, layoutDirection="ltr" is needed in the SDK version 17+. --> android:id="@+id/strip_container"
<org.dslul.openboard.inputmethod.latin.suggestions.SuggestionStripView layout="@layout/strip_container" />
android:id="@+id/suggestion_strip_view"
android:layoutDirection="ltr"
android:layout_width="match_parent"
android:layout_height="@dimen/config_suggestions_strip_height"
android:gravity="center_vertical"
style="?attr/suggestionStripViewStyle" />
<!-- To ensure that key preview popup is correctly placed when the current system locale is <!-- To ensure that key preview popup is correctly placed when the current system locale is
one of RTL locales, layoutDirection="ltr" is needed in the SDK version 17+. --> one of RTL locales, layoutDirection="ltr" is needed in the SDK version 17+. -->
@ -35,6 +29,12 @@
android:layoutDirection="ltr" android:layoutDirection="ltr"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" /> android:layout_height="wrap_content" />
<include
android:id="@+id/emoji_palettes_view"
layout="@layout/emoji_palettes_view" />
<include
android:id="@+id/clipboard_history_view"
layout="@layout/clipboard_history_view" />
<ImageButton <ImageButton
android:id="@+id/btn_stop_one_handed_mode" android:id="@+id/btn_stop_one_handed_mode"

View file

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2014 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"
android:layout_width="match_parent"
android:layout_height="@dimen/config_suggestions_strip_height">
<!-- To ensure that key preview popup is correctly placed when the current system locale is
one of RTL locales, layoutDirection="ltr" is needed in the SDK version 17+. -->
<org.dslul.openboard.inputmethod.latin.suggestions.SuggestionStripView
android:id="@+id/suggestion_strip_view"
android:layoutDirection="ltr"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
style="?attr/suggestionStripViewStyle" />
<LinearLayout
android:id="@+id/emoji_tab_strip"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
style="?attr/suggestionStripViewStyle"
>
<org.dslul.openboard.inputmethod.compat.TabHostCompat
android:id="@+id/emoji_category_tabhost"
android:layout_width="0dip"
android:layout_weight="87.5"
android:layout_height="match_parent"
>
<TabWidget
android:id="@android:id/tabs"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="@null" />
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="0dip"
android:layout_height="0dip"
>
<!-- Empty placeholder that TabHost requires. But we don't use it to actually
display anything. We monitor the tab changes and change the ViewPager.
Similarly the ViewPager swipes are intercepted and passed to the TabHost. -->
<View
android:id="@+id/emoji_keyboard_dummy"
android:layout_width="0dip"
android:layout_height="0dip"
android:visibility="gone" />
</FrameLayout>
</org.dslul.openboard.inputmethod.compat.TabHostCompat>
</LinearLayout>
</FrameLayout>