Auto mini keyboard layout
Bug: 4280617 Change-Id: I34c344cbf350fe125589aa14ad69e4bd1f4e6f66main
parent
72a82d7ee8
commit
5d542c2492
|
@ -63,7 +63,7 @@
|
|||
<!-- This configuration is the index of the array {@link KeyboardSwitcher.KEYBOARD_THEMES}. -->
|
||||
<string name="config_default_keyboard_theme_id" translatable="false">4</string>
|
||||
<string name="config_text_size_of_language_on_spacebar" translatable="false">small</string>
|
||||
<integer name="config_max_popup_keyboard_column">10</integer>
|
||||
<integer name="config_max_popup_keyboard_column">5</integer>
|
||||
<!-- Whether or not auto-correction should be enabled by default -->
|
||||
<bool name="enable_autocorrect">true</bool>
|
||||
<string-array name="auto_correction_threshold_values" translatable="false">
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
package com.android.inputmethod.keyboard;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class KeyDetector {
|
||||
|
@ -110,31 +109,4 @@ public abstract class KeyDetector {
|
|||
* @return The nearest key index
|
||||
*/
|
||||
abstract public int getKeyIndexAndNearbyCodes(int x, int y, final int[] allCodes);
|
||||
|
||||
/**
|
||||
* Compute the most common key width in order to use it as proximity key detection threshold.
|
||||
*
|
||||
* @param keyboard The keyboard to compute the most common key width
|
||||
* @return The most common key width in the keyboard
|
||||
*/
|
||||
public static int getMostCommonKeyWidth(final Keyboard keyboard) {
|
||||
if (keyboard == null) return 0;
|
||||
final List<Key> keys = keyboard.getKeys();
|
||||
if (keys == null || keys.size() == 0) return 0;
|
||||
final HashMap<Integer, Integer> histogram = new HashMap<Integer, Integer>();
|
||||
int maxCount = 0;
|
||||
int mostCommonWidth = 0;
|
||||
for (final Key key : keys) {
|
||||
final Integer width = key.mWidth + key.mGap;
|
||||
Integer count = histogram.get(width);
|
||||
if (count == null)
|
||||
count = 0;
|
||||
histogram.put(width, ++count);
|
||||
if (count > maxCount) {
|
||||
maxCount = count;
|
||||
mostCommonWidth = width;
|
||||
}
|
||||
}
|
||||
return mostCommonWidth + keyboard.getHorizontalGap();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -405,6 +405,29 @@ public class Keyboard {
|
|||
return EMPTY_INT_ARRAY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the most common key width in order to use it as proximity key detection threshold.
|
||||
*
|
||||
* @return The most common key width in the keyboard
|
||||
*/
|
||||
public int getMostCommonKeyWidth() {
|
||||
final HashMap<Integer, Integer> histogram = new HashMap<Integer, Integer>();
|
||||
int maxCount = 0;
|
||||
int mostCommonWidth = 0;
|
||||
for (final Key key : mKeys) {
|
||||
final Integer width = key.mWidth + key.mGap;
|
||||
Integer count = histogram.get(width);
|
||||
if (count == null)
|
||||
count = 0;
|
||||
histogram.put(width, ++count);
|
||||
if (count > maxCount) {
|
||||
maxCount = count;
|
||||
mostCommonWidth = width;
|
||||
}
|
||||
}
|
||||
return mostCommonWidth;
|
||||
}
|
||||
|
||||
private void loadKeyboard(Context context, int xmlLayoutResId) {
|
||||
try {
|
||||
KeyboardParser parser = new KeyboardParser(this, context.getResources());
|
||||
|
|
|
@ -501,7 +501,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
|
|||
requestLayout();
|
||||
mKeyboardChanged = true;
|
||||
invalidateAllKeys();
|
||||
mKeyDetector.setProximityThreshold(KeyDetector.getMostCommonKeyWidth(keyboard));
|
||||
mKeyDetector.setProximityThreshold(keyboard.getMostCommonKeyWidth());
|
||||
mMiniKeyboardCache.clear();
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ public class MiniKeyboardBuilder {
|
|||
/* package */ static class MiniKeyboardLayoutParams {
|
||||
public final int mKeyWidth;
|
||||
public final int mRowHeight;
|
||||
/* package */ final boolean mTopRowNeedsCentering;
|
||||
/* package */ final int mTopRowAdjustment;
|
||||
public final int mNumRows;
|
||||
public final int mNumColumns;
|
||||
public final int mLeftKeys;
|
||||
|
@ -55,29 +55,52 @@ public class MiniKeyboardBuilder {
|
|||
if (parentKeyboardWidth / keyWidth < maxColumns)
|
||||
throw new IllegalArgumentException("Keyboard is too small to hold mini keyboard: "
|
||||
+ parentKeyboardWidth + " " + keyWidth + " " + maxColumns);
|
||||
final int numRows = (numKeys + maxColumns - 1) / maxColumns;
|
||||
mKeyWidth = keyWidth;
|
||||
mRowHeight = rowHeight;
|
||||
mNumRows = numRows;
|
||||
|
||||
final int numColumns = Math.min(numKeys, maxColumns);
|
||||
final int topRowKeys = numKeys % numColumns;
|
||||
final int numRows = (numKeys + maxColumns - 1) / maxColumns;
|
||||
mNumRows = numRows;
|
||||
final int numColumns = getOptimizedColumns(numKeys, maxColumns);
|
||||
mNumColumns = numColumns;
|
||||
mTopRowNeedsCentering = topRowKeys != 0 && (numColumns - topRowKeys) % 2 != 0;
|
||||
|
||||
final int numLeftKeys = (numColumns - 1) / 2;
|
||||
final int numRightKeys = numColumns - numLeftKeys; // including default key.
|
||||
final int maxLeftKeys = coordXInParent / keyWidth;
|
||||
final int maxRightKeys = Math.max(1, (parentKeyboardWidth - coordXInParent) / keyWidth);
|
||||
int leftKeys, rightKeys;
|
||||
if (numLeftKeys > maxLeftKeys) {
|
||||
mLeftKeys = maxLeftKeys;
|
||||
mRightKeys = numColumns - maxLeftKeys;
|
||||
leftKeys = maxLeftKeys;
|
||||
rightKeys = numColumns - maxLeftKeys;
|
||||
} else if (numRightKeys > maxRightKeys) {
|
||||
mLeftKeys = numColumns - maxRightKeys;
|
||||
mRightKeys = maxRightKeys;
|
||||
leftKeys = numColumns - maxRightKeys;
|
||||
rightKeys = maxRightKeys;
|
||||
} else {
|
||||
mLeftKeys = numLeftKeys;
|
||||
mRightKeys = numRightKeys;
|
||||
leftKeys = numLeftKeys;
|
||||
rightKeys = numRightKeys;
|
||||
}
|
||||
// Shift right if the left edge of mini keyboard is on the edge of parent keyboard
|
||||
// unless the parent key is on the left edge.
|
||||
if (leftKeys * keyWidth >= coordXInParent && leftKeys > 0) {
|
||||
leftKeys--;
|
||||
rightKeys++;
|
||||
}
|
||||
// Shift left if the right edge of mini keyboard is on the edge of parent keyboard
|
||||
// unless the parent key is on the right edge.
|
||||
if (rightKeys * keyWidth + coordXInParent >= parentKeyboardWidth && rightKeys > 1) {
|
||||
leftKeys++;
|
||||
rightKeys--;
|
||||
}
|
||||
mLeftKeys = leftKeys;
|
||||
mRightKeys = rightKeys;
|
||||
|
||||
// Centering of the top row.
|
||||
final boolean onEdge = (leftKeys == 0 || rightKeys == 1);
|
||||
if (numRows < 2 || onEdge || getTopRowEmptySlots(numKeys, numColumns) % 2 == 0) {
|
||||
mTopRowAdjustment = 0;
|
||||
} else if (mLeftKeys < mRightKeys - 1) {
|
||||
mTopRowAdjustment = 1;
|
||||
} else {
|
||||
mTopRowAdjustment = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -113,14 +136,32 @@ public class MiniKeyboardBuilder {
|
|||
return pos;
|
||||
}
|
||||
|
||||
private static int getTopRowEmptySlots(int numKeys, int numColumns) {
|
||||
final int remainingKeys = numKeys % numColumns;
|
||||
if (remainingKeys == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return numColumns - remainingKeys;
|
||||
}
|
||||
}
|
||||
|
||||
private int getOptimizedColumns(int numKeys, int maxColumns) {
|
||||
int numColumns = Math.min(numKeys, maxColumns);
|
||||
while (getTopRowEmptySlots(numKeys, numColumns) >= mNumRows) {
|
||||
numColumns--;
|
||||
}
|
||||
return numColumns;
|
||||
}
|
||||
|
||||
public int getDefaultKeyCoordX() {
|
||||
return mLeftKeys * mKeyWidth;
|
||||
}
|
||||
|
||||
public int getX(int n, int row) {
|
||||
final int x = getColumnPos(n) * mKeyWidth + getDefaultKeyCoordX();
|
||||
if (isLastRow(row) && mTopRowNeedsCentering)
|
||||
return x - mKeyWidth / 2;
|
||||
if (isTopRow(row)) {
|
||||
return x + mTopRowAdjustment * (mKeyWidth / 2);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
|
@ -131,27 +172,27 @@ public class MiniKeyboardBuilder {
|
|||
public int getRowFlags(int row) {
|
||||
int rowFlags = 0;
|
||||
if (row == 0) rowFlags |= Keyboard.EDGE_TOP;
|
||||
if (isLastRow(row)) rowFlags |= Keyboard.EDGE_BOTTOM;
|
||||
if (isTopRow(row)) rowFlags |= Keyboard.EDGE_BOTTOM;
|
||||
return rowFlags;
|
||||
}
|
||||
|
||||
private boolean isLastRow(int rowCount) {
|
||||
private boolean isTopRow(int rowCount) {
|
||||
return rowCount == mNumRows - 1;
|
||||
}
|
||||
}
|
||||
|
||||
public MiniKeyboardBuilder(KeyboardView view, int layoutTemplateResId, Key popupKey) {
|
||||
public MiniKeyboardBuilder(KeyboardView view, int layoutTemplateResId, Key parentKey) {
|
||||
final Context context = view.getContext();
|
||||
mRes = context.getResources();
|
||||
final MiniKeyboard keyboard = new MiniKeyboard(context, layoutTemplateResId, null);
|
||||
mKeyboard = keyboard;
|
||||
mPopupCharacters = popupKey.mPopupCharacters;
|
||||
mPopupCharacters = parentKey.mPopupCharacters;
|
||||
|
||||
final int keyWidth = getMaxKeyWidth(view, mPopupCharacters, keyboard.getKeyWidth());
|
||||
final MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(
|
||||
mPopupCharacters.length, popupKey.mMaxPopupColumn,
|
||||
mPopupCharacters.length, parentKey.mMaxPopupColumn,
|
||||
keyWidth, keyboard.getRowHeight(),
|
||||
popupKey.mX + (popupKey.mWidth + popupKey.mGap) / 2 - keyWidth / 2,
|
||||
parentKey.mX + (parentKey.mWidth + parentKey.mGap) / 2 - keyWidth / 2,
|
||||
view.getMeasuredWidth());
|
||||
mParams = params;
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -55,7 +55,7 @@ public class SuggestHelper {
|
|||
mSuggest.setCorrectionMode(Suggest.CORRECTION_FULL);
|
||||
mKeyDetector.setKeyboard(mKeyboard, 0, 0);
|
||||
mKeyDetector.setProximityCorrectionEnabled(true);
|
||||
mKeyDetector.setProximityThreshold(KeyDetector.getMostCommonKeyWidth(mKeyboard));
|
||||
mKeyDetector.setProximityThreshold(mKeyboard.getMostCommonKeyWidth());
|
||||
}
|
||||
|
||||
public void setCorrectionMode(int correctionMode) {
|
||||
|
|
Loading…
Reference in New Issue