Introduce hit box to Key and get rid of edge flags
Change-Id: I2b78d2ca756223b5497d01127c3a0190dcc81e57main
parent
a59f65ad0c
commit
2fc4248700
|
@ -19,6 +19,7 @@ package com.android.inputmethod.keyboard;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.content.res.TypedArray;
|
import android.content.res.TypedArray;
|
||||||
import android.content.res.XmlResourceParser;
|
import android.content.res.XmlResourceParser;
|
||||||
|
import android.graphics.Rect;
|
||||||
import android.graphics.Typeface;
|
import android.graphics.Typeface;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
@ -86,6 +87,9 @@ public class Key {
|
||||||
public final int mX;
|
public final int mX;
|
||||||
/** Y coordinate of the key in the keyboard layout */
|
/** Y coordinate of the key in the keyboard layout */
|
||||||
public final int mY;
|
public final int mY;
|
||||||
|
/** Hit bounding box of the key */
|
||||||
|
public final Rect mHitBox = new Rect();
|
||||||
|
|
||||||
/** Text to output when pressed. This can be multiple characters, like ".com" */
|
/** Text to output when pressed. This can be multiple characters, like ".com" */
|
||||||
public final CharSequence mOutputText;
|
public final CharSequence mOutputText;
|
||||||
/** More keys */
|
/** More keys */
|
||||||
|
@ -93,14 +97,6 @@ public class Key {
|
||||||
/** More keys maximum column number */
|
/** More keys maximum column number */
|
||||||
public final int mMaxMoreKeysColumn;
|
public final int mMaxMoreKeysColumn;
|
||||||
|
|
||||||
/**
|
|
||||||
* Flags that specify the anchoring to edges of the keyboard for detecting touch events
|
|
||||||
* that are just out of the boundary of the key. This is a bit mask of
|
|
||||||
* {@link Keyboard#EDGE_LEFT}, {@link Keyboard#EDGE_RIGHT},
|
|
||||||
* {@link Keyboard#EDGE_TOP} and {@link Keyboard#EDGE_BOTTOM}.
|
|
||||||
*/
|
|
||||||
private int mEdgeFlags;
|
|
||||||
|
|
||||||
/** Background type that represents different key background visual than normal one. */
|
/** Background type that represents different key background visual than normal one. */
|
||||||
public final int mBackgroundType;
|
public final int mBackgroundType;
|
||||||
public static final int BACKGROUND_TYPE_NORMAL = 0;
|
public static final int BACKGROUND_TYPE_NORMAL = 0;
|
||||||
|
@ -167,23 +163,22 @@ public class Key {
|
||||||
* This constructor is being used only for key in more keys keyboard.
|
* This constructor is being used only for key in more keys keyboard.
|
||||||
*/
|
*/
|
||||||
public Key(Resources res, KeyboardParams params, String moreKeySpec,
|
public Key(Resources res, KeyboardParams params, String moreKeySpec,
|
||||||
int x, int y, int width, int height, int edgeFlags) {
|
int x, int y, int width, int height) {
|
||||||
this(params, MoreKeySpecParser.getLabel(moreKeySpec), null, getIcon(params, moreKeySpec),
|
this(params, MoreKeySpecParser.getLabel(moreKeySpec), null, getIcon(params, moreKeySpec),
|
||||||
getCode(res, params, moreKeySpec), MoreKeySpecParser.getOutputText(moreKeySpec),
|
getCode(res, params, moreKeySpec), MoreKeySpecParser.getOutputText(moreKeySpec),
|
||||||
x, y, width, height, edgeFlags);
|
x, y, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This constructor is being used only for key in popup suggestions pane.
|
* This constructor is being used only for key in popup suggestions pane.
|
||||||
*/
|
*/
|
||||||
public Key(KeyboardParams params, CharSequence label, CharSequence hintLabel, Drawable icon,
|
public Key(KeyboardParams params, CharSequence label, CharSequence hintLabel, Drawable icon,
|
||||||
int code, CharSequence outputText, int x, int y, int width, int height, int edgeFlags) {
|
int code, CharSequence outputText, int x, int y, int width, int height) {
|
||||||
mHeight = height - params.mVerticalGap;
|
mHeight = height - params.mVerticalGap;
|
||||||
mHorizontalGap = params.mHorizontalGap;
|
mHorizontalGap = params.mHorizontalGap;
|
||||||
mVerticalGap = params.mVerticalGap;
|
mVerticalGap = params.mVerticalGap;
|
||||||
mVisualInsetsLeft = mVisualInsetsRight = 0;
|
mVisualInsetsLeft = mVisualInsetsRight = 0;
|
||||||
mWidth = width - mHorizontalGap;
|
mWidth = width - mHorizontalGap;
|
||||||
mEdgeFlags = edgeFlags;
|
|
||||||
mHintLabel = hintLabel;
|
mHintLabel = hintLabel;
|
||||||
mLabelOption = 0;
|
mLabelOption = 0;
|
||||||
mBackgroundType = BACKGROUND_TYPE_NORMAL;
|
mBackgroundType = BACKGROUND_TYPE_NORMAL;
|
||||||
|
@ -197,6 +192,7 @@ public class Key {
|
||||||
// Horizontal gap is divided equally to both sides of the key.
|
// Horizontal gap is divided equally to both sides of the key.
|
||||||
mX = x + mHorizontalGap / 2;
|
mX = x + mHorizontalGap / 2;
|
||||||
mY = y;
|
mY = y;
|
||||||
|
mHitBox.set(x, y, x + width + 1, y + height);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -212,8 +208,9 @@ public class Key {
|
||||||
public Key(Resources res, KeyboardParams params, KeyboardBuilder.Row row,
|
public Key(Resources res, KeyboardParams params, KeyboardBuilder.Row row,
|
||||||
XmlResourceParser parser, KeyStyles keyStyles) {
|
XmlResourceParser parser, KeyStyles keyStyles) {
|
||||||
final float horizontalGap = isSpacer() ? 0 : params.mHorizontalGap;
|
final float horizontalGap = isSpacer() ? 0 : params.mHorizontalGap;
|
||||||
|
final int keyHeight = row.mRowHeight;
|
||||||
mVerticalGap = params.mVerticalGap;
|
mVerticalGap = params.mVerticalGap;
|
||||||
mHeight = row.mRowHeight - mVerticalGap;
|
mHeight = keyHeight - mVerticalGap;
|
||||||
|
|
||||||
final TypedArray keyAttr = res.obtainAttributes(Xml.asAttributeSet(parser),
|
final TypedArray keyAttr = res.obtainAttributes(Xml.asAttributeSet(parser),
|
||||||
R.styleable.Keyboard_Key);
|
R.styleable.Keyboard_Key);
|
||||||
|
@ -230,12 +227,14 @@ public class Key {
|
||||||
|
|
||||||
final float keyXPos = row.getKeyX(keyAttr);
|
final float keyXPos = row.getKeyX(keyAttr);
|
||||||
final float keyWidth = row.getKeyWidth(keyAttr, keyXPos);
|
final float keyWidth = row.getKeyWidth(keyAttr, keyXPos);
|
||||||
|
final int keyYPos = row.getKeyY();
|
||||||
|
|
||||||
// Horizontal gap is divided equally to both sides of the key.
|
// Horizontal gap is divided equally to both sides of the key.
|
||||||
mX = (int) (keyXPos + horizontalGap / 2);
|
mX = (int) (keyXPos + horizontalGap / 2);
|
||||||
mY = row.getKeyY();
|
mY = keyYPos;
|
||||||
mWidth = (int) (keyWidth - horizontalGap);
|
mWidth = (int) (keyWidth - horizontalGap);
|
||||||
mHorizontalGap = (int) horizontalGap;
|
mHorizontalGap = (int) horizontalGap;
|
||||||
|
mHitBox.set((int)keyXPos, keyYPos, (int)(keyXPos + keyWidth) + 1, keyYPos + keyHeight);
|
||||||
// Update row to have current x coordinate.
|
// Update row to have current x coordinate.
|
||||||
row.setXPos(keyXPos + keyWidth);
|
row.setXPos(keyXPos + keyWidth);
|
||||||
|
|
||||||
|
@ -256,7 +255,6 @@ public class Key {
|
||||||
R.styleable.Keyboard_Key_backgroundType, BACKGROUND_TYPE_NORMAL);
|
R.styleable.Keyboard_Key_backgroundType, BACKGROUND_TYPE_NORMAL);
|
||||||
mRepeatable = style.getBoolean(keyAttr, R.styleable.Keyboard_Key_isRepeatable, false);
|
mRepeatable = style.getBoolean(keyAttr, R.styleable.Keyboard_Key_isRepeatable, false);
|
||||||
mEnabled = style.getBoolean(keyAttr, R.styleable.Keyboard_Key_enabled, true);
|
mEnabled = style.getBoolean(keyAttr, R.styleable.Keyboard_Key_enabled, true);
|
||||||
mEdgeFlags = 0;
|
|
||||||
|
|
||||||
final KeyboardIconsSet iconsSet = params.mIconsSet;
|
final KeyboardIconsSet iconsSet = params.mIconsSet;
|
||||||
mVisualInsetsLeft = (int) KeyboardBuilder.getDimensionOrFraction(keyAttr,
|
mVisualInsetsLeft = (int) KeyboardBuilder.getDimensionOrFraction(keyAttr,
|
||||||
|
@ -294,8 +292,20 @@ public class Key {
|
||||||
keyAttr.recycle();
|
keyAttr.recycle();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addEdgeFlags(int flags) {
|
public void markAsLeftEdge(KeyboardParams params) {
|
||||||
mEdgeFlags |= flags;
|
mHitBox.left = params.mHorizontalEdgesPadding;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void markAsRightEdge(KeyboardParams params) {
|
||||||
|
mHitBox.right = params.mOccupiedWidth - params.mHorizontalEdgesPadding;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void markAsTopEdge(KeyboardParams params) {
|
||||||
|
mHitBox.top = params.mTopPadding;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void markAsBottomEdge(KeyboardParams params) {
|
||||||
|
mHitBox.bottom = params.mOccupiedHeight + params.mBottomPadding;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSticky() {
|
public boolean isSticky() {
|
||||||
|
@ -427,23 +437,10 @@ public class Key {
|
||||||
* @param y the y-coordinate of the point
|
* @param y the y-coordinate of the point
|
||||||
* @return whether or not the point falls on the key. If the key is attached to an edge, it will
|
* @return whether or not the point falls on the key. If the key is attached to an edge, it will
|
||||||
* assume that all points between the key and the edge are considered to be on the key.
|
* assume that all points between the key and the edge are considered to be on the key.
|
||||||
|
* @see {@link #markAsLeftEdge(KeyboardParams)} etc.
|
||||||
*/
|
*/
|
||||||
public boolean isOnKey(int x, int y) {
|
public boolean isOnKey(int x, int y) {
|
||||||
final int left = mX - mHorizontalGap / 2;
|
return mHitBox.contains(x, y);
|
||||||
final int right = left + mWidth + mHorizontalGap;
|
|
||||||
final int top = mY;
|
|
||||||
final int bottom = top + mHeight + mVerticalGap;
|
|
||||||
final int flags = mEdgeFlags;
|
|
||||||
if (flags == 0) {
|
|
||||||
return x >= left && x <= right && y >= top && y <= bottom;
|
|
||||||
}
|
|
||||||
final boolean leftEdge = (flags & Keyboard.EDGE_LEFT) != 0;
|
|
||||||
final boolean rightEdge = (flags & Keyboard.EDGE_RIGHT) != 0;
|
|
||||||
final boolean topEdge = (flags & Keyboard.EDGE_TOP) != 0;
|
|
||||||
final boolean bottomEdge = (flags & Keyboard.EDGE_BOTTOM) != 0;
|
|
||||||
// In order to mitigate rounding errors, we use (left <= x <= right) here.
|
|
||||||
return (x >= left || leftEdge) && (x <= right || rightEdge)
|
|
||||||
&& (y >= top || topEdge) && (y <= bottom || bottomEdge);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -547,7 +544,7 @@ public class Key {
|
||||||
* This constructor is being used only for divider in more keys keyboard.
|
* This constructor is being used only for divider in more keys keyboard.
|
||||||
*/
|
*/
|
||||||
public Spacer(KeyboardParams params, Drawable icon, int x, int y, int width, int height) {
|
public Spacer(KeyboardParams params, Drawable icon, int x, int y, int width, int height) {
|
||||||
super(params, null, null, icon, Keyboard.CODE_DUMMY, null, x, y, width, height, 0);
|
super(params, null, null, icon, Keyboard.CODE_DUMMY, null, x, y, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -47,11 +47,6 @@ import java.util.Set;
|
||||||
* </pre>
|
* </pre>
|
||||||
*/
|
*/
|
||||||
public class Keyboard {
|
public class Keyboard {
|
||||||
public static final int EDGE_LEFT = 0x01;
|
|
||||||
public static final int EDGE_RIGHT = 0x02;
|
|
||||||
public static final int EDGE_TOP = 0x04;
|
|
||||||
public static final int EDGE_BOTTOM = 0x08;
|
|
||||||
|
|
||||||
/** Some common keys code. These should be aligned with values/keycodes.xml */
|
/** Some common keys code. These should be aligned with values/keycodes.xml */
|
||||||
public static final int CODE_ENTER = '\n';
|
public static final int CODE_ENTER = '\n';
|
||||||
public static final int CODE_TAB = '\t';
|
public static final int CODE_TAB = '\t';
|
||||||
|
|
|
@ -193,13 +193,11 @@ public class MiniKeyboard extends Keyboard {
|
||||||
return (mNumRows - 1 - row) * mDefaultRowHeight + mTopPadding;
|
return (mNumRows - 1 - row) * mDefaultRowHeight + mTopPadding;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getRowFlags(int row) {
|
public void markAsEdgeKey(Key key, int row) {
|
||||||
int rowFlags = 0;
|
|
||||||
if (row == 0)
|
if (row == 0)
|
||||||
rowFlags |= Keyboard.EDGE_TOP;
|
key.markAsTopEdge(this);
|
||||||
if (isTopRow(row))
|
if (isTopRow(row))
|
||||||
rowFlags |= Keyboard.EDGE_BOTTOM;
|
key.markAsBottomEdge(this);
|
||||||
return rowFlags;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isTopRow(int rowCount) {
|
private boolean isTopRow(int rowCount) {
|
||||||
|
@ -254,8 +252,8 @@ public class MiniKeyboard extends Keyboard {
|
||||||
final String moreKeySpec = mMoreKeys[n].toString();
|
final String moreKeySpec = mMoreKeys[n].toString();
|
||||||
final int row = n / params.mNumColumns;
|
final int row = n / params.mNumColumns;
|
||||||
final Key key = new Key(mResources, params, moreKeySpec, params.getX(n, row),
|
final Key key = new Key(mResources, params, moreKeySpec, params.getX(n, row),
|
||||||
params.getY(row), params.mDefaultKeyWidth, params.mDefaultRowHeight,
|
params.getY(row), params.mDefaultKeyWidth, params.mDefaultRowHeight);
|
||||||
params.getRowFlags(row));
|
params.markAsEdgeKey(key, row);
|
||||||
params.onAddKey(key);
|
params.onAddKey(key);
|
||||||
}
|
}
|
||||||
return new MiniKeyboard(params);
|
return new MiniKeyboard(params);
|
||||||
|
|
|
@ -753,7 +753,7 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
|
||||||
if (mCurrentRow == null)
|
if (mCurrentRow == null)
|
||||||
throw new InflateException("orphant end row tag");
|
throw new InflateException("orphant end row tag");
|
||||||
if (mRightEdgeKey != null) {
|
if (mRightEdgeKey != null) {
|
||||||
mRightEdgeKey.addEdgeFlags(Keyboard.EDGE_RIGHT);
|
mRightEdgeKey.markAsRightEdge(mParams);
|
||||||
mRightEdgeKey = null;
|
mRightEdgeKey = null;
|
||||||
}
|
}
|
||||||
addEdgeSpace(mParams.mHorizontalEdgesPadding, row);
|
addEdgeSpace(mParams.mHorizontalEdgesPadding, row);
|
||||||
|
@ -765,11 +765,11 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
|
||||||
private void endKey(Key key) {
|
private void endKey(Key key) {
|
||||||
mParams.onAddKey(key);
|
mParams.onAddKey(key);
|
||||||
if (mLeftEdge) {
|
if (mLeftEdge) {
|
||||||
key.addEdgeFlags(Keyboard.EDGE_LEFT);
|
key.markAsLeftEdge(mParams);
|
||||||
mLeftEdge = false;
|
mLeftEdge = false;
|
||||||
}
|
}
|
||||||
if (mTopEdge) {
|
if (mTopEdge) {
|
||||||
key.addEdgeFlags(Keyboard.EDGE_TOP);
|
key.markAsTopEdge(mParams);
|
||||||
}
|
}
|
||||||
mRightEdgeKey = key;
|
mRightEdgeKey = key;
|
||||||
}
|
}
|
||||||
|
|
|
@ -153,23 +153,19 @@ public class MoreSuggestions extends Keyboard {
|
||||||
return (mOccupiedWidth - mDividerWidth * (numColumnInRow - 1)) / numColumnInRow;
|
return (mOccupiedWidth - mDividerWidth * (numColumnInRow - 1)) / numColumnInRow;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getFlags(int pos) {
|
public void markAsEdgeKey(Key key, int pos) {
|
||||||
int rowFlags = 0;
|
|
||||||
|
|
||||||
final int row = mRowNumbers[pos];
|
final int row = mRowNumbers[pos];
|
||||||
if (row == 0)
|
if (row == 0)
|
||||||
rowFlags |= Keyboard.EDGE_BOTTOM;
|
key.markAsBottomEdge(this);
|
||||||
if (row == mNumRows - 1)
|
if (row == mNumRows - 1)
|
||||||
rowFlags |= Keyboard.EDGE_TOP;
|
key.markAsTopEdge(this);
|
||||||
|
|
||||||
final int numColumnInRow = mNumColumnsInRow[row];
|
final int numColumnInRow = mNumColumnsInRow[row];
|
||||||
final int column = getColumnNumber(pos);
|
final int column = getColumnNumber(pos);
|
||||||
if (column == 0)
|
if (column == 0)
|
||||||
rowFlags |= Keyboard.EDGE_LEFT;
|
key.markAsLeftEdge(this);
|
||||||
if (column == numColumnInRow - 1)
|
if (column == numColumnInRow - 1)
|
||||||
rowFlags |= Keyboard.EDGE_RIGHT;
|
key.markAsRightEdge(this);
|
||||||
|
|
||||||
return rowFlags;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,7 +210,8 @@ public class MoreSuggestions extends Keyboard {
|
||||||
final int index = pos + SUGGESTION_CODE_BASE;
|
final int index = pos + SUGGESTION_CODE_BASE;
|
||||||
final Key key = new Key(
|
final Key key = new Key(
|
||||||
params, word, info, null, index, null, x, y, width,
|
params, word, info, null, index, null, x, y, width,
|
||||||
params.mDefaultRowHeight, params.getFlags(pos));
|
params.mDefaultRowHeight);
|
||||||
|
params.markAsEdgeKey(key, pos);
|
||||||
params.onAddKey(key);
|
params.onAddKey(key);
|
||||||
final int columnNumber = params.getColumnNumber(pos);
|
final int columnNumber = params.getColumnNumber(pos);
|
||||||
final int numColumnInRow = params.getNumColumnInRow(pos);
|
final int numColumnInRow = params.getNumColumnInRow(pos);
|
||||||
|
|
Loading…
Reference in New Issue