Support invalidating multiple keys in KeyboardView

Change-Id: I347ccfc2cf60c17f5f0eddec6566662cb3a954ca
This commit is contained in:
Tadashi G. Takaoka 2012-03-13 17:28:52 +09:00
parent 95fcb0cce9
commit 299ac263b3
3 changed files with 51 additions and 44 deletions

View file

@ -114,7 +114,7 @@
<attr name="shadowColor" format="color" /> <attr name="shadowColor" format="color" />
<attr name="shadowRadius" format="float" /> <attr name="shadowRadius" format="float" />
<attr name="backgroundDimAmount" format="float" /> <attr name="backgroundDimAlpha" format="integer" />
<attr name="keyTextStyle" format="enum"> <attr name="keyTextStyle" format="enum">
<!-- This should be aligned with Typeface.NORMAL etc. --> <!-- This should be aligned with Typeface.NORMAL etc. -->

View file

@ -65,7 +65,7 @@
<item name="verticalCorrection">@dimen/keyboard_vertical_correction</item> <item name="verticalCorrection">@dimen/keyboard_vertical_correction</item>
<item name="shadowColor">#BB000000</item> <item name="shadowColor">#BB000000</item>
<item name="shadowRadius">2.75</item> <item name="shadowRadius">2.75</item>
<item name="backgroundDimAmount">0.5</item> <item name="backgroundDimAlpha">128</item>
<!-- Common attributes of LatinKeyboardView --> <!-- Common attributes of LatinKeyboardView -->
<item name="keyHysteresisDistance">@dimen/config_key_hysteresis_distance</item> <item name="keyHysteresisDistance">@dimen/config_key_hysteresis_distance</item>
<item name="touchNoiseThresholdTime">@integer/config_touch_noise_threshold_time</item> <item name="touchNoiseThresholdTime">@integer/config_touch_noise_threshold_time</item>

View file

