mirror of
https://github.com/Helium314/HeliBoard.git
synced 2025-06-04 05:40:17 +00:00
Allow resizing emoji and clipboard views in one-handed mode (#337)
This commit is contained in:
parent
9a62d85dbf
commit
9f21f540af
19 changed files with 195 additions and 146 deletions
|
@ -7,9 +7,13 @@
|
|||
package org.dslul.openboard.inputmethod.compat;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.util.AttributeSet;
|
||||
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
|
||||
* 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) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,12 +49,12 @@ public class Keyboard {
|
|||
/** Total height of the keyboard, including the padding and keys */
|
||||
public final int mOccupiedHeight;
|
||||
/** 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 */
|
||||
public final int mBaseHeight;
|
||||
/** Base width of the keyboard, used to calculate keys' width */
|
||||
public final int mBaseWidth;
|
||||
public int mBaseWidth;
|
||||
|
||||
/** The padding above the keyboard */
|
||||
public final int mTopPadding;
|
||||
|
|
|
@ -46,6 +46,8 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
|
|||
private View mMainKeyboardFrame;
|
||||
private MainKeyboardView mKeyboardView;
|
||||
private EmojiPalettesView mEmojiPalettesView;
|
||||
private View mEmojiTabStripView;
|
||||
private View mSuggestionStripView;
|
||||
private ClipboardHistoryView mClipboardHistoryView;
|
||||
private LatinIME mLatinIME;
|
||||
private RichInputMethodManager mRichImm;
|
||||
|
@ -272,8 +274,7 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
|
|||
private void setMainKeyboardFrame(
|
||||
@NonNull final SettingsValues settingsValues,
|
||||
@NonNull final KeyboardSwitchState toggleState) {
|
||||
final int visibility = isImeSuppressedByHardwareKeyboard(settingsValues, toggleState)
|
||||
? View.GONE : View.VISIBLE;
|
||||
final int visibility = isImeSuppressedByHardwareKeyboard(settingsValues, toggleState) ? View.GONE : View.VISIBLE;
|
||||
mKeyboardView.setVisibility(visibility);
|
||||
// The visibility of {@link #mKeyboardView} must be aligned with {@link #MainKeyboardFrame}.
|
||||
// @see #getVisibleKeyboardView() and
|
||||
|
@ -281,6 +282,8 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
|
|||
mMainKeyboardFrame.setVisibility(visibility);
|
||||
mEmojiPalettesView.setVisibility(View.GONE);
|
||||
mEmojiPalettesView.stopEmojiPalettes();
|
||||
mEmojiTabStripView.setVisibility(View.GONE);
|
||||
mSuggestionStripView.setVisibility(View.VISIBLE);
|
||||
mClipboardHistoryView.setVisibility(View.GONE);
|
||||
mClipboardHistoryView.stopClipboardHistory();
|
||||
}
|
||||
|
@ -292,11 +295,14 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
|
|||
Log.d(TAG, "setEmojiKeyboard");
|
||||
}
|
||||
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}.
|
||||
// @see #getVisibleKeyboardView() and
|
||||
// @see LatinIME#onComputeInset(android.inputmethodservice.InputMethodService.Insets)
|
||||
mKeyboardView.setVisibility(View.GONE);
|
||||
mSuggestionStripView.setVisibility(View.GONE);
|
||||
mEmojiTabStripView.setVisibility(View.VISIBLE);
|
||||
mClipboardHistoryView.setVisibility(View.GONE);
|
||||
mEmojiPalettesView.startEmojiPalettes(
|
||||
mKeyboardLayoutSet.mLocaleKeyTexts.getLabelAlphabet(),
|
||||
mKeyboardView.getKeyVisualAttribute(), keyboard.mIconsSet);
|
||||
|
@ -310,11 +316,14 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
|
|||
Log.d(TAG, "setClipboardKeyboard");
|
||||
}
|
||||
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}.
|
||||
// @see #getVisibleKeyboardView() and
|
||||
// @see LatinIME#onComputeInset(android.inputmethodservice.InputMethodService.Insets)
|
||||
mKeyboardView.setVisibility(View.GONE);
|
||||
mEmojiTabStripView.setVisibility(View.GONE);
|
||||
mSuggestionStripView.setVisibility(View.VISIBLE);
|
||||
mEmojiPalettesView.setVisibility(View.GONE);
|
||||
mClipboardHistoryView.startClipboardHistory(
|
||||
mLatinIME.getClipboardHistoryManager(),
|
||||
mKeyboardLayoutSet.mLocaleKeyTexts.getLabelAlphabet(),
|
||||
|
@ -429,15 +438,23 @@ 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);
|
||||
|
||||
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(),
|
||||
mLatinIME.getCurrentAutoCapsState(), mLatinIME.getCurrentRecapitalizeState());
|
||||
if (wasEmoji)
|
||||
setEmojiKeyboard();
|
||||
else if (wasClipboard) {
|
||||
setClipboardKeyboard();
|
||||
}
|
||||
}
|
||||
|
||||
// Implements {@link KeyboardState.SwitchActions}.
|
||||
|
@ -499,9 +516,17 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
|
|||
} else if (isShowingClipboardHistory()) {
|
||||
return mClipboardHistoryView;
|
||||
}
|
||||
return mKeyboardView;
|
||||
}
|
||||
|
||||
public View getWrapperView() {
|
||||
return mKeyboardViewWrapper;
|
||||
}
|
||||
|
||||
public View getEmojiTabStrip() {
|
||||
return mEmojiTabStripView;
|
||||
}
|
||||
|
||||
public MainKeyboardView getMainKeyboardView() {
|
||||
return mKeyboardView;
|
||||
}
|
||||
|
@ -540,6 +565,9 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
|
|||
mEmojiPalettesView.setKeyboardActionListener(mLatinIME);
|
||||
mClipboardHistoryView.setHardwareAcceleratedDrawingEnabled(isHardwareAcceleratedDrawingEnabled);
|
||||
mClipboardHistoryView.setKeyboardActionListener(mLatinIME);
|
||||
mEmojiTabStripView = mCurrentInputView.findViewById(R.id.emoji_tab_strip);
|
||||
mSuggestionStripView = mCurrentInputView.findViewById(R.id.suggestion_strip_view);
|
||||
mEmojiPalettesView.initialStart();
|
||||
|
||||
return mCurrentInputView;
|
||||
}
|
||||
|
|
|
@ -213,12 +213,7 @@ public class KeyboardView extends View {
|
|||
}
|
||||
|
||||
mKeyboard = keyboard;
|
||||
final SettingsValues sv = Settings.getInstance().getCurrent();
|
||||
// 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);
|
||||
mKeyScaleForText = (float) Math.sqrt(1 / Settings.getInstance().getCurrent().mKeyboardHeightScale);
|
||||
final int scaledKeyHeight = (int) ((keyboard.mMostCommonKeyHeight - keyboard.mVerticalGap) * mKeyScaleForText);
|
||||
mKeyDrawParams.updateParams(scaledKeyHeight, mKeyVisualAttributes);
|
||||
mKeyDrawParams.updateParams(scaledKeyHeight, keyboard.mKeyVisualAttributes);
|
||||
|
@ -362,6 +357,7 @@ public class KeyboardView extends View {
|
|||
canvas.translate(keyDrawX, keyDrawY);
|
||||
|
||||
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);
|
||||
params.mAnimAlpha = Constants.Color.ALPHA_OPAQUE;
|
||||
|
||||
|
|
|
@ -56,14 +56,16 @@ class ClipboardHistoryView @JvmOverloads constructor(
|
|||
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) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
|
||||
val res = context.resources
|
||||
// The main keyboard expands to the entire this {@link KeyboardView}.
|
||||
val width = (ResourceUtils.getDefaultKeyboardWidth(res) + paddingLeft + paddingRight)
|
||||
val height = (ResourceUtils.getKeyboardHeight(res, Settings.getInstance().current)
|
||||
+ res.getDimensionPixelSize(R.dimen.config_suggestions_strip_height)
|
||||
+ paddingTop + paddingBottom)
|
||||
val width = ResourceUtils.getKeyboardWidth(res, Settings.getInstance().current) + paddingLeft + paddingRight
|
||||
val height = ResourceUtils.getKeyboardHeight(res, Settings.getInstance().current) + paddingTop + paddingBottom
|
||||
findViewById<FrameLayout>(R.id.clipboard_action_bar)?.layoutParams?.width = width
|
||||
setMeasuredDimension(width, height)
|
||||
}
|
||||
|
||||
|
@ -154,6 +156,7 @@ class ClipboardHistoryView @JvmOverloads constructor(
|
|||
}
|
||||
clipboardRecyclerView.apply {
|
||||
adapter = clipboardAdapter
|
||||
layoutParams.width = ResourceUtils.getKeyboardWidth(context.resources, Settings.getInstance().current)
|
||||
}
|
||||
Settings.getInstance().current.mColors.setBackground(this, ColorType.CLIPBOARD_BACKGROUND)
|
||||
}
|
||||
|
|
|
@ -26,8 +26,7 @@ class ClipboardLayoutParams(res: Resources) {
|
|||
|
||||
init {
|
||||
val defaultKeyboardHeight = ResourceUtils.getKeyboardHeight(res, Settings.getInstance().current)
|
||||
val suggestionStripHeight = res.getDimensionPixelSize(R.dimen.config_suggestions_strip_height)
|
||||
val defaultKeyboardWidth = ResourceUtils.getDefaultKeyboardWidth(res)
|
||||
val defaultKeyboardWidth = ResourceUtils.getKeyboardWidth(res, Settings.getInstance().current)
|
||||
|
||||
if (Settings.getInstance().current.mNarrowKeyGaps) {
|
||||
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,
|
||||
defaultKeyboardHeight, defaultKeyboardHeight).toInt()
|
||||
|
||||
actionBarHeight = (defaultKeyboardHeight - bottomPadding - topPadding) / DEFAULT_KEYBOARD_ROWS - keyVerticalGap / 2
|
||||
listHeight = defaultKeyboardHeight + suggestionStripHeight - actionBarHeight - bottomPadding
|
||||
val rowCount = DEFAULT_KEYBOARD_ROWS + if (Settings.getInstance().current.mShowsNumberRow) 1 else 0
|
||||
actionBarHeight = (defaultKeyboardHeight - bottomPadding - topPadding) / rowCount - keyVerticalGap / 2
|
||||
listHeight = defaultKeyboardHeight - actionBarHeight - bottomPadding
|
||||
}
|
||||
|
||||
fun setListProperties(recycler: RecyclerView) {
|
||||
|
|
|
@ -49,19 +49,33 @@ final class DynamicGridKeyboard extends Keyboard {
|
|||
private List<Key> mCachedGridKeys;
|
||||
|
||||
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);
|
||||
// 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 key1 = getTemplateKey(TEMPLATE_KEY_CODE_1);
|
||||
mHorizontalGap = Math.abs(key1.getX() - key0.getX()) - key0.getWidth();
|
||||
mHorizontalStep = key0.getWidth() + mHorizontalGap;
|
||||
mVerticalStep = key0.getHeight() + mVerticalGap;
|
||||
final int horizontalGap = Math.abs(key1.getX() - key0.getX()) - key0.getWidth();
|
||||
final float widthScale = determineWidthScale(key0.getWidth() + horizontalGap);
|
||||
mHorizontalGap = (int) (horizontalGap * widthScale);
|
||||
mHorizontalStep = (int) ((key0.getWidth() + horizontalGap) * widthScale);
|
||||
mVerticalStep = (int) ((key0.getHeight() + mVerticalGap) / Math.sqrt(Settings.getInstance().getCurrent().mKeyboardHeightScale));
|
||||
mColumnsNum = mBaseWidth / mHorizontalStep;
|
||||
mMaxKeyCount = maxKeyCount;
|
||||
mIsRecents = categoryId == EmojiCategory.ID_RECENTS;
|
||||
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) {
|
||||
for (final Key key : super.getSortedKeys()) {
|
||||
if (key.getCode() == code) {
|
||||
|
|
|
@ -20,6 +20,7 @@ import org.dslul.openboard.inputmethod.keyboard.KeyboardId;
|
|||
import org.dslul.openboard.inputmethod.keyboard.KeyboardLayoutSet;
|
||||
import org.dslul.openboard.inputmethod.latin.R;
|
||||
import org.dslul.openboard.inputmethod.latin.settings.Settings;
|
||||
import org.dslul.openboard.inputmethod.latin.utils.ResourceUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
@ -118,8 +119,7 @@ final class EmojiCategory {
|
|||
private final HashMap<String, Integer> mCategoryNameToIdMap = new HashMap<>();
|
||||
private final int[] mCategoryTabIconId = new int[sCategoryName.length];
|
||||
private final ArrayList<CategoryProperties> mShownCategories = new ArrayList<>();
|
||||
private final ConcurrentHashMap<Long, DynamicGridKeyboard> mCategoryKeyboardMap =
|
||||
new ConcurrentHashMap<>();
|
||||
private final ConcurrentHashMap<Long, DynamicGridKeyboard> mCategoryKeyboardMap = new ConcurrentHashMap<>();
|
||||
|
||||
private int mCurrentCategoryId = EmojiCategory.ID_UNSPECIFIED;
|
||||
private int mCurrentCategoryPageId = 0;
|
||||
|
@ -132,8 +132,7 @@ final class EmojiCategory {
|
|||
mLayoutSet = layoutSet;
|
||||
for (int i = 0; i < sCategoryName.length; ++i) {
|
||||
mCategoryNameToIdMap.put(sCategoryName[i], i);
|
||||
mCategoryTabIconId[i] = emojiPaletteViewAttr.getResourceId(
|
||||
sCategoryTabIconAttr[i], 0);
|
||||
mCategoryTabIconId[i] = emojiPaletteViewAttr.getResourceId(sCategoryTabIconAttr[i], 0);
|
||||
}
|
||||
|
||||
int defaultCategoryId = EmojiCategory.ID_SMILEYS_EMOTION;
|
||||
|
@ -168,6 +167,10 @@ final class EmojiCategory {
|
|||
}
|
||||
}
|
||||
|
||||
public void clearKeyboardCache() {
|
||||
mCategoryKeyboardMap.clear();
|
||||
}
|
||||
|
||||
private void addShownCategoryId(final int categoryId) {
|
||||
// Load a keyboard of categoryId
|
||||
final CategoryProperties properties = new CategoryProperties(categoryId);
|
||||
|
@ -294,10 +297,11 @@ final class EmojiCategory {
|
|||
return mCategoryKeyboardMap.get(categoryKeyboardMapKey);
|
||||
}
|
||||
|
||||
final int currentWidth = ResourceUtils.getKeyboardWidth(mRes, Settings.getInstance().getCurrent());
|
||||
if (categoryId == EmojiCategory.ID_RECENTS) {
|
||||
final DynamicGridKeyboard kbd = new DynamicGridKeyboard(mPrefs,
|
||||
mLayoutSet.getKeyboard(KeyboardId.ELEMENT_EMOJI_RECENTS),
|
||||
mMaxRecentsKeyCount, categoryId);
|
||||
mMaxRecentsKeyCount, categoryId, currentWidth);
|
||||
mCategoryKeyboardMap.put(categoryKeyboardMapKey, kbd);
|
||||
return kbd;
|
||||
}
|
||||
|
@ -309,15 +313,14 @@ final class EmojiCategory {
|
|||
for (int pageId = 0; pageId < sortedKeysPages.length; ++pageId) {
|
||||
final DynamicGridKeyboard tempKeyboard = new DynamicGridKeyboard(mPrefs,
|
||||
mLayoutSet.getKeyboard(KeyboardId.ELEMENT_EMOJI_RECENTS),
|
||||
keyCountPerPage, categoryId);
|
||||
keyCountPerPage, categoryId, currentWidth);
|
||||
for (final Key emojiKey : sortedKeysPages[pageId]) {
|
||||
if (emojiKey == null) {
|
||||
break;
|
||||
}
|
||||
tempKeyboard.addKeyLast(emojiKey);
|
||||
}
|
||||
mCategoryKeyboardMap.put(
|
||||
getCategoryKeyboardMapKey(categoryId, pageId), tempKeyboard);
|
||||
mCategoryKeyboardMap.put(getCategoryKeyboardMapKey(categoryId, pageId), tempKeyboard);
|
||||
}
|
||||
return mCategoryKeyboardMap.get(categoryKeyboardMapKey);
|
||||
}
|
||||
|
@ -326,7 +329,7 @@ final class EmojiCategory {
|
|||
private int computeMaxKeyCountPerPage() {
|
||||
final DynamicGridKeyboard tempKeyboard = new DynamicGridKeyboard(mPrefs,
|
||||
mLayoutSet.getKeyboard(KeyboardId.ELEMENT_EMOJI_RECENTS),
|
||||
0, 0);
|
||||
0, 0, ResourceUtils.getKeyboardWidth(mRes, Settings.getInstance().getCurrent()));
|
||||
return MAX_LINE_COUNT_PER_PAGE * tempKeyboard.getColumnsCount();
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ final class EmojiLayoutParams {
|
|||
public EmojiLayoutParams(final Resources res) {
|
||||
final SettingsValues settingsValues = Settings.getInstance().getCurrent();
|
||||
final int defaultKeyboardHeight = ResourceUtils.getKeyboardHeight(res, settingsValues);
|
||||
final int defaultKeyboardWidth = ResourceUtils.getDefaultKeyboardWidth(res);
|
||||
final int defaultKeyboardWidth = ResourceUtils.getKeyboardWidth(res, settingsValues);
|
||||
if (settingsValues.mNarrowKeyGaps) {
|
||||
mKeyVerticalGap = (int) res.getFraction(R.fraction.config_key_vertical_gap_holo_narrow,
|
||||
defaultKeyboardHeight, defaultKeyboardHeight);
|
||||
|
@ -77,6 +77,7 @@ final class EmojiLayoutParams {
|
|||
public void setActionBarProperties(final LinearLayout ll) {
|
||||
final LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) ll.getLayoutParams();
|
||||
lp.height = getActionBarHeight();
|
||||
lp.width = ResourceUtils.getKeyboardWidth(ll.getResources(), Settings.getInstance().getCurrent());
|
||||
ll.setLayoutParams(lp);
|
||||
}
|
||||
|
||||
|
|
|
@ -110,8 +110,7 @@ public final class EmojiPageKeyboardView extends KeyboardView implements
|
|||
final Keyboard keyboard = getKeyboard();
|
||||
if (keyboard instanceof DynamicGridKeyboard) {
|
||||
final int width = keyboard.mOccupiedWidth + getPaddingLeft() + getPaddingRight();
|
||||
final int occupiedHeight =
|
||||
((DynamicGridKeyboard) keyboard).getDynamicOccupiedHeight();
|
||||
final int occupiedHeight = ((DynamicGridKeyboard) keyboard).getDynamicOccupiedHeight();
|
||||
final int height = occupiedHeight + getPaddingTop() + getPaddingBottom();
|
||||
setMeasuredDimension(width, height);
|
||||
return;
|
||||
|
@ -185,8 +184,7 @@ public final class EmojiPageKeyboardView extends KeyboardView implements
|
|||
}
|
||||
|
||||
final View container = mMoreKeysKeyboardContainer;
|
||||
final MoreKeysKeyboardView moreKeysKeyboardView =
|
||||
container.findViewById(R.id.more_keys_keyboard_view);
|
||||
final MoreKeysKeyboardView moreKeysKeyboardView = container.findViewById(R.id.more_keys_keyboard_view);
|
||||
moreKeysKeyboardView.setKeyboard(moreKeysKeyboard);
|
||||
container.measure(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
|
||||
|
@ -198,8 +196,7 @@ public final class EmojiPageKeyboardView extends KeyboardView implements
|
|||
? CoordinateUtils.x(lastCoords)
|
||||
: key.getX() + key.getWidth() / 2;
|
||||
final int pointY = key.getY();
|
||||
moreKeysKeyboardView.showMoreKeysPanel(this, this,
|
||||
pointX, pointY, mListener);
|
||||
moreKeysKeyboardView.showMoreKeysPanel(this, this, pointX, pointY, mListener);
|
||||
return moreKeysKeyboardView;
|
||||
}
|
||||
|
||||
|
@ -253,10 +250,8 @@ public final class EmojiPageKeyboardView extends KeyboardView implements
|
|||
*/
|
||||
@Override
|
||||
public boolean onHoverEvent(final MotionEvent event) {
|
||||
final KeyboardAccessibilityDelegate<EmojiPageKeyboardView> accessibilityDelegate =
|
||||
mAccessibilityDelegate;
|
||||
if (accessibilityDelegate != null
|
||||
&& AccessibilityUtils.Companion.getInstance().isTouchExplorationEnabled()) {
|
||||
final KeyboardAccessibilityDelegate<EmojiPageKeyboardView> accessibilityDelegate = mAccessibilityDelegate;
|
||||
if (accessibilityDelegate != null && AccessibilityUtils.Companion.getInstance().isTouchExplorationEnabled()) {
|
||||
return accessibilityDelegate.onHoverEvent(event);
|
||||
}
|
||||
return super.onHoverEvent(event);
|
||||
|
@ -387,12 +382,7 @@ public final class EmojiPageKeyboardView extends KeyboardView implements
|
|||
} else if (key == currentKey && pendingKeyDown != null) {
|
||||
pendingKeyDown.run();
|
||||
// Trigger key-release event a little later so that a user can see visual feedback.
|
||||
mHandler.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
callListenerOnReleaseKey(key, true /* withRegistering */);
|
||||
}
|
||||
}, KEY_RELEASE_DELAY_TIME);
|
||||
mHandler.postDelayed(() -> callListenerOnReleaseKey(key, true), KEY_RELEASE_DELAY_TIME);
|
||||
} else if (key != null) {
|
||||
callListenerOnReleaseKey(key, true /* withRegistering */);
|
||||
}
|
||||
|
@ -402,7 +392,7 @@ public final class EmojiPageKeyboardView extends KeyboardView implements
|
|||
}
|
||||
|
||||
public boolean onCancel(final MotionEvent e) {
|
||||
releaseCurrentKey(false /* withKeyRegistering */);
|
||||
releaseCurrentKey(false);
|
||||
dismissMoreKeysPanel();
|
||||
cancelLongPress();
|
||||
return true;
|
||||
|
@ -417,7 +407,7 @@ public final class EmojiPageKeyboardView extends KeyboardView implements
|
|||
// Touched key has changed, release previous key's callbacks and
|
||||
// re-register them for the new key.
|
||||
if (key != mCurrentKey && !isShowingMoreKeysPanel) {
|
||||
releaseCurrentKey(false /* withKeyRegistering */);
|
||||
releaseCurrentKey(false);
|
||||
mCurrentKey = key;
|
||||
if (key == null) {
|
||||
return false;
|
||||
|
|
|
@ -30,6 +30,7 @@ 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;
|
||||
import org.dslul.openboard.inputmethod.keyboard.KeyboardSwitcher;
|
||||
import org.dslul.openboard.inputmethod.keyboard.KeyboardView;
|
||||
import org.dslul.openboard.inputmethod.keyboard.internal.KeyDrawParams;
|
||||
import org.dslul.openboard.inputmethod.keyboard.internal.KeyVisualAttributes;
|
||||
|
@ -108,7 +109,7 @@ public final class EmojiPalettesView extends LinearLayout
|
|||
final Resources res = context.getResources();
|
||||
mEmojiLayoutParams = new EmojiLayoutParams(res);
|
||||
builder.setSubtype(RichInputMethodSubtype.getEmojiSubtype());
|
||||
builder.setKeyboardGeometry(ResourceUtils.getDefaultKeyboardWidth(res),
|
||||
builder.setKeyboardGeometry(ResourceUtils.getKeyboardWidth(res, Settings.getInstance().getCurrent()),
|
||||
mEmojiLayoutParams.mEmojiKeyboardHeight);
|
||||
final KeyboardLayoutSet layoutSet = builder.build();
|
||||
final TypedArray emojiPalettesViewAttr = context.obtainStyledAttributes(attrs,
|
||||
|
@ -133,10 +134,9 @@ public final class EmojiPalettesView extends LinearLayout
|
|||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
final Resources res = getContext().getResources();
|
||||
// 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();
|
||||
final int height = ResourceUtils.getKeyboardHeight(res, Settings.getInstance().getCurrent())
|
||||
+ res.getDimensionPixelSize(R.dimen.config_suggestions_strip_height)
|
||||
+ getPaddingTop() + getPaddingBottom();
|
||||
setMeasuredDimension(width, height);
|
||||
}
|
||||
|
@ -155,14 +155,10 @@ public final class EmojiPalettesView extends LinearLayout
|
|||
host.addTab(tspec);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
|
||||
mTabHost = findViewById(R.id.emoji_category_tabhost);
|
||||
public void initialStart() { // needs to be delayed for access to EmojiTabStrip, which is not a child of this view
|
||||
mTabHost = KeyboardSwitcher.getInstance().getEmojiTabStrip().findViewById(R.id.emoji_category_tabhost);
|
||||
mTabHost.setup();
|
||||
for (final EmojiCategory.CategoryProperties properties
|
||||
: mEmojiCategory.getShownCategories()) {
|
||||
for (final EmojiCategory.CategoryProperties properties : mEmojiCategory.getShownCategories()) {
|
||||
addTab(mTabHost, properties.mCategoryId);
|
||||
}
|
||||
mTabHost.setOnTabChangedListener(this);
|
||||
|
@ -226,9 +222,6 @@ public final class EmojiPalettesView extends LinearLayout
|
|||
// Enable reselection after the first setCurrentCategoryAndPageId() init call
|
||||
mTabHost.setFireOnTabChangeListenerOnReselection(true);
|
||||
|
||||
final LinearLayout actionBar = findViewById(R.id.emoji_action_bar);
|
||||
mEmojiLayoutParams.setActionBarProperties(actionBar);
|
||||
|
||||
// deleteKey depends only on OnTouchListener.
|
||||
mDeleteKey = findViewById(R.id.emoji_keyboard_delete);
|
||||
mDeleteKey.setBackgroundResource(mFunctionalKeyBackgroundId);
|
||||
|
@ -378,6 +371,7 @@ public final class EmojiPalettesView extends LinearLayout
|
|||
if (deleteIconResId != 0) {
|
||||
mDeleteKey.setImageResource(deleteIconResId);
|
||||
}
|
||||
mEmojiLayoutParams.setActionBarProperties(findViewById(R.id.emoji_action_bar));
|
||||
final KeyDrawParams params = new KeyDrawParams();
|
||||
params.updateParams(mEmojiLayoutParams.getActionBarHeight(), keyVisualAttr);
|
||||
setupAlphabetKey(mAlphabetKeyLeft, switchToAlphaLabel, params);
|
||||
|
@ -480,4 +474,8 @@ public final class EmojiPalettesView extends LinearLayout
|
|||
v.setPressed(false);
|
||||
}
|
||||
}
|
||||
|
||||
public void clearKeyboardCache() {
|
||||
mEmojiCategory.clearKeyboardCache();
|
||||
}
|
||||
}
|
|
@ -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.StringUtils
|
||||
import org.dslul.openboard.inputmethod.latin.settings.Settings
|
||||
import kotlin.math.round
|
||||
import org.dslul.openboard.inputmethod.latin.utils.ResourceUtils
|
||||
import kotlin.math.sqrt
|
||||
|
||||
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)
|
||||
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()
|
||||
// extra scale for height only, to undo the effect of number row increasing absolute key height
|
||||
// todo: with this things look ok, but number row still slightly affects emoji size (which it should not)
|
||||
val numScale = if (Settings.getInstance().current.mShowsNumberRow) 1.25f else 1f
|
||||
// determine key width for default settings (no number row, no one-handed mode, 100% height and bottom padding scale)
|
||||
// this is a bit long, but ensures that emoji size stays the same, independent of these settings
|
||||
val defaultKeyWidth = (ResourceUtils.getDefaultKeyboardWidth(context.resources) - params.mLeftPadding - params.mRightPadding) * params.mDefaultRelativeKeyWidth
|
||||
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 ->
|
||||
val keyParams = parseEmojiKey(codeArraySpec, moreEmojisArray?.get(i)?.takeIf { it.isNotEmpty() }) ?: return@forEachIndexed
|
||||
keyParams.setDimensionsFromRelativeSize(currentX, currentY)
|
||||
keyParams.mFullHeight /= numScale
|
||||
keyParams.mFullWidth *= widthScale
|
||||
keyParams.xPos = currentX
|
||||
keyParams.yPos = currentY
|
||||
keyParams.mFullWidth = keyWidth
|
||||
keyParams.mFullHeight = keyHeight
|
||||
currentX += keyParams.mFullWidth
|
||||
row.add(keyParams)
|
||||
// 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)
|
||||
}
|
||||
|
||||
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>? {
|
||||
val specAndSdk = spec.split("||")
|
||||
if (specAndSdk.getOrNull(1)?.toIntOrNull()?.let { it > Build.VERSION.SDK_INT } == true) return null
|
||||
|
|
|
@ -5,7 +5,6 @@ package org.dslul.openboard.inputmethod.latin
|
|||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.res.Configuration
|
||||
import android.graphics.Color
|
||||
import android.util.AttributeSet
|
||||
import android.view.Gravity
|
||||
import android.view.MotionEvent
|
||||
|
@ -13,6 +12,7 @@ import android.view.View
|
|||
import android.widget.FrameLayout
|
||||
import android.widget.ImageButton
|
||||
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.Constants
|
||||
import org.dslul.openboard.inputmethod.latin.settings.Settings
|
||||
|
@ -29,7 +29,6 @@ class KeyboardWrapperView @JvmOverloads constructor(
|
|||
|
||||
private lateinit var stopOneHandedModeBtn: ImageButton
|
||||
private lateinit var switchOneHandedModeBtn: ImageButton
|
||||
private lateinit var keyboardView: View
|
||||
private lateinit var resizeOneHandedModeBtn: ImageButton
|
||||
private val iconStopOneHandedModeId: Int
|
||||
private val iconSwitchOneHandedModeId: Int
|
||||
|
@ -62,7 +61,6 @@ class KeyboardWrapperView @JvmOverloads constructor(
|
|||
resizeOneHandedModeBtn = findViewById(R.id.btn_resize_one_handed_mode)
|
||||
resizeOneHandedModeBtn.setImageResource(iconResizeOneHandedModeId)
|
||||
resizeOneHandedModeBtn.visibility = GONE
|
||||
keyboardView = findViewById(R.id.keyboard_view)
|
||||
|
||||
stopOneHandedModeBtn.setOnClickListener(this)
|
||||
switchOneHandedModeBtn.setOnClickListener(this)
|
||||
|
@ -141,6 +139,7 @@ class KeyboardWrapperView @JvmOverloads constructor(
|
|||
|
||||
val isLeftGravity = oneHandedGravity == Gravity.LEFT
|
||||
val width = right - left
|
||||
val keyboardView = KeyboardSwitcher.getInstance().visibleKeyboardView
|
||||
val spareWidth = width - keyboardView.measuredWidth
|
||||
|
||||
val keyboardLeft = if (isLeftGravity) 0 else spareWidth
|
||||
|
|
|
@ -1248,7 +1248,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
if (mInputView == null) {
|
||||
return;
|
||||
}
|
||||
final View visibleKeyboardView = mKeyboardSwitcher.getVisibleKeyboardView();
|
||||
final View visibleKeyboardView = mKeyboardSwitcher.getWrapperView();
|
||||
if (visibleKeyboardView == null || !hasSuggestionStripView()) {
|
||||
return;
|
||||
}
|
||||
|
@ -1261,11 +1261,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
mInsetsUpdater.setInsets(outInsets);
|
||||
return;
|
||||
}
|
||||
final int suggestionsHeight = (!mKeyboardSwitcher.isShowingEmojiPalettes()
|
||||
&& !mKeyboardSwitcher.isShowingClipboardHistory()
|
||||
&& mSuggestionStripView.getVisibility() == View.VISIBLE)
|
||||
? mSuggestionStripView.getHeight() : 0;
|
||||
final int visibleTopY = inputHeight - visibleKeyboardView.getHeight() - suggestionsHeight;
|
||||
final int visibleTopY = inputHeight - visibleKeyboardView.getHeight() - mSuggestionStripView.getHeight();
|
||||
mSuggestionStripView.setMoreSuggestionsHeight(visibleTopY);
|
||||
// Need to set expanded touchable region only if a keyboard view is being shown.
|
||||
if (visibleKeyboardView.isShown()) {
|
||||
|
|
|
@ -192,7 +192,7 @@ public final class ResourceUtils {
|
|||
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 float keyboardHeight = res.getDimension(R.dimen.config_default_keyboard_height) * (showsNumberRow ? 1.25f : 1f);
|
||||
final float maxKeyboardHeight = res.getFraction(
|
||||
|
|
|
@ -14,40 +14,6 @@
|
|||
android:visibility="gone"
|
||||
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
|
||||
android:id="@+id/emoji_keyboard_list"
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -13,10 +13,4 @@
|
|||
<include
|
||||
android:id="@+id/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>
|
||||
|
|
|
@ -12,15 +12,9 @@
|
|||
android:layout_gravity="bottom"
|
||||
android:orientation="vertical" >
|
||||
|
||||
<!-- 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="@dimen/config_suggestions_strip_height"
|
||||
android:gravity="center_vertical"
|
||||
style="?attr/suggestionStripViewStyle" />
|
||||
<include
|
||||
android:id="@+id/strip_container"
|
||||
layout="@layout/strip_container" />
|
||||
|
||||
<!-- 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+. -->
|
||||
|
@ -35,6 +29,12 @@
|
|||
android:layoutDirection="ltr"
|
||||
android:layout_width="match_parent"
|
||||
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
|
||||
android:id="@+id/btn_stop_one_handed_mode"
|
||||
|
|
55
app/src/main/res/layout/strip_container.xml
Normal file
55
app/src/main/res/layout/strip_container.xml
Normal 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>
|
Loading…
Add table
Add a link
Reference in a new issue