properly set relative key(board) params

This commit is contained in:
Helium314 2023-10-27 13:19:57 +02:00
parent 1916eb233f
commit 309f121848
5 changed files with 158 additions and 113 deletions

View file

@ -938,18 +938,10 @@ public class Key implements Comparable<Key> {
public static class KeyParams { public static class KeyParams {
// params for building // params for building
boolean isSpacer; boolean isSpacer;
// relative values and absolute keyboard dimensions for re-determining key dimensions (if necessary) private final KeyboardParams mParams; // for reading gaps and keyboard width / height
/* public float mRelativeWidth; // also allows -1f as value, this means "fill right"
// todo: currently commented because not used, but planned (see todo below) public float mRelativeHeight; // also allows negative values, indicating absolute height is defined
public int keyboardWidth;
public int keyboardHeight;
// relative widths and heights may not add up to 100% when including gaps
// this is ok with fill right, but otherwise?
public float mRelativeWidth; // also allow -1f as value, this means "fill right"
public float mRelativeHeight;
public float mRelativeHorizontalGap;
public float mRelativeVerticalGap;
*/
// stuff that likely remains after constructor, maybe make final // stuff that likely remains after constructor, maybe make final
final int mCode; final int mCode;
@Nullable final String mLabel; @Nullable final String mLabel;
@ -964,13 +956,13 @@ public class Key implements Comparable<Key> {
@Nullable final OptionalAttributes mOptionalAttributes; @Nullable final OptionalAttributes mOptionalAttributes;
public boolean mEnabled = true; public boolean mEnabled = true;
// stuff that may very well change, or only be set just before it's needed // stuff that may very well change
int mWidth; private int mWidth;
int mHeight; private int mHeight;
int mHorizontalGap; private int mHorizontalGap;
int mVerticalGap; private int mVerticalGap;
float xPos; private float xPos;
int yPos; private int yPos;
public static KeyParams newSpacer(final TypedArray keyAttr, final KeyStyle keyStyle, public static KeyParams newSpacer(final TypedArray keyAttr, final KeyStyle keyStyle,
final KeyboardParams params, final XmlKeyboardRow row) { final KeyboardParams params, final XmlKeyboardRow row) {
@ -984,26 +976,33 @@ public class Key implements Comparable<Key> {
return new Key(this); return new Key(this);
} }
// todo: // todo: use it
// get relativeWidth and others when creating the params // first for inserting spacers to get a split keyboard
// check how relative width could be adjusted // any use for adjusting width or height?
// there is the fillRight thing // width is already more or less done with one-handed mode, but this could be more flexible
// and not sure if there is a spacer on the left side if the key starts not directly at the edge // height is already implemented via the setting
// then it should be possible to re-create the entire keyboard using the new dimensions // any use in combination with number row?
// can add keys (spacer) in a row, for split keyboard // when completely replacing number row stuff, also moreKeys stuff would need to be adjusted
/* public void setDimensionsFromRelativeSize(final int newX, final int newY) {
public void setDimensionsFromRelativeSize() { if (mRelativeHeight == 0 || mRelativeWidth == 0)
if (keyboardHeight == 0 || keyboardWidth == 0 || mRelativeHeight == 0 || mRelativeWidth == 0)
throw new IllegalStateException("can't use setUsingRelativeHeight, not all fields are set"); throw new IllegalStateException("can't use setUsingRelativeHeight, not all fields are set");
float horizontalGap = isSpacer ? 0f : mRelativeHorizontalGap * keyboardWidth; if (mRelativeHeight < 0)
throw new IllegalStateException("can't (yet) deal with absolute height"); // todo: decide... maybe just use it and deal with it properly when it needs to be adjusted?
xPos = newX;
yPos = newY;
float horizontalGap = isSpacer ? 0f : mParams.mRelativeHorizontalGap * mParams.mId.mWidth; // gap width / height is based on params.mId.height / width
float verticalGap = mParams.mRelativeVerticalGap * mParams.mId.mHeight;
mHorizontalGap = (int) horizontalGap; mHorizontalGap = (int) horizontalGap;
float verticalGap = mRelativeVerticalGap * mRelativeHeight;
mVerticalGap = (int) verticalGap; mVerticalGap = (int) verticalGap;
float keyWidth = mRelativeWidth * keyboardWidth; float keyWidth;
if (mRelativeWidth > 0)
keyWidth = mRelativeWidth * mParams.mBaseWidth; // key width / height is based on params.mBaseHeight / width
else // fillRight
keyWidth = (mParams.mOccupiedWidth - mParams.mRightPadding) - xPos; // right keyboard edge - x
mWidth = Math.round(keyWidth - horizontalGap); mWidth = Math.round(keyWidth - horizontalGap);
mHeight = (int) (mRelativeHeight * keyboardHeight - verticalGap); mHeight = (int) (mRelativeHeight * mParams.mBaseHeight - verticalGap);
} }
*/
/** /**
* Create keyParams with the given top-left coordinate and extract its attributes from a key * Create keyParams with the given top-left coordinate and extract its attributes from a key
* specification string, Key attribute array, key style, and etc. * specification string, Key attribute array, key style, and etc.
@ -1018,6 +1017,9 @@ public class Key implements Comparable<Key> {
public KeyParams(@Nullable final String keySpec, @NonNull final TypedArray keyAttr, public KeyParams(@Nullable final String keySpec, @NonNull final TypedArray keyAttr,
@NonNull final KeyStyle style, @NonNull final KeyboardParams params, @NonNull final KeyStyle style, @NonNull final KeyboardParams params,
@NonNull final XmlKeyboardRow row) { @NonNull final XmlKeyboardRow row) {
mParams = params;
mRelativeHeight = row.mRelativeRowHeight;
mRelativeWidth = row.getRelativeKeyWidth(keyAttr);
mHorizontalGap = params.mHorizontalGap; mHorizontalGap = params.mHorizontalGap;
mVerticalGap = params.mVerticalGap; mVerticalGap = params.mVerticalGap;
@ -1168,6 +1170,7 @@ public class Key implements Comparable<Key> {
@Nullable final String hintLabel, @Nullable final String moreKeySpecs, @Nullable final String hintLabel, @Nullable final String moreKeySpecs,
final int labelFlags, final int backgroundType, final int x, final int y, final int labelFlags, final int backgroundType, final int x, final int y,
final int width, final int height, final KeyboardParams params) { final int width, final int height, final KeyboardParams params) {
mParams = params;
mWidth = width - params.mHorizontalGap; mWidth = width - params.mHorizontalGap;
mHeight = height - params.mVerticalGap; mHeight = height - params.mVerticalGap;
mHorizontalGap = params.mHorizontalGap; mHorizontalGap = params.mHorizontalGap;

View file

@ -57,6 +57,8 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
public KeyboardBuilder<KP> loadFromXml(final int xmlId, final KeyboardId id) { public KeyboardBuilder<KP> loadFromXml(final int xmlId, final KeyboardId id) {
mParams.mId = id; mParams.mId = id;
// loading a keyboard should set default params like mParams.readAttributes(mContext, attrs);
// attrs may be null, then default values are used (looks good for "normal" keyboards)
try (XmlKeyboardParser keyboardParser = new XmlKeyboardParser(xmlId, mParams, mContext)) { try (XmlKeyboardParser keyboardParser = new XmlKeyboardParser(xmlId, mParams, mContext)) {
keysInRows = keyboardParser.parseKeyboard(); keysInRows = keyboardParser.parseKeyboard();
} catch (XmlPullParserException e) { } catch (XmlPullParserException e) {

View file

@ -6,6 +6,9 @@
package org.dslul.openboard.inputmethod.keyboard.internal; package org.dslul.openboard.inputmethod.keyboard.internal;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.util.SparseIntArray; import android.util.SparseIntArray;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
@ -13,7 +16,10 @@ import androidx.annotation.Nullable;
import org.dslul.openboard.inputmethod.keyboard.Key; import org.dslul.openboard.inputmethod.keyboard.Key;
import org.dslul.openboard.inputmethod.keyboard.KeyboardId; import org.dslul.openboard.inputmethod.keyboard.KeyboardId;
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.settings.Settings;
import org.dslul.openboard.inputmethod.latin.utils.ResourceUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Comparator; import java.util.Comparator;
@ -21,6 +27,9 @@ import java.util.SortedSet;
import java.util.TreeSet; import java.util.TreeSet;
public class KeyboardParams { public class KeyboardParams {
private static final int DEFAULT_KEYBOARD_COLUMNS = 10;
private static final int DEFAULT_KEYBOARD_ROWS = 4;
public KeyboardId mId; public KeyboardId mId;
public int mThemeId; public int mThemeId;
@ -42,6 +51,11 @@ public class KeyboardParams {
@Nullable @Nullable
public KeyVisualAttributes mKeyVisualAttributes; public KeyVisualAttributes mKeyVisualAttributes;
public float mDefaultRelativeRowHeight;
public float mDefaultRelativeKeyWidth;
public float mRelativeHorizontalGap;
public float mRelativeVerticalGap;
// relative values multiplied with baseHeight / baseWidth
public int mDefaultRowHeight; public int mDefaultRowHeight;
public int mDefaultKeyWidth; public int mDefaultKeyWidth;
public int mHorizontalGap; public int mHorizontalGap;
@ -177,4 +191,84 @@ public class KeyboardParams {
mMostCommonKeyWidth = width; mMostCommonKeyWidth = width;
} }
} }
// when attr is null, default attributes will be loaded
// these are good for basic keyboards already, but have wrong/unsuitable sizes e.g. for emojis,
// moreKeys and moreSuggestions
public void readAttributes(final Context context, @Nullable final AttributeSet attr) {
final TypedArray keyboardAttr = context.obtainStyledAttributes(
attr, R.styleable.Keyboard, R.attr.keyboardStyle, R.style.Keyboard);
final TypedArray keyAttr;
if (attr == null)
keyAttr = context.obtainStyledAttributes(attr, R.styleable.Keyboard_Key);
else
keyAttr = context.getResources().obtainAttributes(attr, R.styleable.Keyboard_Key);
try {
final int height = mId.mHeight;
final int width = mId.mWidth;
mOccupiedHeight = height;
mOccupiedWidth = width;
mTopPadding = (int) keyboardAttr.getFraction(
R.styleable.Keyboard_keyboardTopPadding, height, height, 0);
mBottomPadding = (int) keyboardAttr.getFraction(
R.styleable.Keyboard_keyboardBottomPadding, height, height, 0);
mLeftPadding = (int) keyboardAttr.getFraction(
R.styleable.Keyboard_keyboardLeftPadding, width, width, 0);
mRightPadding = (int) keyboardAttr.getFraction(
R.styleable.Keyboard_keyboardRightPadding, width, width, 0);
final int baseWidth = mOccupiedWidth - mLeftPadding - mRightPadding;
mBaseWidth = baseWidth;
mDefaultRelativeKeyWidth = keyAttr.getFraction(R.styleable.Keyboard_Key_keyWidth,
1, 1, 1f / DEFAULT_KEYBOARD_COLUMNS);
mDefaultKeyWidth = (int) (mDefaultRelativeKeyWidth * baseWidth);
// todo: maybe settings should not be accessed from here?
if (Settings.getInstance().getCurrent().mNarrowKeyGaps) {
mRelativeHorizontalGap = keyboardAttr.getFraction(
R.styleable.Keyboard_horizontalGapNarrow, 1, 1, 0);
mRelativeVerticalGap = keyboardAttr.getFraction(
R.styleable.Keyboard_verticalGapNarrow, 1, 1, 0);
} else {
mRelativeHorizontalGap = keyboardAttr.getFraction(
R.styleable.Keyboard_horizontalGap, 1, 1, 0);
mRelativeVerticalGap = keyboardAttr.getFraction(
R.styleable.Keyboard_verticalGap, 1, 1, 0);
// TODO: Fix keyboard geometry calculation clearer. Historically vertical gap between
// rows are determined based on the entire keyboard height including top and bottom
// paddings.
}
mHorizontalGap = (int) (mRelativeHorizontalGap * width);
mVerticalGap = (int) (mRelativeVerticalGap * height);
final int baseHeight = mOccupiedHeight - mTopPadding - mBottomPadding + mVerticalGap;
mBaseHeight = baseHeight;
mDefaultRelativeRowHeight = ResourceUtils.getDimensionOrFraction(keyboardAttr,
R.styleable.Keyboard_rowHeight, 1, 1f / DEFAULT_KEYBOARD_ROWS);
if (mDefaultRelativeRowHeight > 1) { // can be absolute size, in that case will be > 1
mDefaultRowHeight = (int) mDefaultRelativeRowHeight;
mDefaultRelativeRowHeight *= -1; // make it negative when it's absolute
} else {
mDefaultRowHeight = (int) (mDefaultRelativeRowHeight * baseHeight);
}
mKeyVisualAttributes = KeyVisualAttributes.newInstance(keyAttr);
mMoreKeysTemplate = keyboardAttr.getResourceId(R.styleable.Keyboard_moreKeysTemplate, 0);
mMaxMoreKeysKeyboardColumn = keyAttr.getInt(R.styleable.Keyboard_Key_maxMoreKeysColumn, 5);
mThemeId = keyboardAttr.getInt(R.styleable.Keyboard_themeId, 0);
mIconsSet.loadIcons(keyboardAttr);
mTextsSet.setLocale(mId.getLocale(), context);
final int resourceId = keyboardAttr.getResourceId(R.styleable.Keyboard_touchPositionCorrectionData, 0);
if (resourceId != 0) {
final String[] data = context.getResources().getStringArray(resourceId);
mTouchPositionCorrection.load(data);
}
} finally {
keyAttr.recycle();
keyboardAttr.recycle();
}
}
} }

View file

@ -16,14 +16,12 @@ import org.dslul.openboard.inputmethod.keyboard.KeyboardId;
import org.dslul.openboard.inputmethod.keyboard.KeyboardTheme; import org.dslul.openboard.inputmethod.keyboard.KeyboardTheme;
import org.dslul.openboard.inputmethod.keyboard.internal.CodesArrayParser; import org.dslul.openboard.inputmethod.keyboard.internal.CodesArrayParser;
import org.dslul.openboard.inputmethod.keyboard.internal.KeyStyle; import org.dslul.openboard.inputmethod.keyboard.internal.KeyStyle;
import org.dslul.openboard.inputmethod.keyboard.internal.KeyVisualAttributes;
import org.dslul.openboard.inputmethod.keyboard.internal.KeyboardIconsSet; import org.dslul.openboard.inputmethod.keyboard.internal.KeyboardIconsSet;
import org.dslul.openboard.inputmethod.keyboard.internal.KeyboardParams; import org.dslul.openboard.inputmethod.keyboard.internal.KeyboardParams;
import org.dslul.openboard.inputmethod.keyboard.internal.MoreCodesArrayParser; import org.dslul.openboard.inputmethod.keyboard.internal.MoreCodesArrayParser;
import org.dslul.openboard.inputmethod.latin.R; 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.utils.ResourceUtils; import org.dslul.openboard.inputmethod.latin.utils.ResourceUtils;
import org.dslul.openboard.inputmethod.latin.utils.XmlParseUtils; import org.dslul.openboard.inputmethod.latin.utils.XmlParseUtils;
import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParser;
@ -121,9 +119,6 @@ public class XmlKeyboardParser implements AutoCloseable {
private static final String TAG_DEFAULT = "default"; private static final String TAG_DEFAULT = "default";
public static final String TAG_KEY_STYLE = "key-style"; public static final String TAG_KEY_STYLE = "key-style";
private static final int DEFAULT_KEYBOARD_COLUMNS = 10;
private static final int DEFAULT_KEYBOARD_ROWS = 4;
protected final Context mContext; protected final Context mContext;
protected final Resources mResources; protected final Resources mResources;
private final XmlResourceParser mParser; private final XmlResourceParser mParser;
@ -189,74 +184,7 @@ public class XmlKeyboardParser implements AutoCloseable {
/** this and parseKeyStyle are the only place where anything is written to params */ /** this and parseKeyStyle are the only place where anything is written to params */
private void parseKeyboardAttributes(final XmlPullParser parser) { private void parseKeyboardAttributes(final XmlPullParser parser) {
final AttributeSet attr = Xml.asAttributeSet(parser); final AttributeSet attr = Xml.asAttributeSet(parser);
final TypedArray keyboardAttr = mContext.obtainStyledAttributes( mParams.readAttributes(mContext, attr);
attr, R.styleable.Keyboard, R.attr.keyboardStyle, R.style.Keyboard);
final TypedArray keyAttr = mResources.obtainAttributes(attr, R.styleable.Keyboard_Key);
final KeyboardParams params = mParams;
try {
final int height = params.mId.mHeight;
final int width = params.mId.mWidth;
params.mOccupiedHeight = height;
params.mOccupiedWidth = width;
params.mTopPadding = (int)keyboardAttr.getFraction(
R.styleable.Keyboard_keyboardTopPadding, height, height, 0);
params.mBottomPadding = (int)keyboardAttr.getFraction(
R.styleable.Keyboard_keyboardBottomPadding, height, height, 0);
params.mLeftPadding = (int)keyboardAttr.getFraction(
R.styleable.Keyboard_keyboardLeftPadding, width, width, 0);
params.mRightPadding = (int)keyboardAttr.getFraction(
R.styleable.Keyboard_keyboardRightPadding, width, width, 0);
final int baseWidth =
params.mOccupiedWidth - params.mLeftPadding - params.mRightPadding;
params.mBaseWidth = baseWidth;
params.mDefaultKeyWidth = (int)keyAttr.getFraction(R.styleable.Keyboard_Key_keyWidth,
baseWidth, baseWidth, baseWidth / DEFAULT_KEYBOARD_COLUMNS);
// todo: actually settings should not be accessed from here
// maybe parse normal key gaps and adjust them later (using the relative params!)
if (Settings.getInstance().getCurrent().mNarrowKeyGaps) {
params.mHorizontalGap = (int) keyboardAttr.getFraction(
R.styleable.Keyboard_horizontalGapNarrow, baseWidth, baseWidth, 0);
params.mVerticalGap = (int) keyboardAttr.getFraction(
R.styleable.Keyboard_verticalGapNarrow, height, height, 0);
} else {
params.mHorizontalGap = (int) keyboardAttr.getFraction(
R.styleable.Keyboard_horizontalGap, baseWidth, baseWidth, 0);
// TODO: Fix keyboard geometry calculation clearer. Historically vertical gap between
// rows are determined based on the entire keyboard height including top and bottom
// paddings.
params.mVerticalGap = (int) keyboardAttr.getFraction(
R.styleable.Keyboard_verticalGap, height, height, 0);
}
final int baseHeight = params.mOccupiedHeight - params.mTopPadding
- params.mBottomPadding + params.mVerticalGap;
params.mBaseHeight = baseHeight;
params.mDefaultRowHeight = (int) ResourceUtils.getDimensionOrFraction(keyboardAttr,
R.styleable.Keyboard_rowHeight, baseHeight, baseHeight / DEFAULT_KEYBOARD_ROWS);
params.mKeyVisualAttributes = KeyVisualAttributes.newInstance(keyAttr);
params.mMoreKeysTemplate = keyboardAttr.getResourceId(
R.styleable.Keyboard_moreKeysTemplate, 0);
params.mMaxMoreKeysKeyboardColumn = keyAttr.getInt(
R.styleable.Keyboard_Key_maxMoreKeysColumn, 5);
params.mThemeId = keyboardAttr.getInt(R.styleable.Keyboard_themeId, 0);
params.mIconsSet.loadIcons(keyboardAttr);
params.mTextsSet.setLocale(params.mId.getLocale(), mContext);
final int resourceId = keyboardAttr.getResourceId(
R.styleable.Keyboard_touchPositionCorrectionData, 0);
if (resourceId != 0) {
final String[] data = mResources.getStringArray(resourceId);
params.mTouchPositionCorrection.load(data);
}
} finally {
keyAttr.recycle();
keyboardAttr.recycle();
}
} }
private void parseKeyboardContent(final XmlPullParser parser, final boolean skip) private void parseKeyboardContent(final XmlPullParser parser, final boolean skip)
@ -366,7 +294,6 @@ public class XmlKeyboardParser implements AutoCloseable {
R.styleable.Keyboard_GridRows_textsArray, 0); R.styleable.Keyboard_GridRows_textsArray, 0);
final int moreCodesArrayId = gridRowAttr.getResourceId( final int moreCodesArrayId = gridRowAttr.getResourceId(
R.styleable.Keyboard_GridRows_moreCodesArray, 0); R.styleable.Keyboard_GridRows_moreCodesArray, 0);
// todo: read relative key width, key / row height and gaps (but they might also be absolute, see getDimensionOrFraction)
gridRowAttr.recycle(); gridRowAttr.recycle();
if (codesArrayId == 0 && textsArrayId == 0) { if (codesArrayId == 0 && textsArrayId == 0) {
throw new XmlParseUtils.ParseException( throw new XmlParseUtils.ParseException(
@ -436,7 +363,9 @@ public class XmlKeyboardParser implements AutoCloseable {
final String hintLabel = moreKeySpecs != null ? "\u25E5" : null; final String hintLabel = moreKeySpecs != null ? "\u25E5" : null;
final Key.KeyParams key = new Key.KeyParams(label, code, outputText, hintLabel, moreKeySpecs, final Key.KeyParams key = new Key.KeyParams(label, code, outputText, hintLabel, moreKeySpecs,
labelFlags, backgroundType, x, y, width, height, mParams); labelFlags, backgroundType, x, y, width, height, mParams);
// todo: add relative width and others // (relative) width is always default when using gridRows.getKeyWidth(null, 0.0f)
key.mRelativeWidth = mParams.mDefaultRelativeKeyWidth;
key.mRelativeHeight = gridRows.mRelativeRowHeight;
keyParamsRow.add(key); keyParamsRow.add(key);
row.advanceXPos(keyWidth); row.advanceXPos(keyWidth);
} }
@ -462,7 +391,6 @@ public class XmlKeyboardParser implements AutoCloseable {
} }
final Key.KeyParams key = new Key.KeyParams(keySpec, keyAttr, keyStyle, mParams, row); final Key.KeyParams key = new Key.KeyParams(keySpec, keyAttr, keyStyle, mParams, row);
keyAttr.recycle(); keyAttr.recycle();
// todo: add relative width and others
if (DEBUG) { if (DEBUG) {
startEndTag("<%s%s %s moreKeys=%s />", TAG_KEY, (key.mEnabled ? "" : " disabled"), startEndTag("<%s%s %s moreKeys=%s />", TAG_KEY, (key.mEnabled ? "" : " disabled"),
key, Arrays.toString(key.mMoreKeys)); key, Arrays.toString(key.mMoreKeys));
@ -483,7 +411,6 @@ public class XmlKeyboardParser implements AutoCloseable {
final KeyStyle keyStyle = mParams.mKeyStyles.getKeyStyle(keyAttr, parser); final KeyStyle keyStyle = mParams.mKeyStyles.getKeyStyle(keyAttr, parser);
final Key.KeyParams spacer = Key.KeyParams.newSpacer(keyAttr, keyStyle, mParams, row); final Key.KeyParams spacer = Key.KeyParams.newSpacer(keyAttr, keyStyle, mParams, row);
keyAttr.recycle(); keyAttr.recycle();
// todo: add relative width and others
keysInRows.get(keysInRows.size() - 1).add(spacer); keysInRows.get(keysInRows.size() - 1).add(spacer);
if (DEBUG) startEndTag("<%s />", TAG_SPACER); if (DEBUG) startEndTag("<%s />", TAG_SPACER);
XmlParseUtils.checkEndTag(TAG_SPACER, parser); XmlParseUtils.checkEndTag(TAG_SPACER, parser);

View file

@ -32,6 +32,7 @@ public final class XmlKeyboardRow {
private final KeyboardParams mParams; private final KeyboardParams mParams;
/** The height of this row. */ /** The height of this row. */
private final int mRowHeight; private final int mRowHeight;
final public float mRelativeRowHeight;
private final ArrayDeque<RowAttributes> mRowAttributesStack = new ArrayDeque<>(); private final ArrayDeque<RowAttributes> mRowAttributesStack = new ArrayDeque<>();
@ -88,9 +89,16 @@ public final class XmlKeyboardRow {
mParams = params; mParams = params;
final TypedArray keyboardAttr = res.obtainAttributes(Xml.asAttributeSet(parser), final TypedArray keyboardAttr = res.obtainAttributes(Xml.asAttributeSet(parser),
R.styleable.Keyboard); R.styleable.Keyboard);
mRowHeight = (int)ResourceUtils.getDimensionOrFraction(keyboardAttr, float relativeRowHeight = ResourceUtils.getDimensionOrFraction(keyboardAttr,
R.styleable.Keyboard_rowHeight, params.mBaseHeight, params.mDefaultRowHeight); R.styleable.Keyboard_rowHeight, 1, params.mDefaultRelativeRowHeight);
keyboardAttr.recycle(); keyboardAttr.recycle();
if (relativeRowHeight > 1) {
mRelativeRowHeight = -relativeRowHeight;
mRowHeight = (int) relativeRowHeight;
} else {
mRelativeRowHeight = relativeRowHeight;
mRowHeight = (int) (relativeRowHeight * params.mBaseHeight);
}
final TypedArray keyAttr = res.obtainAttributes(Xml.asAttributeSet(parser), final TypedArray keyAttr = res.obtainAttributes(Xml.asAttributeSet(parser),
R.styleable.Keyboard_Key); R.styleable.Keyboard_Key);
mRowAttributesStack.push(new RowAttributes( mRowAttributesStack.push(new RowAttributes(
@ -157,6 +165,17 @@ public final class XmlKeyboardRow {
return Math.max(keyXPos + keyboardRightEdge, mCurrentX); return Math.max(keyXPos + keyboardRightEdge, mCurrentX);
} }
public float getRelativeKeyWidth(final TypedArray keyAttr) {
if (keyAttr == null)
return mParams.mDefaultRelativeKeyWidth;
final int widthType = ResourceUtils.getEnumValue(keyAttr,
R.styleable.Keyboard_Key_keyWidth, KEYWIDTH_NOT_ENUM);
if (widthType == KEYWIDTH_FILL_RIGHT)
return -1;
return keyAttr.getFraction(R.styleable.Keyboard_Key_keyWidth,
1, 1, mParams.mDefaultRelativeKeyWidth);
}
public float getKeyWidth(final TypedArray keyAttr, final float keyXPos) { public float getKeyWidth(final TypedArray keyAttr, final float keyXPos) {
if (keyAttr == null) { if (keyAttr == null) {
return getDefaultKeyWidth(); return getDefaultKeyWidth();