Introduce hit box to Key and get rid of edge flags

Change-Id: I2b78d2ca756223b5497d01127c3a0190dcc81e57
main
Tadashi G. Takaoka 2011-09-28 18:51:57 +09:00
parent a59f65ad0c
commit 2fc4248700
5 changed files with 45 additions and 58 deletions

View File

@ -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

View File

@ -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';

View File

@ -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);

View File

@ -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;
} }

View File

@ -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);