parent
cdaee868a3
commit
08ae0d5ca0
|
@ -26,10 +26,8 @@ import android.graphics.Paint.Align;
|
||||||
import android.graphics.PorterDuff;
|
import android.graphics.PorterDuff;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.graphics.Region;
|
import android.graphics.Region;
|
||||||
import android.graphics.Typeface;
|
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.util.SparseArray;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import com.android.inputmethod.keyboard.internal.KeyDrawParams;
|
import com.android.inputmethod.keyboard.internal.KeyDrawParams;
|
||||||
|
@ -73,15 +71,15 @@ import java.util.HashSet;
|
||||||
*/
|
*/
|
||||||
public class KeyboardView extends View {
|
public class KeyboardView extends View {
|
||||||
// XML attributes
|
// XML attributes
|
||||||
protected final KeyVisualAttributes mKeyVisualAttributes;
|
private final KeyVisualAttributes mKeyVisualAttributes;
|
||||||
private final int mKeyLabelHorizontalPadding;
|
private final int mKeyLabelHorizontalPadding;
|
||||||
private final float mKeyHintLetterPadding;
|
private final float mKeyHintLetterPadding;
|
||||||
private final float mKeyPopupHintLetterPadding;
|
private final float mKeyPopupHintLetterPadding;
|
||||||
private final float mKeyShiftedLetterHintPadding;
|
private final float mKeyShiftedLetterHintPadding;
|
||||||
private final float mKeyTextShadowRadius;
|
private final float mKeyTextShadowRadius;
|
||||||
protected final float mVerticalCorrection;
|
private final float mVerticalCorrection;
|
||||||
protected final Drawable mKeyBackground;
|
private final Drawable mKeyBackground;
|
||||||
protected final Rect mKeyBackgroundPadding = new Rect();
|
private final Rect mKeyBackgroundPadding = new Rect();
|
||||||
|
|
||||||
// HORIZONTAL ELLIPSIS "...", character for popup hint.
|
// HORIZONTAL ELLIPSIS "...", character for popup hint.
|
||||||
private static final String POPUP_HINT_CHAR = "\u2026";
|
private static final String POPUP_HINT_CHAR = "\u2026";
|
||||||
|
@ -113,10 +111,6 @@ public class KeyboardView extends View {
|
||||||
private final Canvas mOffscreenCanvas = new Canvas();
|
private final Canvas mOffscreenCanvas = new Canvas();
|
||||||
private final Paint mPaint = new Paint();
|
private final Paint mPaint = new Paint();
|
||||||
private final Paint.FontMetrics mFontMetrics = new Paint.FontMetrics();
|
private final Paint.FontMetrics mFontMetrics = new Paint.FontMetrics();
|
||||||
// This sparse array caches key label text height in pixel indexed by key label text size.
|
|
||||||
private static final SparseArray<Float> sTextHeightCache = CollectionUtils.newSparseArray();
|
|
||||||
// This sparse array caches key label text width in pixel indexed by key label text size.
|
|
||||||
private static final SparseArray<Float> sTextWidthCache = CollectionUtils.newSparseArray();
|
|
||||||
private static final char[] KEY_LABEL_REFERENCE_CHAR = { 'M' };
|
private static final char[] KEY_LABEL_REFERENCE_CHAR = { 'M' };
|
||||||
private static final char[] KEY_NUMERIC_HINT_LABEL_REFERENCE_CHAR = { '8' };
|
private static final char[] KEY_NUMERIC_HINT_LABEL_REFERENCE_CHAR = { '8' };
|
||||||
|
|
||||||
|
@ -134,15 +128,15 @@ public class KeyboardView extends View {
|
||||||
mKeyLabelHorizontalPadding = keyboardViewAttr.getDimensionPixelOffset(
|
mKeyLabelHorizontalPadding = keyboardViewAttr.getDimensionPixelOffset(
|
||||||
R.styleable.KeyboardView_keyLabelHorizontalPadding, 0);
|
R.styleable.KeyboardView_keyLabelHorizontalPadding, 0);
|
||||||
mKeyHintLetterPadding = keyboardViewAttr.getDimension(
|
mKeyHintLetterPadding = keyboardViewAttr.getDimension(
|
||||||
R.styleable.KeyboardView_keyHintLetterPadding, 0);
|
R.styleable.KeyboardView_keyHintLetterPadding, 0.0f);
|
||||||
mKeyPopupHintLetterPadding = keyboardViewAttr.getDimension(
|
mKeyPopupHintLetterPadding = keyboardViewAttr.getDimension(
|
||||||
R.styleable.KeyboardView_keyPopupHintLetterPadding, 0);
|
R.styleable.KeyboardView_keyPopupHintLetterPadding, 0.0f);
|
||||||
mKeyShiftedLetterHintPadding = keyboardViewAttr.getDimension(
|
mKeyShiftedLetterHintPadding = keyboardViewAttr.getDimension(
|
||||||
R.styleable.KeyboardView_keyShiftedLetterHintPadding, 0);
|
R.styleable.KeyboardView_keyShiftedLetterHintPadding, 0.0f);
|
||||||
mKeyTextShadowRadius = keyboardViewAttr.getFloat(
|
mKeyTextShadowRadius = keyboardViewAttr.getFloat(
|
||||||
R.styleable.KeyboardView_keyTextShadowRadius, 0.0f);
|
R.styleable.KeyboardView_keyTextShadowRadius, 0.0f);
|
||||||
mVerticalCorrection = keyboardViewAttr.getDimension(
|
mVerticalCorrection = keyboardViewAttr.getDimension(
|
||||||
R.styleable.KeyboardView_verticalCorrection, 0);
|
R.styleable.KeyboardView_verticalCorrection, 0.0f);
|
||||||
keyboardViewAttr.recycle();
|
keyboardViewAttr.recycle();
|
||||||
|
|
||||||
final TypedArray keyAttr = context.obtainStyledAttributes(attrs,
|
final TypedArray keyAttr = context.obtainStyledAttributes(attrs,
|
||||||
|
@ -185,6 +179,14 @@ public class KeyboardView extends View {
|
||||||
return mKeyboard;
|
return mKeyboard;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected float getVerticalCorrection() {
|
||||||
|
return mVerticalCorrection;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void updateKeyDrawParams(final int keyHeight) {
|
||||||
|
mKeyDrawParams.updateParams(keyHeight, mKeyVisualAttributes);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
|
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
|
||||||
if (mKeyboard != null) {
|
if (mKeyboard != null) {
|
||||||
|
@ -213,7 +215,7 @@ public class KeyboardView extends View {
|
||||||
}
|
}
|
||||||
onDrawKeyboard(mOffscreenCanvas);
|
onDrawKeyboard(mOffscreenCanvas);
|
||||||
}
|
}
|
||||||
canvas.drawBitmap(mOffscreenBuffer, 0, 0, null);
|
canvas.drawBitmap(mOffscreenBuffer, 0.0f, 0.0f, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean maybeAllocateOffscreenBuffer() {
|
private boolean maybeAllocateOffscreenBuffer() {
|
||||||
|
@ -333,7 +335,7 @@ public class KeyboardView extends View {
|
||||||
canvas.translate(bgX, bgY);
|
canvas.translate(bgX, bgY);
|
||||||
background.draw(canvas);
|
background.draw(canvas);
|
||||||
if (LatinImeLogger.sVISUALDEBUG) {
|
if (LatinImeLogger.sVISUALDEBUG) {
|
||||||
drawRectangle(canvas, 0, 0, bgWidth, bgHeight, 0x80c00000, new Paint());
|
drawRectangle(canvas, 0.0f, 0.0f, bgWidth, bgHeight, 0x80c00000, new Paint());
|
||||||
}
|
}
|
||||||
canvas.translate(-bgX, -bgY);
|
canvas.translate(-bgX, -bgY);
|
||||||
}
|
}
|
||||||
|
@ -347,7 +349,7 @@ public class KeyboardView extends View {
|
||||||
final float centerY = keyHeight * 0.5f;
|
final float centerY = keyHeight * 0.5f;
|
||||||
|
|
||||||
if (LatinImeLogger.sVISUALDEBUG) {
|
if (LatinImeLogger.sVISUALDEBUG) {
|
||||||
drawRectangle(canvas, 0, 0, keyWidth, keyHeight, 0x800000c0, new Paint());
|
drawRectangle(canvas, 0.0f, 0.0f, keyWidth, keyHeight, 0x800000c0, new Paint());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw key label.
|
// Draw key label.
|
||||||
|
@ -357,14 +359,16 @@ public class KeyboardView extends View {
|
||||||
final String label = key.mLabel;
|
final String label = key.mLabel;
|
||||||
paint.setTypeface(key.selectTypeface(params));
|
paint.setTypeface(key.selectTypeface(params));
|
||||||
paint.setTextSize(key.selectTextSize(params));
|
paint.setTextSize(key.selectTextSize(params));
|
||||||
final float labelCharHeight = getCharHeight(KEY_LABEL_REFERENCE_CHAR, paint);
|
final float labelCharHeight = TypefaceUtils.getCharHeight(
|
||||||
final float labelCharWidth = getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint);
|
KEY_LABEL_REFERENCE_CHAR, paint);
|
||||||
|
final float labelCharWidth = TypefaceUtils.getCharWidth(
|
||||||
|
KEY_LABEL_REFERENCE_CHAR, paint);
|
||||||
|
|
||||||
// Vertical label text alignment.
|
// Vertical label text alignment.
|
||||||
final float baseline = centerY + labelCharHeight / 2;
|
final float baseline = centerY + labelCharHeight / 2.0f;
|
||||||
|
|
||||||
// Horizontal label text alignment
|
// Horizontal label text alignment
|
||||||
float labelWidth = 0;
|
float labelWidth = 0.0f;
|
||||||
if (key.isAlignLeft()) {
|
if (key.isAlignLeft()) {
|
||||||
positionX = mKeyLabelHorizontalPadding;
|
positionX = mKeyLabelHorizontalPadding;
|
||||||
paint.setTextAlign(Align.LEFT);
|
paint.setTextAlign(Align.LEFT);
|
||||||
|
@ -373,31 +377,31 @@ public class KeyboardView extends View {
|
||||||
paint.setTextAlign(Align.RIGHT);
|
paint.setTextAlign(Align.RIGHT);
|
||||||
} else if (key.isAlignLeftOfCenter()) {
|
} else if (key.isAlignLeftOfCenter()) {
|
||||||
// TODO: Parameterise this?
|
// TODO: Parameterise this?
|
||||||
positionX = centerX - labelCharWidth * 7 / 4;
|
positionX = centerX - labelCharWidth * 7.0f / 4.0f;
|
||||||
paint.setTextAlign(Align.LEFT);
|
paint.setTextAlign(Align.LEFT);
|
||||||
} else if (key.hasLabelWithIconLeft() && icon != null) {
|
} else if (key.hasLabelWithIconLeft() && icon != null) {
|
||||||
labelWidth = getLabelWidth(label, paint) + icon.getIntrinsicWidth()
|
labelWidth = TypefaceUtils.getLabelWidth(label, paint) + icon.getIntrinsicWidth()
|
||||||
+ LABEL_ICON_MARGIN * keyWidth;
|
+ LABEL_ICON_MARGIN * keyWidth;
|
||||||
positionX = centerX + labelWidth / 2;
|
positionX = centerX + labelWidth / 2.0f;
|
||||||
paint.setTextAlign(Align.RIGHT);
|
paint.setTextAlign(Align.RIGHT);
|
||||||
} else if (key.hasLabelWithIconRight() && icon != null) {
|
} else if (key.hasLabelWithIconRight() && icon != null) {
|
||||||
labelWidth = getLabelWidth(label, paint) + icon.getIntrinsicWidth()
|
labelWidth = TypefaceUtils.getLabelWidth(label, paint) + icon.getIntrinsicWidth()
|
||||||
+ LABEL_ICON_MARGIN * keyWidth;
|
+ LABEL_ICON_MARGIN * keyWidth;
|
||||||
positionX = centerX - labelWidth / 2;
|
positionX = centerX - labelWidth / 2.0f;
|
||||||
paint.setTextAlign(Align.LEFT);
|
paint.setTextAlign(Align.LEFT);
|
||||||
} else {
|
} else {
|
||||||
positionX = centerX;
|
positionX = centerX;
|
||||||
paint.setTextAlign(Align.CENTER);
|
paint.setTextAlign(Align.CENTER);
|
||||||
}
|
}
|
||||||
if (key.needsXScale()) {
|
if (key.needsXScale()) {
|
||||||
paint.setTextScaleX(
|
paint.setTextScaleX(Math.min(1.0f,
|
||||||
Math.min(1.0f, (keyWidth * MAX_LABEL_RATIO) / getLabelWidth(label, paint)));
|
(keyWidth * MAX_LABEL_RATIO) / TypefaceUtils.getLabelWidth(label, paint)));
|
||||||
}
|
}
|
||||||
|
|
||||||
paint.setColor(key.selectTextColor(params));
|
paint.setColor(key.selectTextColor(params));
|
||||||
if (key.isEnabled()) {
|
if (key.isEnabled()) {
|
||||||
// Set a drop shadow for the text
|
// Set a drop shadow for the text
|
||||||
paint.setShadowLayer(mKeyTextShadowRadius, 0, 0, params.mTextShadowColor);
|
paint.setShadowLayer(mKeyTextShadowRadius, 0.0f, 0.0f, params.mTextShadowColor);
|
||||||
} else {
|
} else {
|
||||||
// Make label invisible
|
// Make label invisible
|
||||||
paint.setColor(Color.TRANSPARENT);
|
paint.setColor(Color.TRANSPARENT);
|
||||||
|
@ -405,7 +409,7 @@ public class KeyboardView extends View {
|
||||||
blendAlpha(paint, params.mAnimAlpha);
|
blendAlpha(paint, params.mAnimAlpha);
|
||||||
canvas.drawText(label, 0, label.length(), positionX, baseline, paint);
|
canvas.drawText(label, 0, label.length(), positionX, baseline, paint);
|
||||||
// Turn off drop shadow and reset x-scale.
|
// Turn off drop shadow and reset x-scale.
|
||||||
paint.setShadowLayer(0, 0, 0, 0);
|
paint.setShadowLayer(0.0f, 0.0f, 0.0f, Color.TRANSPARENT);
|
||||||
paint.setTextScaleX(1.0f);
|
paint.setTextScaleX(1.0f);
|
||||||
|
|
||||||
if (icon != null) {
|
if (icon != null) {
|
||||||
|
@ -413,10 +417,10 @@ public class KeyboardView extends View {
|
||||||
final int iconHeight = icon.getIntrinsicHeight();
|
final int iconHeight = icon.getIntrinsicHeight();
|
||||||
final int iconY = (keyHeight - iconHeight) / 2;
|
final int iconY = (keyHeight - iconHeight) / 2;
|
||||||
if (key.hasLabelWithIconLeft()) {
|
if (key.hasLabelWithIconLeft()) {
|
||||||
final int iconX = (int)(centerX - labelWidth / 2);
|
final int iconX = (int)(centerX - labelWidth / 2.0f);
|
||||||
drawIcon(canvas, icon, iconX, iconY, iconWidth, iconHeight);
|
drawIcon(canvas, icon, iconX, iconY, iconWidth, iconHeight);
|
||||||
} else if (key.hasLabelWithIconRight()) {
|
} else if (key.hasLabelWithIconRight()) {
|
||||||
final int iconX = (int)(centerX + labelWidth / 2 - iconWidth);
|
final int iconX = (int)(centerX + labelWidth / 2.0f - iconWidth);
|
||||||
drawIcon(canvas, icon, iconX, iconY, iconWidth, iconHeight);
|
drawIcon(canvas, icon, iconX, iconY, iconWidth, iconHeight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -439,20 +443,23 @@ public class KeyboardView extends View {
|
||||||
// The hint label is placed just right of the key label. Used mainly on
|
// The hint label is placed just right of the key label. Used mainly on
|
||||||
// "phone number" layout.
|
// "phone number" layout.
|
||||||
// TODO: Generalize the following calculations.
|
// TODO: Generalize the following calculations.
|
||||||
hintX = positionX + getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint) * 2;
|
hintX = positionX
|
||||||
hintY = centerY + getCharHeight(KEY_LABEL_REFERENCE_CHAR, paint) / 2;
|
+ TypefaceUtils.getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint) * 2.0f;
|
||||||
|
hintY = centerY
|
||||||
|
+ TypefaceUtils.getCharHeight(KEY_LABEL_REFERENCE_CHAR, paint) / 2.0f;
|
||||||
paint.setTextAlign(Align.LEFT);
|
paint.setTextAlign(Align.LEFT);
|
||||||
} else if (key.hasShiftedLetterHint()) {
|
} else if (key.hasShiftedLetterHint()) {
|
||||||
// The hint label is placed at top-right corner of the key. Used mainly on tablet.
|
// The hint label is placed at top-right corner of the key. Used mainly on tablet.
|
||||||
hintX = keyWidth - mKeyShiftedLetterHintPadding
|
hintX = keyWidth - mKeyShiftedLetterHintPadding
|
||||||
- getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint) / 2;
|
- TypefaceUtils.getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint) / 2.0f;
|
||||||
paint.getFontMetrics(mFontMetrics);
|
paint.getFontMetrics(mFontMetrics);
|
||||||
hintY = -mFontMetrics.top;
|
hintY = -mFontMetrics.top;
|
||||||
paint.setTextAlign(Align.CENTER);
|
paint.setTextAlign(Align.CENTER);
|
||||||
} else { // key.hasHintLetter()
|
} else { // key.hasHintLetter()
|
||||||
// The hint letter is placed at top-right corner of the key. Used mainly on phone.
|
// The hint letter is placed at top-right corner of the key. Used mainly on phone.
|
||||||
hintX = keyWidth - mKeyHintLetterPadding
|
hintX = keyWidth - mKeyHintLetterPadding
|
||||||
- getCharWidth(KEY_NUMERIC_HINT_LABEL_REFERENCE_CHAR, paint) / 2;
|
- TypefaceUtils.getCharWidth(KEY_NUMERIC_HINT_LABEL_REFERENCE_CHAR, paint)
|
||||||
|
/ 2.0f;
|
||||||
hintY = -paint.ascent();
|
hintY = -paint.ascent();
|
||||||
paint.setTextAlign(Align.CENTER);
|
paint.setTextAlign(Align.CENTER);
|
||||||
}
|
}
|
||||||
|
@ -506,7 +513,7 @@ public class KeyboardView extends View {
|
||||||
paint.setColor(params.mHintLabelColor);
|
paint.setColor(params.mHintLabelColor);
|
||||||
paint.setTextAlign(Align.CENTER);
|
paint.setTextAlign(Align.CENTER);
|
||||||
final float hintX = keyWidth - mKeyHintLetterPadding
|
final float hintX = keyWidth - mKeyHintLetterPadding
|
||||||
- getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint) / 2;
|
- TypefaceUtils.getCharWidth(KEY_LABEL_REFERENCE_CHAR, paint) / 2.0f;
|
||||||
final float hintY = keyHeight - mKeyPopupHintLetterPadding;
|
final float hintY = keyHeight - mKeyPopupHintLetterPadding;
|
||||||
canvas.drawText(POPUP_HINT_CHAR, hintX, hintY, paint);
|
canvas.drawText(POPUP_HINT_CHAR, hintX, hintY, paint);
|
||||||
|
|
||||||
|
@ -517,54 +524,6 @@ public class KeyboardView extends View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int getCharGeometryCacheKey(final char referenceChar, final Paint paint) {
|
|
||||||
final int labelSize = (int)paint.getTextSize();
|
|
||||||
final Typeface face = paint.getTypeface();
|
|
||||||
final int codePointOffset = referenceChar << 15;
|
|
||||||
if (face == Typeface.DEFAULT) {
|
|
||||||
return codePointOffset + labelSize;
|
|
||||||
} else if (face == Typeface.DEFAULT_BOLD) {
|
|
||||||
return codePointOffset + labelSize + 0x1000;
|
|
||||||
} else if (face == Typeface.MONOSPACE) {
|
|
||||||
return codePointOffset + labelSize + 0x2000;
|
|
||||||
} else {
|
|
||||||
return codePointOffset + labelSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Working variable for the following methods.
|
|
||||||
private final Rect mTextBounds = new Rect();
|
|
||||||
|
|
||||||
private float getCharHeight(final char[] referenceChar, final Paint paint) {
|
|
||||||
final int key = getCharGeometryCacheKey(referenceChar[0], paint);
|
|
||||||
final Float cachedValue = sTextHeightCache.get(key);
|
|
||||||
if (cachedValue != null)
|
|
||||||
return cachedValue;
|
|
||||||
|
|
||||||
paint.getTextBounds(referenceChar, 0, 1, mTextBounds);
|
|
||||||
final float height = mTextBounds.height();
|
|
||||||
sTextHeightCache.put(key, height);
|
|
||||||
return height;
|
|
||||||
}
|
|
||||||
|
|
||||||
private float getCharWidth(final char[] referenceChar, final Paint paint) {
|
|
||||||
final int key = getCharGeometryCacheKey(referenceChar[0], paint);
|
|
||||||
final Float cachedValue = sTextWidthCache.get(key);
|
|
||||||
if (cachedValue != null)
|
|
||||||
return cachedValue;
|
|
||||||
|
|
||||||
paint.getTextBounds(referenceChar, 0, 1, mTextBounds);
|
|
||||||
final float width = mTextBounds.width();
|
|
||||||
sTextWidthCache.put(key, width);
|
|
||||||
return width;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Remove this method.
|
|
||||||
public float getLabelWidth(final String label, final Paint paint) {
|
|
||||||
paint.getTextBounds(label, 0, label.length(), mTextBounds);
|
|
||||||
return mTextBounds.width();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static void drawIcon(final Canvas canvas, final Drawable icon, final int x,
|
protected static void drawIcon(final Canvas canvas, final Drawable icon, final int x,
|
||||||
final int y, final int width, final int height) {
|
final int y, final int width, final int height) {
|
||||||
canvas.translate(x, y);
|
canvas.translate(x, y);
|
||||||
|
@ -578,7 +537,7 @@ public class KeyboardView extends View {
|
||||||
paint.setStyle(Paint.Style.STROKE);
|
paint.setStyle(Paint.Style.STROKE);
|
||||||
paint.setStrokeWidth(1.0f);
|
paint.setStrokeWidth(1.0f);
|
||||||
paint.setColor(color);
|
paint.setColor(color);
|
||||||
canvas.drawLine(0, y, w, y, paint);
|
canvas.drawLine(0.0f, y, w, y, paint);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void drawVerticalLine(final Canvas canvas, final float x, final float h,
|
private static void drawVerticalLine(final Canvas canvas, final float x, final float h,
|
||||||
|
@ -586,7 +545,7 @@ public class KeyboardView extends View {
|
||||||
paint.setStyle(Paint.Style.STROKE);
|
paint.setStyle(Paint.Style.STROKE);
|
||||||
paint.setStrokeWidth(1.0f);
|
paint.setStrokeWidth(1.0f);
|
||||||
paint.setColor(color);
|
paint.setColor(color);
|
||||||
canvas.drawLine(x, 0, x, h, paint);
|
canvas.drawLine(x, 0.0f, x, h, paint);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void drawRectangle(final Canvas canvas, final float x, final float y,
|
private static void drawRectangle(final Canvas canvas, final float x, final float y,
|
||||||
|
@ -595,15 +554,20 @@ public class KeyboardView extends View {
|
||||||
paint.setStrokeWidth(1.0f);
|
paint.setStrokeWidth(1.0f);
|
||||||
paint.setColor(color);
|
paint.setColor(color);
|
||||||
canvas.translate(x, y);
|
canvas.translate(x, y);
|
||||||
canvas.drawRect(0, 0, w, h, paint);
|
canvas.drawRect(0.0f, 0.0f, w, h, paint);
|
||||||
canvas.translate(-x, -y);
|
canvas.translate(-x, -y);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Paint newDefaultLabelPaint() {
|
public Paint newLabelPaint(final Key key) {
|
||||||
final Paint paint = new Paint();
|
final Paint paint = new Paint();
|
||||||
paint.setAntiAlias(true);
|
paint.setAntiAlias(true);
|
||||||
paint.setTypeface(mKeyDrawParams.mTypeface);
|
if (key == null) {
|
||||||
paint.setTextSize(mKeyDrawParams.mLabelSize);
|
paint.setTypeface(mKeyDrawParams.mTypeface);
|
||||||
|
paint.setTextSize(mKeyDrawParams.mLabelSize);
|
||||||
|
} else {
|
||||||
|
paint.setTypeface(key.selectTypeface(mKeyDrawParams));
|
||||||
|
paint.setTextSize(key.selectTextSize(mKeyDrawParams));
|
||||||
|
}
|
||||||
return paint;
|
return paint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -530,9 +530,9 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
|
||||||
R.styleable.MainKeyboardView_altCodeKeyWhileTypingFadeinAnimator, 0);
|
R.styleable.MainKeyboardView_altCodeKeyWhileTypingFadeinAnimator, 0);
|
||||||
|
|
||||||
final float keyHysteresisDistance = mainKeyboardViewAttr.getDimension(
|
final float keyHysteresisDistance = mainKeyboardViewAttr.getDimension(
|
||||||
R.styleable.MainKeyboardView_keyHysteresisDistance, 0);
|
R.styleable.MainKeyboardView_keyHysteresisDistance, 0.0f);
|
||||||
final float keyHysteresisDistanceForSlidingModifier = mainKeyboardViewAttr.getDimension(
|
final float keyHysteresisDistanceForSlidingModifier = mainKeyboardViewAttr.getDimension(
|
||||||
R.styleable.MainKeyboardView_keyHysteresisDistanceForSlidingModifier, 0);
|
R.styleable.MainKeyboardView_keyHysteresisDistanceForSlidingModifier, 0.0f);
|
||||||
mKeyDetector = new KeyDetector(
|
mKeyDetector = new KeyDetector(
|
||||||
keyHysteresisDistance, keyHysteresisDistanceForSlidingModifier);
|
keyHysteresisDistance, keyHysteresisDistanceForSlidingModifier);
|
||||||
mKeyTimerHandler = new KeyTimerHandler(this, mainKeyboardViewAttr);
|
mKeyTimerHandler = new KeyTimerHandler(this, mainKeyboardViewAttr);
|
||||||
|
@ -655,7 +655,7 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
|
||||||
mKeyTimerHandler.cancelLongPressTimer();
|
mKeyTimerHandler.cancelLongPressTimer();
|
||||||
super.setKeyboard(keyboard);
|
super.setKeyboard(keyboard);
|
||||||
mKeyDetector.setKeyboard(
|
mKeyDetector.setKeyboard(
|
||||||
keyboard, -getPaddingLeft(), -getPaddingTop() + mVerticalCorrection);
|
keyboard, -getPaddingLeft(), -getPaddingTop() + getVerticalCorrection());
|
||||||
PointerTracker.setKeyDetector(mKeyDetector);
|
PointerTracker.setKeyDetector(mKeyDetector);
|
||||||
mTouchScreenRegulator.setKeyboardGeometry(keyboard.mOccupiedWidth);
|
mTouchScreenRegulator.setKeyboardGeometry(keyboard.mOccupiedWidth);
|
||||||
mMoreKeysKeyboardCache.clear();
|
mMoreKeysKeyboardCache.clear();
|
||||||
|
@ -1329,7 +1329,7 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
|
||||||
|
|
||||||
// Overlay a dark rectangle to dim.
|
// Overlay a dark rectangle to dim.
|
||||||
if (mNeedsToDimEntireKeyboard) {
|
if (mNeedsToDimEntireKeyboard) {
|
||||||
canvas.drawRect(0, 0, getWidth(), getHeight(), mBackgroundDimAlphaPaint);
|
canvas.drawRect(0.0f, 0.0f, getWidth(), getHeight(), mBackgroundDimAlphaPaint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1353,9 +1353,10 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean fitsTextIntoWidth(final int width, final String text, final Paint paint) {
|
private static boolean fitsTextIntoWidth(final int width, final String text,
|
||||||
|
final Paint paint) {
|
||||||
paint.setTextScaleX(1.0f);
|
paint.setTextScaleX(1.0f);
|
||||||
final float textWidth = getLabelWidth(text, paint);
|
final float textWidth = TypefaceUtils.getLabelWidth(text, paint);
|
||||||
if (textWidth < width) {
|
if (textWidth < width) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1366,12 +1367,12 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
|
||||||
}
|
}
|
||||||
|
|
||||||
paint.setTextScaleX(scaleX);
|
paint.setTextScaleX(scaleX);
|
||||||
return getLabelWidth(text, paint) < width;
|
return TypefaceUtils.getLabelWidth(text, paint) < width;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Layout language name on spacebar.
|
// Layout language name on spacebar.
|
||||||
private String layoutLanguageOnSpacebar(final Paint paint, final InputMethodSubtype subtype,
|
private static String layoutLanguageOnSpacebar(final Paint paint,
|
||||||
final int width) {
|
final InputMethodSubtype subtype, final int width) {
|
||||||
// Choose appropriate language name to fit into the width.
|
// Choose appropriate language name to fit into the width.
|
||||||
final String fullText = getFullDisplayName(subtype);
|
final String fullText = getFullDisplayName(subtype);
|
||||||
if (fitsTextIntoWidth(width, fullText, paint)) {
|
if (fitsTextIntoWidth(width, fullText, paint)) {
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
package com.android.inputmethod.keyboard;
|
package com.android.inputmethod.keyboard;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.res.Resources;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
|
|
||||||
|
@ -257,7 +258,6 @@ public final class MoreKeysKeyboard extends Keyboard {
|
||||||
private static final float LABEL_PADDING_RATIO = 0.2f;
|
private static final float LABEL_PADDING_RATIO = 0.2f;
|
||||||
private static final float DIVIDER_RATIO = 0.2f;
|
private static final float DIVIDER_RATIO = 0.2f;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The builder of MoreKeysKeyboard.
|
* The builder of MoreKeysKeyboard.
|
||||||
* @param context the context of {@link MoreKeysKeyboardView}.
|
* @param context the context of {@link MoreKeysKeyboardView}.
|
||||||
|
@ -289,10 +289,10 @@ public final class MoreKeysKeyboard extends Keyboard {
|
||||||
// be considered because the vertical positions of both backgrounds were already
|
// be considered because the vertical positions of both backgrounds were already
|
||||||
// adjusted with their bottom paddings deducted.
|
// adjusted with their bottom paddings deducted.
|
||||||
width = keyPreviewDrawParams.mPreviewVisibleWidth;
|
width = keyPreviewDrawParams.mPreviewVisibleWidth;
|
||||||
height = keyPreviewDrawParams.mPreviewVisibleHeight
|
height = keyPreviewDrawParams.mPreviewVisibleHeight + mParams.mVerticalGap;
|
||||||
+ mParams.mVerticalGap;
|
|
||||||
} else {
|
} else {
|
||||||
width = getMaxKeyWidth(parentKeyboardView, parentKey, mParams.mDefaultKeyWidth);
|
width = getMaxKeyWidth(parentKeyboardView, parentKey, mParams.mDefaultKeyWidth,
|
||||||
|
context.getResources());
|
||||||
height = parentKeyboard.mMostCommonKeyHeight;
|
height = parentKeyboard.mMostCommonKeyHeight;
|
||||||
}
|
}
|
||||||
final int dividerWidth;
|
final int dividerWidth;
|
||||||
|
@ -310,22 +310,18 @@ public final class MoreKeysKeyboard extends Keyboard {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int getMaxKeyWidth(final KeyboardView view, final Key parentKey,
|
private static int getMaxKeyWidth(final KeyboardView view, final Key parentKey,
|
||||||
final int minKeyWidth) {
|
final int minKeyWidth, final Resources res) {
|
||||||
final int padding = (int)(view.getResources()
|
final float padding =
|
||||||
.getDimension(R.dimen.more_keys_keyboard_key_horizontal_padding)
|
res.getDimension(R.dimen.more_keys_keyboard_key_horizontal_padding)
|
||||||
+ (parentKey.hasLabelsInMoreKeys() ? minKeyWidth * LABEL_PADDING_RATIO : 0));
|
+ (parentKey.hasLabelsInMoreKeys() ? minKeyWidth * LABEL_PADDING_RATIO : 0.0f);
|
||||||
final Paint paint = view.newDefaultLabelPaint();
|
final Paint paint = view.newLabelPaint(parentKey);
|
||||||
paint.setTypeface(parentKey.selectTypeface(view.mKeyDrawParams));
|
|
||||||
paint.setTextSize(parentKey.selectMoreKeyTextSize(view.mKeyDrawParams));
|
|
||||||
int maxWidth = minKeyWidth;
|
int maxWidth = minKeyWidth;
|
||||||
for (final MoreKeySpec spec : parentKey.mMoreKeys) {
|
for (final MoreKeySpec spec : parentKey.mMoreKeys) {
|
||||||
final String label = spec.mLabel;
|
final String label = spec.mLabel;
|
||||||
// If the label is single letter, minKeyWidth is enough to hold the label.
|
// If the label is single letter, minKeyWidth is enough to hold the label.
|
||||||
if (label != null && StringUtils.codePointCount(label) > 1) {
|
if (label != null && StringUtils.codePointCount(label) > 1) {
|
||||||
final int width = (int)view.getLabelWidth(label, paint) + padding;
|
maxWidth = Math.max(maxWidth,
|
||||||
if (maxWidth < width) {
|
(int)(TypefaceUtils.getLabelWidth(label, paint) + padding));
|
||||||
maxWidth = width;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return maxWidth;
|
return maxWidth;
|
||||||
|
|
|
@ -71,7 +71,7 @@ public class MoreKeysKeyboardView extends KeyboardView implements MoreKeysPanel
|
||||||
public void setKeyboard(final Keyboard keyboard) {
|
public void setKeyboard(final Keyboard keyboard) {
|
||||||
super.setKeyboard(keyboard);
|
super.setKeyboard(keyboard);
|
||||||
mKeyDetector.setKeyboard(keyboard, -getPaddingLeft(),
|
mKeyDetector.setKeyboard(keyboard, -getPaddingLeft(),
|
||||||
-getPaddingTop() + mVerticalCorrection);
|
-getPaddingTop() + getVerticalCorrection());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,91 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2013 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.inputmethod.keyboard;
|
||||||
|
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.graphics.Typeface;
|
||||||
|
import android.util.SparseArray;
|
||||||
|
|
||||||
|
import com.android.inputmethod.latin.CollectionUtils;
|
||||||
|
|
||||||
|
public final class TypefaceUtils {
|
||||||
|
private TypefaceUtils() {
|
||||||
|
// This utility class is not publicly instantiable.
|
||||||
|
}
|
||||||
|
|
||||||
|
// This sparse array caches key label text height in pixel indexed by key label text size.
|
||||||
|
private static final SparseArray<Float> sTextHeightCache = CollectionUtils.newSparseArray();
|
||||||
|
// Working variable for the following method.
|
||||||
|
private static final Rect sTextHeightBounds = new Rect();
|
||||||
|
|
||||||
|
public static float getCharHeight(final char[] referenceChar, final Paint paint) {
|
||||||
|
final int key = getCharGeometryCacheKey(referenceChar[0], paint);
|
||||||
|
synchronized (sTextHeightCache) {
|
||||||
|
final Float cachedValue = sTextHeightCache.get(key);
|
||||||
|
if (cachedValue != null) {
|
||||||
|
return cachedValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
paint.getTextBounds(referenceChar, 0, 1, sTextHeightBounds);
|
||||||
|
final float height = sTextHeightBounds.height();
|
||||||
|
sTextHeightCache.put(key, height);
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This sparse array caches key label text width in pixel indexed by key label text size.
|
||||||
|
private static final SparseArray<Float> sTextWidthCache = CollectionUtils.newSparseArray();
|
||||||
|
// Working variable for the following method.
|
||||||
|
private static final Rect sTextWidthBounds = new Rect();
|
||||||
|
|
||||||
|
public static float getCharWidth(final char[] referenceChar, final Paint paint) {
|
||||||
|
final int key = getCharGeometryCacheKey(referenceChar[0], paint);
|
||||||
|
synchronized (sTextWidthCache) {
|
||||||
|
final Float cachedValue = sTextWidthCache.get(key);
|
||||||
|
if (cachedValue != null) {
|
||||||
|
return cachedValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
paint.getTextBounds(referenceChar, 0, 1, sTextWidthBounds);
|
||||||
|
final float width = sTextWidthBounds.width();
|
||||||
|
sTextWidthCache.put(key, width);
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int getCharGeometryCacheKey(final char referenceChar, final Paint paint) {
|
||||||
|
final int labelSize = (int)paint.getTextSize();
|
||||||
|
final Typeface face = paint.getTypeface();
|
||||||
|
final int codePointOffset = referenceChar << 15;
|
||||||
|
if (face == Typeface.DEFAULT) {
|
||||||
|
return codePointOffset + labelSize;
|
||||||
|
} else if (face == Typeface.DEFAULT_BOLD) {
|
||||||
|
return codePointOffset + labelSize + 0x1000;
|
||||||
|
} else if (face == Typeface.MONOSPACE) {
|
||||||
|
return codePointOffset + labelSize + 0x2000;
|
||||||
|
} else {
|
||||||
|
return codePointOffset + labelSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float getLabelWidth(final String label, final Paint paint) {
|
||||||
|
final Rect textBounds = new Rect();
|
||||||
|
paint.getTextBounds(label, 0, label.length(), textBounds);
|
||||||
|
return textBounds.width();
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,12 +16,14 @@
|
||||||
|
|
||||||
package com.android.inputmethod.latin.suggestions;
|
package com.android.inputmethod.latin.suggestions;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
|
|
||||||
import com.android.inputmethod.keyboard.Key;
|
import com.android.inputmethod.keyboard.Key;
|
||||||
import com.android.inputmethod.keyboard.Keyboard;
|
import com.android.inputmethod.keyboard.Keyboard;
|
||||||
|
import com.android.inputmethod.keyboard.TypefaceUtils;
|
||||||
import com.android.inputmethod.keyboard.internal.KeyboardBuilder;
|
import com.android.inputmethod.keyboard.internal.KeyboardBuilder;
|
||||||
import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
|
import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
|
||||||
import com.android.inputmethod.keyboard.internal.KeyboardParams;
|
import com.android.inputmethod.keyboard.internal.KeyboardParams;
|
||||||
|
@ -50,16 +52,12 @@ public final class MoreSuggestions extends Keyboard {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Remove {@link MoreSuggestionsView} argument.
|
|
||||||
public int layout(final SuggestedWords suggestions, final int fromPos, final int maxWidth,
|
public int layout(final SuggestedWords suggestions, final int fromPos, final int maxWidth,
|
||||||
final int minWidth, final int maxRow, final MoreSuggestionsView view) {
|
final int minWidth, final int maxRow, final Paint paint, final Resources res) {
|
||||||
clearKeys();
|
clearKeys();
|
||||||
final Resources res = view.getResources();
|
|
||||||
mDivider = res.getDrawable(R.drawable.more_suggestions_divider);
|
mDivider = res.getDrawable(R.drawable.more_suggestions_divider);
|
||||||
mDividerWidth = mDivider.getIntrinsicWidth();
|
mDividerWidth = mDivider.getIntrinsicWidth();
|
||||||
final int padding = (int) res.getDimension(
|
final float padding = res.getDimension(R.dimen.more_suggestions_key_horizontal_padding);
|
||||||
R.dimen.more_suggestions_key_horizontal_padding);
|
|
||||||
final Paint paint = view.newDefaultLabelPaint();
|
|
||||||
|
|
||||||
int row = 0;
|
int row = 0;
|
||||||
int pos = fromPos, rowStartPos = fromPos;
|
int pos = fromPos, rowStartPos = fromPos;
|
||||||
|
@ -67,7 +65,7 @@ public final class MoreSuggestions extends Keyboard {
|
||||||
while (pos < size) {
|
while (pos < size) {
|
||||||
final String word = suggestions.getWord(pos);
|
final String word = suggestions.getWord(pos);
|
||||||
// TODO: Should take care of text x-scaling.
|
// TODO: Should take care of text x-scaling.
|
||||||
mWidths[pos] = (int)view.getLabelWidth(word, paint) + padding;
|
mWidths[pos] = (int)(TypefaceUtils.getLabelWidth(word, paint) + padding);
|
||||||
final int numColumn = pos - rowStartPos + 1;
|
final int numColumn = pos - rowStartPos + 1;
|
||||||
final int columnWidth =
|
final int columnWidth =
|
||||||
(maxWidth - mDividerWidth * (numColumn - 1)) / numColumn;
|
(maxWidth - mDividerWidth * (numColumn - 1)) / numColumn;
|
||||||
|
@ -169,8 +167,8 @@ public final class MoreSuggestions extends Keyboard {
|
||||||
private int mFromPos;
|
private int mFromPos;
|
||||||
private int mToPos;
|
private int mToPos;
|
||||||
|
|
||||||
public Builder(final MoreSuggestionsView paneView) {
|
public Builder(final Context context, final MoreSuggestionsView paneView) {
|
||||||
super(paneView.getContext(), new MoreSuggestionsParam());
|
super(context, new MoreSuggestionsParam());
|
||||||
mPaneView = paneView;
|
mPaneView = paneView;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,7 +181,7 @@ public final class MoreSuggestions extends Keyboard {
|
||||||
|
|
||||||
mPaneView.updateKeyboardGeometry(mParams.mDefaultRowHeight);
|
mPaneView.updateKeyboardGeometry(mParams.mDefaultRowHeight);
|
||||||
final int count = mParams.layout(suggestions, fromPos, maxWidth, minWidth, maxRow,
|
final int count = mParams.layout(suggestions, fromPos, maxWidth, minWidth, maxRow,
|
||||||
mPaneView);
|
mPaneView.newLabelPaint(null /* key */), mResources);
|
||||||
mFromPos = fromPos;
|
mFromPos = fromPos;
|
||||||
mToPos = fromPos + count;
|
mToPos = fromPos + count;
|
||||||
mSuggestions = suggestions;
|
mSuggestions = suggestions;
|
||||||
|
|
|
@ -43,7 +43,7 @@ public final class MoreSuggestionsView extends MoreKeysKeyboardView {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateKeyboardGeometry(final int keyHeight) {
|
public void updateKeyboardGeometry(final int keyHeight) {
|
||||||
mKeyDrawParams.updateParams(keyHeight, mKeyVisualAttributes);
|
updateKeyDrawParams(keyHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -596,7 +596,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
|
||||||
mMoreSuggestionsContainer = inflater.inflate(R.layout.more_suggestions, null);
|
mMoreSuggestionsContainer = inflater.inflate(R.layout.more_suggestions, null);
|
||||||
mMoreSuggestionsView = (MoreSuggestionsView)mMoreSuggestionsContainer
|
mMoreSuggestionsView = (MoreSuggestionsView)mMoreSuggestionsContainer
|
||||||
.findViewById(R.id.more_suggestions_view);
|
.findViewById(R.id.more_suggestions_view);
|
||||||
mMoreSuggestionsBuilder = new MoreSuggestions.Builder(mMoreSuggestionsView);
|
mMoreSuggestionsBuilder = new MoreSuggestions.Builder(context, mMoreSuggestionsView);
|
||||||
|
|
||||||
final Resources res = context.getResources();
|
final Resources res = context.getResources();
|
||||||
mMoreSuggestionsModalTolerance = res.getDimensionPixelOffset(
|
mMoreSuggestionsModalTolerance = res.getDimensionPixelOffset(
|
||||||
|
|
Loading…
Reference in New Issue