@ -44,11 +44,12 @@ import com.android.inputmethod.latin.StaticInnerHandlerWrapper;
import com.android.inputmethod.latin.StringUtils; import com.android.inputmethod.latin.StringUtils;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
/** /**
* A view that renders a virtual {@link Keyboard}. * A view that renders a virtual {@link Keyboard}.
* *
* @attr ref R.styleable#KeyboardView_backgroundDimAmount * @attr ref R.styleable#KeyboardView_backgroundDimAlpha
* @attr ref R.styleable#KeyboardView_keyBackground * @attr ref R.styleable#KeyboardView_keyBackground
* @attr ref R.styleable#KeyboardView_keyLetterRatio * @attr ref R.styleable#KeyboardView_keyLetterRatio
* @attr ref R.styleable#KeyboardView_keyLargeLetterRatio * @attr ref R.styleable#KeyboardView_keyLargeLetterRatio
@ -81,7 +82,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
// XML attributes // XML attributes
protected final float mVerticalCorrection; protected final float mVerticalCorrection;
protected final int mMoreKeysLayout; protected final int mMoreKeysLayout;
private final float mBackgroundDimAmount; private final int mBackgroundDimAlpha;
// 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";
@ -110,12 +111,12 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
private boolean mNeedsToDimBackground; private boolean mNeedsToDimBackground;
/** Whether the keyboard bitmap buffer needs to be redrawn before it's blitted. **/ /** Whether the keyboard bitmap buffer needs to be redrawn before it's blitted. **/
private boolean mBufferNeedsUpdate; private boolean mBufferNeedsUpdate;
/** The dirty region in the keyboard bitmap */ /** True if all keys should be drawn */
private final Rect mDirtyRect = new Rect(); private boolean mInvalidateAllKeys;
/** The key to invalidate. */ /** The keys that should be drawn */
private Key mInvalidatedKey; private final HashSet<Key> mInvalidatedKeys = new HashSet<Key>();
/** The dirty region for single key drawing */ /** The region of invalidated keys */
private final Rect mInvalidatedKeyRect = new Rect(); private final Rect mInvalidatedKeysRect = new Rect();
/** The keyboard bitmap buffer for faster updates */ /** The keyboard bitmap buffer for faster updates */
private Bitmap mBuffer; private Bitmap mBuffer;
/** The canvas for the above mutable keyboard bitmap */ /** The canvas for the above mutable keyboard bitmap */
@ -335,7 +336,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
mVerticalCorrection = a.getDimensionPixelOffset( mVerticalCorrection = a.getDimensionPixelOffset(
R.styleable.KeyboardView_verticalCorrection, 0); R.styleable.KeyboardView_verticalCorrection, 0);
mMoreKeysLayout = a.getResourceId(R.styleable.KeyboardView_moreKeysLayout, 0); mMoreKeysLayout = a.getResourceId(R.styleable.KeyboardView_moreKeysLayout, 0);
mBackgroundDimAmount = a.getFloat(R.styleable.KeyboardView_backgroundDimAmount, 0.5f); mBackgroundDimAlpha = a.getInt(R.styleable.KeyboardView_backgroundDimAlpha, 0);
a.recycle(); a.recycle();
mDelayAfterPreview = mKeyPreviewDrawParams.mLingerTimeout; mDelayAfterPreview = mKeyPreviewDrawParams.mLingerTimeout;
@ -366,8 +367,6 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
mKeyboard = keyboard; mKeyboard = keyboard;
LatinImeLogger.onSetKeyboard(keyboard); LatinImeLogger.onSetKeyboard(keyboard);
requestLayout(); requestLayout();
mDirtyRect.set(0, 0, getWidth(), getHeight());
mBufferNeedsUpdate = true;
invalidateAllKeys(); invalidateAllKeys();
final int keyHeight = keyboard.mMostCommonKeyHeight - keyboard.mVerticalGap; final int keyHeight = keyboard.mMostCommonKeyHeight - keyboard.mVerticalGap;
mKeyDrawParams.updateKeyHeight(keyHeight); mKeyDrawParams.updateKeyHeight(keyHeight);
@ -434,47 +433,50 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
if (mBuffer != null) if (mBuffer != null)
mBuffer.recycle(); mBuffer.recycle();
mBuffer = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); mBuffer = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
mDirtyRect.union(0, 0, width, height); mInvalidateAllKeys = true;
if (mCanvas != null) { if (mCanvas != null) {
mCanvas.setBitmap(mBuffer); mCanvas.setBitmap(mBuffer);
} else { } else {
mCanvas = new Canvas(mBuffer); mCanvas = new Canvas(mBuffer);
} }
} }
final Canvas canvas = mCanvas;
canvas.clipRect(mDirtyRect, Op.REPLACE);
canvas.drawColor(Color.BLACK, PorterDuff.Mode.CLEAR);
if (mKeyboard == null) return; if (mKeyboard == null) return;
final Canvas canvas = mCanvas;
final Paint paint = mPaint;
final KeyDrawParams params = mKeyDrawParams; final KeyDrawParams params = mKeyDrawParams;
if (mInvalidatedKey != null && mInvalidatedKeyRect.contains(mDirtyRect)) {
// Draw a single key. if (mInvalidateAllKeys || mInvalidatedKeys.isEmpty()) {
final int keyDrawX = mInvalidatedKey.mX + mInvalidatedKey.mVisualInsetsLeft mInvalidatedKeysRect.set(0, 0, getWidth(), getHeight());
+ getPaddingLeft(); canvas.clipRect(mInvalidatedKeysRect, Op.REPLACE);
final int keyDrawY = mInvalidatedKey.mY + getPaddingTop(); canvas.drawColor(Color.BLACK, PorterDuff.Mode.CLEAR);
canvas.translate(keyDrawX, keyDrawY);
onDrawKey(mInvalidatedKey, canvas, mPaint, params);
canvas.translate(-keyDrawX, -keyDrawY);
} else {
// Draw all keys. // Draw all keys.
for (final Key key : mKeyboard.mKeys) { for (final Key key : mKeyboard.mKeys) {
final int keyDrawX = key.mX + key.mVisualInsetsLeft + getPaddingLeft(); onDrawKey(key, canvas, paint, params);
final int keyDrawY = key.mY + getPaddingTop(); }
canvas.translate(keyDrawX, keyDrawY); } else {
onDrawKey(key, canvas, mPaint, params); // Draw invalidated keys.
canvas.translate(-keyDrawX, -keyDrawY); for (final Key key : mInvalidatedKeys) {
final int x = key.mX + getPaddingLeft();
final int y = key.mY + getPaddingTop();
mInvalidatedKeysRect.set(x, y, x + key.mWidth, y + key.mHeight);
canvas.clipRect(mInvalidatedKeysRect, Op.REPLACE);
canvas.drawColor(Color.BLACK, PorterDuff.Mode.CLEAR);
onDrawKey(key, canvas, paint, params);
} }
} }
// Overlay a dark rectangle to dim the entire keyboard // Overlay a dark rectangle to dim the entire keyboard
if (mNeedsToDimBackground) { if (mNeedsToDimBackground) {
mPaint.setColor((int) (mBackgroundDimAmount * 0xFF) << 24); paint.setColor(Color.BLACK);
canvas.drawRect(0, 0, width, height, mPaint); paint.setAlpha(mBackgroundDimAlpha);
canvas.drawRect(0, 0, width, height, paint);
} }
mInvalidatedKey = null; mInvalidatedKeys.clear();
mDirtyRect.setEmpty(); mInvalidatedKeysRect.setEmpty();
mInvalidateAllKeys = false;
} }
public void dimEntireKeyboard(boolean dimmed) { public void dimEntireKeyboard(boolean dimmed) {
@ -486,10 +488,16 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
} }
private void onDrawKey(Key key, Canvas canvas, Paint paint, KeyDrawParams params) { private void onDrawKey(Key key, Canvas canvas, Paint paint, KeyDrawParams params) {
final int keyDrawX = key.mX + key.mVisualInsetsLeft + getPaddingLeft();
final int keyDrawY = key.mY + getPaddingTop();
canvas.translate(keyDrawX, keyDrawY);
if (!key.isSpacer()) { if (!key.isSpacer()) {
onDrawKeyBackground(key, canvas, params); onDrawKeyBackground(key, canvas, params);
} }
onDrawKeyTopVisuals(key, canvas, paint, params); onDrawKeyTopVisuals(key, canvas, paint, params);
canvas.translate(-keyDrawX, -keyDrawY);
} }
// Draw key background. // Draw key background.
@ -905,9 +913,9 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
* @see #invalidateKey(Key) * @see #invalidateKey(Key)
*/ */
public void invalidateAllKeys() { public void invalidateAllKeys() {
mDirtyRect.union(0, 0, getWidth(), getHeight()); mInvalidatedKeys.clear();
mInvalidateAllKeys = true;
mBufferNeedsUpdate = true; mBufferNeedsUpdate = true;
mInvalidatedKey = null;
invalidate(); invalidate();
} }
@ -920,22 +928,21 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
*/ */
@Override @Override
public void invalidateKey(Key key) { public void invalidateKey(Key key) {
if (key == null) if (mInvalidateAllKeys) return;
return; if (key == null) return;
mInvalidatedKey = key; mInvalidatedKeys.add(key);
final int x = key.mX + getPaddingLeft(); final int x = key.mX + getPaddingLeft();
final int y = key.mY + getPaddingTop(); final int y = key.mY + getPaddingTop();
mInvalidatedKeyRect.set(x, y, x + key.mWidth, y + key.mHeight); mInvalidatedKeysRect.union(x, y, x + key.mWidth, y + key.mHeight);
mDirtyRect.union(mInvalidatedKeyRect);
mBufferNeedsUpdate = true; mBufferNeedsUpdate = true;
invalidate(mInvalidatedKeyRect); invalidate(mInvalidatedKeysRect);
} }
public void closing() { public void closing() {
PointerTracker.dismissAllKeyPreviews(); PointerTracker.dismissAllKeyPreviews();
cancelAllMessages(); cancelAllMessages();
mDirtyRect.union(0, 0, getWidth(), getHeight()); mInvalidateAllKeys = true;
requestLayout(); requestLayout();
} }