Android Open Source - slidekeyboard Slide Keyboard View






From Project

Back to project page slidekeyboard.

License

The source code is released under:

MIT License

If you think the Android project slidekeyboard listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.asigbe.slidekeyboardpro;
// ww w.  j a v a 2  s . c o  m
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.content.Context;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.Region.Op;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.inputmethodservice.Keyboard;
import android.inputmethodservice.KeyboardView;
import android.os.Debug;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.Display;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
import android.widget.PopupWindow;
import android.widget.TextView;

import com.asigbe.slidekeyboardpro.AsigbeKeyboard.Key;
import com.asigbe.view.ViewTools;

/**
 * A view that renders a virtual {@link Keyboard}. It handles rendering of keys
 * and detecting key presses and touch movements.
 */
public class SlideKeyboardView extends View implements View.OnClickListener {

    /**
     * Listener for virtual keyboard events.
     */
    public interface OnKeyboardActionListener {

  /**
   * Called when the user presses a key. This is sent before the
   * {@link #onKey} is called. For keys that repeat, this is only called
   * once.
   * 
   * @param primaryCode
   *            the unicode of the key being pressed. If the touch is not
   *            on a valid key, the value will be zero.
   */
  void onPress(int primaryCode);

  /**
   * Called when the user releases a key. This is sent after the
   * {@link #onKey} is called. For keys that repeat, this is only called
   * once.
   * 
   * @param primaryCode
   *            the code of the key that was released
   */
  void onRelease(int primaryCode);

  /**
   * Send a key press to the listener.
   * 
   * @param primaryCode
   *            this is the key that was pressed
   */
  void onKeyDown(int primaryCode, int[] keyCodes, Object option);

  /**
   * Send a long key press to the listener.
   * 
   * @param primaryCode
   *            this is the key that was pressed
   */
  void onLongKeyDown(int primaryCode, int[] keyCodes, Object option);

  /**
   * Send a key press to the listener.
   * 
   * @param primaryCode
   *            this is the key that was pressed
   */
  void onKeyUp(int primaryCode, int[] keyCodes, Object option);

  /**
   * Sends a sequence of characters to the listener.
   * 
   * @param text
   *            the sequence of characters to be displayed.
   */
  void onText(CharSequence text);

  /**
   * Called when the user quickly moves the finger from right to left.
   */
  void swipeLeft();

  /**
   * Called when the user quickly moves the finger from left to right.
   */
  void swipeRight();

  /**
   * Called when the user quickly moves the finger from up to down.
   */
  void swipeDown();

  /**
   * Called when the user quickly moves the finger from down to up.
   */
  void swipeUp();
    }

    private final class CacheKey {

  public final int swipingDirection;
  public final Key key;

  public CacheKey(Key key, int swipingDirection) {
      this.key = key;
      this.swipingDirection = swipingDirection;
  }

  @Override
  public int hashCode() {
      final int prime = 31;
      int result = 1;
      result = prime * result + getOuterType().hashCode();
      result = prime * result
        + ((this.key == null) ? 0 : this.key.hashCode());
      result = prime * result + this.swipingDirection;
      return result;
  }

  @Override
  public boolean equals(Object obj) {
      if (this == obj) {
    return true;
      }
      if (obj == null) {
    return false;
      }
      if (getClass() != obj.getClass()) {
    return false;
      }
      CacheKey other = (CacheKey) obj;
      if (!getOuterType().equals(other.getOuterType())) {
    return false;
      }
      if (this.key == null) {
    if (other.key != null) {
        return false;
    }
      } else if (!this.key.equals(other.key)) {
    return false;
      }
      if (this.swipingDirection != other.swipingDirection) {
    return false;
      }
      return true;
  }

  private SlideKeyboardView getOuterType() {
      return SlideKeyboardView.this;
  }

    }

    static final int                 KEYCODE_OPTIONS          = -100;
    static final int                 KEYCODE_SHIFT_LONGPRESS  = -101;

    private static final int         FIGURE_NORMAL            = 0;
    private static final int         FIGURE_OCTOGONAL         = 1;

    private static final int         NO_LINE                  = 0;
    private static final int         LINE_NORMAL              = 1;
    private static final int         LINE_OBLIQUE             = 2;

    private static final int         NO_SWIPING               = 0;
    private static final int         SWIPING_TOP              = 1;
    private static final int         SWIPING_BOTTOM           = 2;
    private static final int         SWIPING_LEFT             = 3;
    private static final int         SWIPING_RIGHT            = 4;

    private static final int         NOT_A_KEY                = -1;
    private static final int[]       LONG_PRESSABLE_STATE_SET = { android.R.attr.state_long_pressable };

    private AsigbeKeyboard           keyboard;
    private int                      labelTextSize;
    private int                      keyTextSize;
    private int                      keyTextColor;
    private float                    shadowRadius;
    private int                      shadowColor;
    private int                      centerTextColor;
    private float                    backgroundDimAmount;

    private TextView                 previewText;
    private PopupWindow              previewPopup;
    private int                      previewTextSizeLarge;
    private int                      previewOffset;
    private int                      previewHeight;
    private int[]                    offsetInWindow;

    private PopupWindow              popupKeyboard;
    private View                     miniKeyboardContainer;
    private SlideKeyboardView        miniKeyboard;
    private boolean                  miniKeyboardOnScreen;
    private View                     popupParent;
    private int                      mMiniKeyboardOffsetX;
    private int                      mMiniKeyboardOffsetY;
    private Map<CacheKey, View>      miniKeyboardCache;
    private int[]                    mWindowOffset;
    private Key[]                    keys;

    /** Listener for {@link OnKeyboardActionListener}. */
    private OnKeyboardActionListener keyboardActionListener;

    private int                      sensitivity              = 15;
    private static final int         MSG_SHOW_PREVIEW         = 1;
    private static final int         MSG_REMOVE_PREVIEW       = 2;
    private static final int         MSG_REPEAT               = 3;
    private static final int         MSG_LONGPRESS            = 4;

    private static final int         DELAY_BEFORE_PREVIEW     = 70;
    private static final int         DELAY_AFTER_PREVIEW      = 60;

    private int                      verticalCorrection;
    private int                      mProximityThreshold;

    private final boolean            mPreviewCentered         = false;
    private boolean                  mShowPreview             = true;
    private int                      mPopupPreviewX;
    private int                      mPopupPreviewY;

    private boolean                  mProximityCorrectOn;

    private final Paint              paint;
    private Rect                     padding;

    private final int[]              mKeyIndices              = new int[12];
    private int                      popupX;
    private int                      popupY;
    private int                      popupLayout;
    private List<Key>                invalidatedKeys;
    private final Rect               clipRegion               = new Rect(0, 0,
                                                                0, 0);

    private Drawable                 keyBackground;
    private int                      repeatInterval;
    private static final int         REPEAT_START_DELAY       = 400;
    private static final Rect        INTERNAL_PADDING         = new Rect(5, 5,
                                                                5, 5);
    // Deemed to be too short : ViewConfiguration.getLongPressTimeout();

    private static int               MAX_NEARBY_KEYS          = 12;
    private final int[]              mDistances               = new int[MAX_NEARBY_KEYS];

    /** Whether the keyboard bitmap needs to be redrawn before it's blitted. **/
    private boolean                  mDrawPending;
    /** The dirty region in the keyboard bitmap */
    private final Rect               dirtyRect                = new Rect();
    /** The keyboard bitmap for faster updates */
    private Bitmap                   buffer;
    /** The canvas for the above mutable keyboard bitmap */
    private Canvas                   canvas;

    Handler                          handler                  = new Handler() {
                                                            @Override
                                                            public void handleMessage(
                                                                    Message msg) {
                                                          switch (msg.what) {
                                                          case MSG_SHOW_PREVIEW:
                                                              showKey((TouchInfo) msg.obj);
                                                              break;
                                                          case MSG_REMOVE_PREVIEW:
                                                              SlideKeyboardView.this.previewText
                                                                      .setVisibility(INVISIBLE);
                                                              break;
                                                          case MSG_REPEAT:
                                                              if (repeatKey((TouchInfo) msg.obj)) {
                                                            Message repeat = Message
                                                                    .obtain(this,
                                                                            MSG_REPEAT,
                                                                            msg.obj);
                                                            sendMessageDelayed(
                                                                    repeat,
                                                                    SlideKeyboardView.this.repeatInterval);
                                                              }
                                                              break;
                                                          case MSG_LONGPRESS:
                                                              openPopupIfRequired((TouchInfo) msg.obj);
                                                              break;
                                                          }
                                                            }
                                                        };

    private final int                displayWidth;
    private int                      textStyle;
    private int                      temporaryBackgroundColor;
    private int                      permanentBackgroundColor;
    private int                      figureStyle;
    private int                      lineStyle;
    private boolean                  displayKeyPreview;
    private final AttributeSet       attrs;
    private boolean                  mustLeaveSpaceWhenNoLetter;

    public SlideKeyboardView(Context context, AttributeSet attrs) {
  this(context, attrs, R.style.SlideKeyboardStyle);

    }

    public SlideKeyboardView(Context context, AttributeSet attrs, int defStyle) {
  super(context, attrs, defStyle);
  this.attrs = attrs;
  this.invalidatedKeys = new ArrayList<AsigbeKeyboard.Key>();

  WindowManager wm = (WindowManager) context
          .getSystemService(Context.WINDOW_SERVICE);
  final Display display = wm.getDefaultDisplay();
  this.displayWidth = display.getWidth();

  this.paint = new Paint();
  this.paint.setAntiAlias(true);
  this.paint.setTextSize(keyTextSize);
  this.paint.setTextAlign(Align.CENTER);

  this.padding = new Rect(0, 0, 0, 0);
  this.popupParent = this;
  this.touchInfos[0] = new TouchInfo();
  this.touchInfos[1] = new TouchInfo();
  applySkin(context, defStyle);
    }

    public void applySkin(Context context, int defStyle) {

  LayoutInflater inflate = (LayoutInflater) context
          .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
  TypedArray a = context.obtainStyledAttributes(this.attrs,
          R.styleable.SlideKeyboardView, 0, defStyle);

  int previewLayout = 0;
  int n = a.getIndexCount();
  for (int i = 0; i < n; i++) {
      int attr = a.getIndex(i);

      switch (attr) {
      case R.styleable.SlideKeyboardView_android_keyBackground:
    this.keyBackground = a.getDrawable(attr);
    break;
      case R.styleable.SlideKeyboardView_android_verticalCorrection:
    this.verticalCorrection = a.getDimensionPixelOffset(attr, 0);
    break;
      case R.styleable.SlideKeyboardView_android_keyPreviewLayout:
    previewLayout = a.getResourceId(attr, 0);
    break;
      case R.styleable.SlideKeyboardView_android_keyPreviewOffset:
    this.previewOffset = a.getDimensionPixelOffset(attr, 0);
    break;
      case R.styleable.SlideKeyboardView_android_keyPreviewHeight:
    this.previewHeight = a.getDimensionPixelSize(attr, 80);
    break;
      case R.styleable.SlideKeyboardView_android_keyTextSize:
    this.keyTextSize = a.getDimensionPixelSize(attr, 18);
    break;
      case R.styleable.SlideKeyboardView_android_keyTextColor:
    this.keyTextColor = a.getColor(attr, Color.WHITE);
    break;
      case R.styleable.SlideKeyboardView_android_labelTextSize:
    this.labelTextSize = a.getDimensionPixelSize(attr, 14);
    break;
      case R.styleable.SlideKeyboardView_android_popupLayout:
    this.popupLayout = a.getResourceId(attr, 0);
    break;
      case R.styleable.SlideKeyboardView_android_shadowColor:
    this.shadowColor = a.getColor(attr, 0);
    break;
      case R.styleable.SlideKeyboardView_android_shadowRadius:
    this.shadowRadius = a.getFloat(attr, 0f);
    break;
      case R.styleable.SlideKeyboardView_android_textStyle:
    this.textStyle = a.getInt(attr, Typeface.NORMAL);
    break;
      case R.styleable.SlideKeyboardView_centerTextColor:
    this.centerTextColor = a.getColor(attr, Color.WHITE);
    break;
      case R.styleable.SlideKeyboardView_temporaryBackgroundColor:
    this.temporaryBackgroundColor = a.getColor(attr, Color.BLUE);
    break;
      case R.styleable.SlideKeyboardView_permanentBackgroundColor:
    this.permanentBackgroundColor = a.getColor(attr, Color.BLACK);
    break;
      case R.styleable.SlideKeyboardView_figureStyle:
    this.figureStyle = a.getInt(attr, FIGURE_NORMAL);
    break;
      case R.styleable.SlideKeyboardView_lineStyle:
    this.lineStyle = a.getInt(attr, LINE_NORMAL);
      case R.styleable.SlideKeyboardView_leaveSpaceWhenNoLetter:
    this.mustLeaveSpaceWhenNoLetter = a.getBoolean(attr, true);
    break;
      }

      switch (this.textStyle) {
      case Typeface.NORMAL:
    this.textTypeFace = SlideKeyboard.textTypeFace;
    break;
      case Typeface.BOLD:
    this.textTypeFace = SlideKeyboard.boldTextTypeFace;
    break;
      case Typeface.ITALIC:
    this.textTypeFace = SlideKeyboard.italicTextTypeFace;
    break;
      default:
    this.textTypeFace = SlideKeyboard.textTypeFace;
    break;
      }
  }

  // No theme configured
  // a = getContext().obtainStyledAttributes(android.R.attr.theme);
  // mBackgroundDimAmount = a.getFloat(R.attr.Theme_backgroundDimAmount,
  // 0.5f);

  this.backgroundDimAmount = 0.5f;
  this.previewPopup = new PopupWindow(context);
  if (previewLayout != 0) {
      this.previewText = (TextView) inflate.inflate(previewLayout, null);
      this.previewText.setTypeface(this.textTypeFace);
      this.previewTextSizeLarge = (int) this.previewText.getTextSize();
      this.previewPopup.setContentView(this.previewText);
      this.previewPopup.setBackgroundDrawable(null);
  } else {
      this.mShowPreview = false;
  }

  this.previewPopup.setTouchable(false);

  this.popupKeyboard = new PopupWindow(context);
  this.popupKeyboard.setBackgroundDrawable(null);
  // mPopupKeyboard.setClippingEnabled(false);

  // mPredicting = true;
  this.miniKeyboardCache = new HashMap<CacheKey, View>();
  if (!this.keyBackground.getPadding(this.padding)) {
      this.padding = INTERNAL_PADDING;
  }
  resetSwiping();
    }

    public void setOnKeyboardActionListener(OnKeyboardActionListener listener) {
  this.keyboardActionListener = listener;
    }

    /**
     * Returns the {@link OnKeyboardActionListener} object.
     * 
     * @return the listener attached to this keyboard
     */
    protected OnKeyboardActionListener getOnKeyboardActionListener() {
  return this.keyboardActionListener;
    }

    /**
     * Attaches a keyboard to this view. The keyboard can be switched at any
     * time and the view will re-layout itself to accommodate the keyboard.
     * 
     * @see Keyboard
     * @see #getKeyboard()
     * @param keyboard
     *            the keyboard to display in this view
     */
    public void setKeyboard(AsigbeKeyboard keyboard) {
  if (this.keyboard != null) {
      cancelPreview();
  }
  this.keyboard = keyboard;
  List<Key> keys = this.keyboard.getKeys();
  this.keys = keys.toArray(new Key[keys.size()]);
  releaseAllKeys();
  requestLayout();
  // Release buffer, just in case the new keyboard has a different size.
  // It will be reallocated on the next draw.
  this.buffer = null;
  invalidateAll();
  computeProximityThreshold(keyboard);
  this.miniKeyboardCache.clear(); // Not really necessary to do every
  // time,
  // but will free up views
    }

    /**
     * Returns the current keyboard being displayed by this view.
     * 
     * @return the currently attached keyboard
     * @see #setKeyboard(Keyboard)
     */
    public AsigbeKeyboard getKeyboard() {
  return this.keyboard;
    }

    /**
     * Sets the state of the shift key of the keyboard, if any.
     * 
     * @param shifted
     *            whether or not to enable the state of the shift key
     * @return true if the shift key state changed, false if there was no change
     * @see KeyboardView#isShifted()
     */
    public boolean setShifted(boolean shifted, boolean locked) {
  if (this.keyboard != null) {
      if (this.keyboard.setShifted(shifted, locked)) {
    // The whole keyboard probably needs to be redrawn
    invalidateAll();
    return true;
      }
  }
  return false;
    }

    /**
     * Returns the state of the shift key of the keyboard, if any.
     * 
     * @return true if the shift is in a pressed state, false otherwise. If
     *         there is no shift key on the keyboard or there is no keyboard
     *         attached, it returns false.
     * @see KeyboardView#setShifted(boolean)
     */
    public boolean isShifted() {
  if (this.keyboard != null) {
      return this.keyboard.isShifted();
  }
  return false;
    }

    /**
     * Enables or disables the key feedback popup. This is a popup that shows a
     * magnified version of the depressed key. By default the preview is
     * enabled.
     * 
     * @param previewEnabled
     *            whether or not to enable the key feedback popup
     * @see #isPreviewEnabled()
     */
    public void setPreviewEnabled(boolean previewEnabled) {
  this.mShowPreview = previewEnabled;
    }

    /**
     * Returns the enabled state of the key feedback popup.
     * 
     * @return whether or not the key feedback popup is enabled
     * @see #setPreviewEnabled(boolean)
     */
    public boolean isPreviewEnabled() {
  return this.mShowPreview;
    }

    public void setPopupParent(View v) {
  this.popupParent = v;
    }

    public void setPopupOffset(int x, int y) {
  this.mMiniKeyboardOffsetX = x;
  this.mMiniKeyboardOffsetY = y;
  if (this.previewPopup.isShowing()) {
      this.previewPopup.dismiss();
  }
    }

    /**
     * When enabled, calls to {@link OnKeyboardActionListener#onKey} will
     * include key codes for adjacent keys. When disabled, only the primary key
     * code will be reported.
     * 
     * @param enabled
     *            whether or not the proximity correction is enabled
     */
    public void setProximityCorrectionEnabled(boolean enabled) {
  this.mProximityCorrectOn = enabled;
    }

    /**
     * Returns true if proximity correction is enabled.
     */
    public boolean isProximityCorrectionEnabled() {
  return this.mProximityCorrectOn;
    }

    /**
     * Popup keyboard close button clicked.
     * 
     * @hide
     */
    public void onClick(View v) {
  dismissPopupKeyboard();
    }

    private CharSequence adjustCase(CharSequence label) {
  if (this.keyboard.isShifted() && label != null && label.length() < 3
          && Character.isLowerCase(label.charAt(0))) {
      label = label.toString().toUpperCase();
  }
  return label;
    }

    @Override
    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  // Round up a little
  if (this.keyboard == null) {
      setMeasuredDimension(getPaddingLeft() + getPaddingRight(),
        getPaddingTop() + getPaddingBottom());
  } else {
      int width = this.keyboard.getFillScreenWidth() ? this.displayWidth
        : this.keyboard.getMinWidth() + getPaddingLeft()
                + getPaddingRight();
      if (MeasureSpec.getSize(widthMeasureSpec) < width + 10) {
    width = MeasureSpec.getSize(widthMeasureSpec);
      }
      setMeasuredDimension(width, this.keyboard.getHeight()
        + getPaddingTop() + getPaddingBottom());
  }
    }

    /**
     * Compute the average distance between adjacent keys (horizontally and
     * vertically) and square it to get the proximity threshold. We use a square
     * here and in computing the touch distance from a key's center to avoid
     * taking a square root.
     * 
     * @param keyboard
     */
    private void computeProximityThreshold(AsigbeKeyboard keyboard) {
  if (keyboard == null) {
      return;
  }
  final Key[] keys = this.keys;
  if (keys == null) {
      return;
  }
  int length = keys.length;
  int dimensionSum = 0;
  for (int i = 0; i < length; i++) {
      Key key = keys[i];
      dimensionSum += Math.min(key.width, key.height) + key.gap;
  }
  if ((dimensionSum < 0) || (length == 0)) {
      return;
  }
  this.mProximityThreshold = (int) (dimensionSum * 1.4f / length);
  this.mProximityThreshold *= this.mProximityThreshold; // Square it
    }

    @Override
    public void onSizeChanged(int w, int h, int oldw, int oldh) {
  super.onSizeChanged(w, h, oldw, oldh);
  // Release the buffer, if any and it will be reallocated on the next
  // draw
  this.buffer = null;
    }

    @Override
    public void onDraw(Canvas canvas) {
  super.onDraw(canvas);
  if (this.mDrawPending || (this.buffer == null)) {
      onBufferDraw();
  }
  canvas.drawBitmap(this.buffer, 0, 0, null);
    }

    private void onBufferDraw() {
  final Key[] keys = this.keys;
  if (this.buffer == null) {
      this.buffer = Bitmap.createBitmap(getWidth(), getHeight(),
        Bitmap.Config.ARGB_8888);
      this.canvas = new Canvas(this.buffer);
      this.octagonalPath = new Path();
      this.octagonalPath.moveTo(keys[0].width / 2, 0);
      this.octagonalPath.lineTo(getWidth() - keys[0].width / 2, 0);
      this.octagonalPath.lineTo(getWidth(), keys[0].height / 2);
      this.octagonalPath.lineTo(getWidth(), getHeight() - keys[0].height
        / 2);
      this.octagonalPath.lineTo(getWidth() - keys[0].width / 2,
        getHeight());
      this.octagonalPath.lineTo(keys[0].width / 2, getHeight());
      this.octagonalPath.lineTo(0, getHeight() - keys[0].height / 2);
      this.octagonalPath.lineTo(0, keys[0].height / 2);

      this.borderPath = new Path();
      this.borderPath.moveTo(keys[0].width / 2 + 1, 0);
      this.borderPath.lineTo(getWidth() - keys[0].width / 2 - 1, 0);
      this.borderPath.lineTo(getWidth(), keys[0].height / 2 + 1);
      this.borderPath.lineTo(getWidth(), getHeight() - keys[0].height / 2
        - 1);
      this.borderPath.lineTo(getWidth() - keys[0].width / 2 - 1,
        getHeight());
      this.borderPath.lineTo(keys[0].width / 2 + 1, getHeight());
      this.borderPath.lineTo(0, getHeight() - keys[0].height / 2 - 1);
      this.borderPath.lineTo(0, keys[0].height / 2 + 1);

      invalidateAll();
  }

  final Canvas canvas = this.canvas;
  canvas.clipRect(this.dirtyRect, Op.REPLACE);

  if (this.keyboard == null) {
      return;
  }

  int centerOffset = getWidth() - this.keyboard.getMinWidth();
  canvas.translate(centerOffset / 2, 0);
  if (this.figureStyle == FIGURE_OCTOGONAL) {
      canvas.clipPath(this.octagonalPath);
      canvas.drawPath(this.borderPath, paint);
  }

  final Paint paint = this.paint;
  final Rect clipRegion = this.clipRegion;
  final Rect padding = this.padding;
  final int kbdPaddingLeft = getPaddingLeft();
  final int kbdPaddingTop = getPaddingTop();

  paint.setAlpha(255);
  paint.setColor(this.keyTextColor);
  boolean drawSingleKey = false;
  for (Key invalidKey : this.invalidatedKeys) {
      if (canvas.getClipBounds(clipRegion)) {
    // Is clipRegion completely contained within the invalidated
    // key?
    if ((invalidKey.x + kbdPaddingLeft + centerOffset - 1 <= clipRegion.left)
            && (invalidKey.y + kbdPaddingTop - 1 <= clipRegion.top)
            && (invalidKey.x + invalidKey.width + kbdPaddingLeft
                    + centerOffset + 1 >= clipRegion.right)
            && (invalidKey.y + invalidKey.height + kbdPaddingTop
                    + 1 >= clipRegion.bottom)) {
        drawSingleKey = true;
    }
      }
  }
  final Drawable keyBackground = this.keyBackground;
  int keyTextSize = this.keyTextSize;
  int centerTextColor = this.centerTextColor;
  int keyTextColor = this.keyTextColor;

  canvas.drawColor(0x00000000, PorterDuff.Mode.CLEAR);
  final int keyCount = keys.length;
  for (int i = 0; i < keyCount; i++) {
      final Key key = keys[i];
      if (drawSingleKey) {
    boolean found = false;
    for (int j = 0; j < this.invalidatedKeys.size() && !found; j++) {
        found = (this.invalidatedKeys.get(j) == key);
    }
    if (!found) {
        continue;
    }
      }
      int[] drawableState = key.getCurrentDrawableState();
      keyBackground.setState(drawableState);

      final Rect bounds = keyBackground.getBounds();
      if ((key.width != bounds.right) || (key.height != bounds.bottom)) {
    keyBackground.setBounds(0, 0, key.width, key.height);
      }
      canvas.translate(key.x + kbdPaddingLeft, key.y + kbdPaddingTop);
      keyBackground.draw(canvas);

      // initializes the typeface
      paint.setTextSize(keyTextSize);

      int keyHeightWithoutPadding = key.height - padding.top
        - padding.bottom;
      if (!this.mustLeaveSpaceWhenNoLetter) {
    // we translate if we must not leave space for empty letters

    // right letter is missing
    if ((key.labelLeft != null || key.iconLeft != null)
            && (key.labelRight == null && key.iconRight == null)) {
        canvas.translate(
          (key.width - padding.left - padding.right) / 6, 0);
    }

    // left letter is missing
    if ((key.labelRight != null || key.iconRight != null)
            && (key.labelLeft == null && key.iconLeft == null)) {
        canvas.translate(
          -((key.width - padding.left - padding.right) / 6),
          0);
    }

    // bottom letter is missing
    if ((key.labelTop != null || key.iconTop != null)
            && (key.labelBottom == null && key.iconBottom == null)) {
        canvas.translate(
          0,
          keyHeightWithoutPadding / 6 + padding.top
                  + (paint.getTextSize() - paint.descent())
                  / 2);
    }

    // top letter is missing
    if ((key.labelBottom != null || key.iconBottom != null)
            && (key.labelTop == null && key.iconTop == null)) {
        canvas.translate(0, -(keyHeightWithoutPadding / 6
          + padding.top + (paint.getTextSize() - paint
          .descent()) / 2));
    }
      }

      float centerx = (key.width - padding.left - padding.right) / 2
        + padding.left;
      float centery = keyHeightWithoutPadding / 2
        + (paint.getTextSize() - paint.descent()) / 2 + padding.top
        - 1;

      // paint on center
      paint.setColor(centerTextColor);
      if (key.icon != null) {
    key.icon.setColorFilter(centerTextColor,
            PorterDuff.Mode.SRC_ATOP);
      }
      int iconWidth = key.icon != null ? key.icon.getIntrinsicWidth() : 0;
      int centerDrawableX = computeCenterDrawableX(padding, key, key.icon);
      int centerDrawableY = computeCenterDrawableY(padding, key, key.icon);
      paintLabel(key.label, key.icon, centerx, centery, centerDrawableX,
        centerDrawableY, key, canvas, paint);

      // paint on left
      paint.setColor(keyTextColor);
      iconWidth = key.iconLeft != null ? key.iconLeft.getIntrinsicWidth()
        : 0;
      centerDrawableX = computeCenterDrawableX(padding, key, key.iconLeft);
      centerDrawableY = computeCenterDrawableY(padding, key, key.iconLeft);
      paintLabel(key.labelLeft, key.iconLeft,
        (key.width - padding.left - padding.right) / 6
                + padding.left, centery,
        (key.width - padding.left - padding.right) / 6 - iconWidth
                / 2, centerDrawableY, key, canvas, paint);

      // paint on right
      iconWidth = key.iconRight != null ? key.iconRight
        .getIntrinsicWidth() : 0;
      centerDrawableX = computeCenterDrawableX(padding, key,
        key.iconRight);
      centerDrawableY = computeCenterDrawableY(padding, key,
        key.iconRight);
      paintLabel(key.labelRight, key.iconRight, 5
        * (key.width - padding.left - padding.right) / 6
        + padding.left, centery, 5
        * (key.width - padding.left - padding.right) / 6
        + padding.left - iconWidth / 2, centerDrawableY, key,
        canvas, paint);

      // paint on top
      int iconHeight = key.iconTop != null ? key.iconTop
        .getIntrinsicHeight() : 0;
      centerDrawableX = computeCenterDrawableX(padding, key, key.iconTop);
      centerDrawableY = computeCenterDrawableY(padding, key, key.iconTop);
      paintLabel(
        key.labelTop,
        key.iconTop,
        centerx,
        keyHeightWithoutPadding / 6 + padding.top
                + (paint.getTextSize() - paint.descent()) / 2 - 2,
        centerDrawableX, keyHeightWithoutPadding / 6 + padding.top
                - iconHeight / 2, key, canvas, paint);

      // paint on bottom
      iconHeight = key.iconBottom != null ? key.iconBottom
        .getIntrinsicHeight() : 0;
      centerDrawableX = computeCenterDrawableX(padding, key,
        key.iconBottom);
      centerDrawableY = computeCenterDrawableY(padding, key,
        key.iconBottom);
      paintLabel(
        key.labelBottom,
        key.iconBottom,
        centerx,
        5 * keyHeightWithoutPadding / 6 + padding.top
                + (paint.getTextSize() - paint.descent()) / 2,
        centerDrawableX, 5 * keyHeightWithoutPadding / 6
                + padding.top - iconHeight / 2 + 2, key, canvas,
        paint);

      if (!this.mustLeaveSpaceWhenNoLetter) {
    // we cancel the translatation if we must not leave space for
    // empty letters
    if ((key.labelLeft != null || key.iconLeft != null)
            && (key.labelRight == null && key.iconRight == null)) {
        canvas.translate(
          -((key.width - padding.left - padding.right) / 6),
          0);
    }

    if ((key.labelRight != null || key.iconRight != null)
            && (key.labelLeft == null && key.iconLeft == null)) {
        canvas.translate(
          (key.width - padding.left - padding.right) / 6, 0);
    }

    if ((key.labelTop != null || key.iconTop != null)
            && (key.labelBottom == null && key.iconBottom == null)) {
        canvas.translate(0, -(keyHeightWithoutPadding / 6
          + padding.top + (paint.getTextSize() - paint
          .descent()) / 2));
    }

    if ((key.labelBottom != null || key.iconBottom != null)
            && (key.labelTop == null && key.iconTop == null)) {
        canvas.translate(
          0,
          keyHeightWithoutPadding / 6 + padding.top
                  + (paint.getTextSize() - paint.descent())
                  / 2);
    }
      }

      if (this.lineStyle == LINE_NORMAL) {
    // draw vertical lines
    float offset = padding.left
            + (key.width - padding.left - padding.right) / 3;
    canvas.drawLine(offset, padding.top, offset, key.height
            - padding.bottom, paint);
    offset += (key.width - padding.left - padding.right) / 3;
    canvas.drawLine(offset, padding.top, offset, key.height
            - padding.bottom, paint);

    // draw horizontal lines
    offset = padding.top + keyHeightWithoutPadding / 3;
    canvas.drawLine(padding.left, offset,
            key.width - padding.right, offset, paint);
    offset += keyHeightWithoutPadding / 3;
    canvas.drawLine(padding.left, offset,
            key.width - padding.right, offset, paint);
      } else if (this.lineStyle == LINE_OBLIQUE) {
    paint.setAlpha(123);
    int leftOffset = (key.width - padding.left - padding.right - this.keyTextSize) / 2;
    int rightOffset = key.width - leftOffset;
    int topOffset = (key.height - padding.top - padding.bottom - this.keyTextSize) / 2;
    int bottomOffset = key.height - topOffset;
    if ((key.edgeFlags & Keyboard.EDGE_LEFT) != Keyboard.EDGE_LEFT) {
        if ((key.edgeFlags & Keyboard.EDGE_TOP) != Keyboard.EDGE_TOP) {
      canvas.drawLine(0, 0, leftOffset, topOffset, paint);
        }
        if ((key.edgeFlags & Keyboard.EDGE_BOTTOM) != Keyboard.EDGE_BOTTOM) {
      canvas.drawLine(0, key.height, leftOffset,
              bottomOffset, paint);
        }
        // if ((key.edgeFlags & Keyboard.EDGE_TOP) !=
        // Keyboard.EDGE_TOP)
        // {
        // canvas.drawLine(key.width, 0, rightOffset,
        // bottomOffset,
        // paint);
        // }
    }

    if ((key.edgeFlags & Keyboard.EDGE_RIGHT) != Keyboard.EDGE_RIGHT) {
        if ((key.edgeFlags & Keyboard.EDGE_TOP) != Keyboard.EDGE_TOP) {
      canvas.drawLine(key.width, 0, rightOffset, topOffset,
              paint);
        }
        if ((key.edgeFlags & Keyboard.EDGE_BOTTOM) != Keyboard.EDGE_BOTTOM) {
      canvas.drawLine(key.width, key.height, rightOffset,
              bottomOffset, paint);
        }

        // if ((key.edgeFlags & Keyboard.EDGE_TOP) !=
        // Keyboard.EDGE_TOP)
        // {
        // canvas.drawLine(key.width, 0, rightOffset,
        // bottomOffset,
        // paint);
        // }
    }

    if (((key.edgeFlags & Keyboard.EDGE_RIGHT) != Keyboard.EDGE_RIGHT)
            && ((key.edgeFlags & Keyboard.EDGE_LEFT) != Keyboard.EDGE_LEFT)) {
        if ((key.edgeFlags & Keyboard.EDGE_TOP) == Keyboard.EDGE_TOP) {
      canvas.drawLine(key.width / 2, 0, key.width / 2,
              topOffset, paint);
        } else if ((key.edgeFlags & Keyboard.EDGE_BOTTOM) == Keyboard.EDGE_BOTTOM) {
      canvas.drawLine(key.width / 2, key.height,
              key.width / 2, bottomOffset, paint);
        }
    } else if ((key.edgeFlags & Keyboard.EDGE_LEFT) == Keyboard.EDGE_LEFT) {
        if (((key.edgeFlags & Keyboard.EDGE_TOP) != Keyboard.EDGE_TOP)
          && ((key.edgeFlags & Keyboard.EDGE_BOTTOM) != Keyboard.EDGE_BOTTOM)) {
      canvas.drawLine(0, key.height / 2, leftOffset,
              key.height / 2, paint);
        } else if ((key.edgeFlags & Keyboard.EDGE_TOP) == Keyboard.EDGE_TOP) {
      canvas.drawLine(0, 0, leftOffset, topOffset, paint);
        } else if ((key.edgeFlags & Keyboard.EDGE_BOTTOM) == Keyboard.EDGE_BOTTOM) {
      canvas.drawLine(0, key.height, leftOffset,
              bottomOffset, paint);
        }
    } else if ((key.edgeFlags & Keyboard.EDGE_RIGHT) == Keyboard.EDGE_RIGHT) {
        if (((key.edgeFlags & Keyboard.EDGE_TOP) != Keyboard.EDGE_TOP)
          && ((key.edgeFlags & Keyboard.EDGE_BOTTOM) != Keyboard.EDGE_BOTTOM)) {
      canvas.drawLine(key.width, key.height / 2, rightOffset,
              key.height / 2, paint);
        } else if ((key.edgeFlags & Keyboard.EDGE_TOP) == Keyboard.EDGE_TOP) {
      canvas.drawLine(key.width, 0, rightOffset, topOffset,
              paint);
        } else if ((key.edgeFlags & Keyboard.EDGE_BOTTOM) == Keyboard.EDGE_BOTTOM) {
      canvas.drawLine(key.width, key.height, rightOffset,
              bottomOffset, paint);
        }
    }

    paint.setAlpha(255);
      }

      canvas.translate(-key.x - kbdPaddingLeft, -key.y - kbdPaddingTop);

  }
  this.invalidatedKeys.clear();
  // Overlay a dark rectangle to dim the keyboard
  if (this.miniKeyboardOnScreen) {
      paint.setColor((int) (this.backgroundDimAmount * 0xFF) << 24);
      canvas.drawRect(0, 0, getWidth(), getHeight(), paint);
  }

  this.mDrawPending = false;
  this.dirtyRect.setEmpty();
  canvas.translate(-centerOffset / 2, 0);
    }

    private int computeCenterDrawableY(final Rect padding, final Key key,
      Drawable icon) {
  if (icon == null) {
      return 0;
  }
  return (key.height - padding.top - padding.bottom - icon
          .getIntrinsicHeight()) / 2 + padding.top;
    }

    private int computeCenterDrawableX(final Rect padding, final Key key,
      Drawable icon) {
  if (icon == null) {
      return 0;
  }
  return (key.width - padding.left - padding.right - icon
          .getIntrinsicWidth()) / 2 + padding.left;
    }

    private final Rect rect = new Rect();
    private int        longPressTimeOut;
    private boolean    isTemporarySwitch;
    private Typeface   textTypeFace;
    private Path       octagonalPath;
    private Path       borderPath;

    private void paintLabel(CharSequence labelToPaint, Drawable icon, float x,
      float y, int drawableX, int drawableY, Key key, Canvas canvas,
      Paint paint) {

  // Switch the character to uppercase if shift is pressed
  String label = labelToPaint == null ? null : adjustCase(labelToPaint)
          .toString();
  if (label != null) {
      // For characters, use large font. For labels like "Done", use
      // small font.
      if ((label.length() > 1)
        && ((key.codes != null) && (key.codes.length < 2))) {
    paint.setTextSize(this.labelTextSize);
    paint.getTextBounds(label, 0, label.length(), this.rect);

    // if (this.rect.right - this.rect.left < 20) {
    // paint.setTextSize(this.labelTextSize + 4);
    // }
      } else {
    paint.setTextSize(this.keyTextSize);
      }
      paint.setTypeface(this.textTypeFace);
      // Draw a drop shadow for the text
      paint.setShadowLayer(this.shadowRadius, 0, 0, this.shadowColor);
      canvas.drawText(label, x, y, paint);
      // Turn off drop shadow
      paint.setShadowLayer(0, 0, 0, 0);
  } else if (icon != null) {
      canvas.translate(drawableX, drawableY);
      icon.setBounds(5, 5, icon.getIntrinsicWidth() - 5,
        icon.getIntrinsicHeight() - 5);
      icon.draw(canvas);
      canvas.translate(-drawableX, -drawableY);
  }
    }

    private int getKeyIndices(int x, int y, int[] allKeys) {
  final Key[] keys = this.keys;
  int primaryIndex = NOT_A_KEY;
  int closestKey = NOT_A_KEY;
  int closestKeyDist = this.mProximityThreshold + 1;
  java.util.Arrays.fill(this.mDistances, Integer.MAX_VALUE);
  int[] nearestKeyIndices = this.keyboard.getNearestKeys(x, y);
  final int keyCount = nearestKeyIndices.length;
  for (int i = 0; i < keyCount; i++) {
      final Key key = keys[nearestKeyIndices[i]];
      int dist = 0;
      boolean isInside = key.isInside(x, y);
      if (((this.mProximityCorrectOn && ((dist = key.squaredDistanceFrom(
        x, y)) < this.mProximityThreshold)) || isInside)
        && ((key.codes != null) && (key.codes[0] > 32))) {
    // Find insertion point
    final int nCodes = key.codes.length;
    if (dist < closestKeyDist) {
        closestKeyDist = dist;
        closestKey = nearestKeyIndices[i];
    }

    if (allKeys == null) {
        continue;
    }

    for (int j = 0; j < this.mDistances.length; j++) {
        if (this.mDistances[j] > dist) {
      // Make space for nCodes codes
      System.arraycopy(this.mDistances, j, this.mDistances, j
              + nCodes, this.mDistances.length - j - nCodes);
      System.arraycopy(allKeys, j, allKeys, j + nCodes,
              allKeys.length - j - nCodes);
      for (int c = 0; c < nCodes; c++) {
          allKeys[j + c] = key.codes[c];
          this.mDistances[j + c] = dist;
      }
      break;
        }
    }
      }

      if (isInside) {
    primaryIndex = nearestKeyIndices[i];
      }
  }
  if (primaryIndex == NOT_A_KEY) {
      primaryIndex = closestKey;
  }
  return primaryIndex;
    }

    /**
     * Detects the key by using the current slide status.
     */
    private void detectAndSendKey(TouchInfo touchInfo, boolean isDown) {
  if (touchInfo.currentKeyIndex >= 0
          && touchInfo.currentKeyIndex < this.keys.length) {
      final Key key = this.keys[touchInfo.currentKeyIndex];
      CharSequence text = null;
      Object option = null;
      switch (touchInfo.currentSwiping) {
      case NO_SWIPING:
    text = key.text;
    option = key.keyboard;
    break;
      case SWIPING_TOP:
    text = key.textTop;
    option = key.keyboardTop;
    break;
      case SWIPING_BOTTOM:
    text = key.textBottom;
    option = key.keyboardBottom;
    break;
      case SWIPING_LEFT:
    text = key.textLeft;
    option = key.keyboardLeft;
    break;
      case SWIPING_RIGHT:
    text = key.textRight;
    option = key.keyboardRight;
    break;
      }

      if (text == null) {
    text = key.defaultText;
      }
      if (text != null) {
    // if the key has a text we write it
    this.keyboardActionListener.onText(text);
    this.keyboardActionListener.onRelease(NOT_A_KEY);
      } else {
    // stores codes of each direction for alternatives
    ArrayList<Integer> codes = new ArrayList<Integer>(5);
    codes.add(key.codes != null ? key.codes[0] : 0);
    codes.add(key.codesTop != null ? key.codesTop[0] : 0);
    codes.add(key.codesBottom != null ? key.codesBottom[0] : 0);
    codes.add(key.codesLeft != null ? key.codesLeft[0] : 0);
    codes.add(key.codesRight != null ? key.codesRight[0] : 0);
    int swippedCode[];
    switch (touchInfo.currentSwiping) {
    case NO_SWIPING:
        swippedCode = key.codes;
        option = key.keyboard;
        break;
    case SWIPING_TOP:
        swippedCode = key.codesTop;
        option = key.keyboardTop;
        break;
    case SWIPING_BOTTOM:
        swippedCode = key.codesBottom;
        option = key.keyboardBottom;
        break;
    case SWIPING_LEFT:
        swippedCode = key.codesLeft;
        option = key.keyboardLeft;
        break;
    case SWIPING_RIGHT:
        swippedCode = key.codesRight;
        option = key.keyboardRight;
        break;
    default:
        swippedCode = key.codes;
        option = key.keyboard;
        break;
    }
    if (swippedCode == null) {
        if (key.defaultCodes == null) {
      return;
        }
        swippedCode = key.defaultCodes;
    }

    Integer code = swippedCode[0];
    if (code != Integer.MAX_VALUE) {
        codes.remove(code);
        int[] alternatesCodes = new int[4];
        for (int i = 0; i < alternatesCodes.length; i++) {
      alternatesCodes[i] = codes.get(i);
        }
        if (isDown) {
      this.keyboardActionListener.onKeyDown(code,
              alternatesCodes, option);
        } else {
      this.keyboardActionListener.onKeyUp(code,
              alternatesCodes, option);
      this.keyboardActionListener.onRelease(code);
        }
    }
      }
  }
    }

    /**
     * Handle slide keys by producing the key label for the current slide state.
     */
    private CharSequence getPreviewText(TouchInfo touchInfo, Key key) {
  CharSequence chaine;
  switch (touchInfo.currentSwiping) {
  case NO_SWIPING:
      chaine = key.label;
      break;
  case SWIPING_BOTTOM:
      chaine = key.labelBottom;
      break;
  case SWIPING_TOP:
      chaine = key.labelTop;
      break;
  case SWIPING_LEFT:
      chaine = key.labelLeft;
      break;
  case SWIPING_RIGHT:
      chaine = key.labelRight;
      break;
  default:
      chaine = key.label;
      break;
  }
  if (chaine == null) {
      chaine = key.label;
  }
  return adjustCase(chaine);
    }

    private void cancelPreview() {
  if (this.displayKeyPreview) {
      this.handler.removeMessages(MSG_SHOW_PREVIEW);
      if (previewPopup.isShowing()) {
    this.handler.sendMessageDelayed(
            this.handler.obtainMessage(MSG_REMOVE_PREVIEW),
            DELAY_AFTER_PREVIEW);
      }
  }
    }

    private void showPreview(TouchInfo touchInfo) {

  final PopupWindow previewPopup = this.previewPopup;

  if (this.displayKeyPreview) {
      // If key changed and preview is on ...
      if (this.mShowPreview) {
    if (touchInfo.currentKeyIndex != NOT_A_KEY) {
        if (previewPopup.isShowing()
          && (this.previewText.getVisibility() == VISIBLE)) {
      // Show right away, if it's already visible and finger
      // is moving around
      showKey(touchInfo);
        } else {
      Message obtainMessage = this.handler.obtainMessage(
              MSG_SHOW_PREVIEW, touchInfo);
      this.handler.sendMessageDelayed(obtainMessage,
              DELAY_BEFORE_PREVIEW);
        }
    }
      }
  }
    }

    private void showKey(TouchInfo touchInfo) {
  final PopupWindow previewPopup = this.previewPopup;
  final Key[] keys = this.keys;
  Key key = keys[touchInfo.currentKeyIndex];
  Drawable iconPreview = null;
  switch (touchInfo.currentSwiping) {
  case NO_SWIPING:
      iconPreview = key.iconPreview;
      break;
  case SWIPING_TOP:
      iconPreview = key.iconPreviewTop;
      break;
  case SWIPING_BOTTOM:
      iconPreview = key.iconPreviewBottom;
      break;
  case SWIPING_LEFT:
      iconPreview = key.iconPreviewLeft;
      break;
  case SWIPING_RIGHT:
      iconPreview = key.iconPreviewRight;
      break;
  }
  if (iconPreview != null) {
      this.previewText
        .setCompoundDrawables(null, null, null, iconPreview);
      this.previewText.setText(null);
  } else {
      this.previewText.setCompoundDrawables(null, null, null, null);
      this.previewText.setText(getPreviewText(touchInfo, key));
      if (((key.label != null) && (key.label.length() > 1))
        && (key.codes.length < 2)) {
    this.previewText.setTextSize(this.keyTextSize);
    this.previewText.setTypeface(Typeface.DEFAULT_BOLD);
      } else {
    this.previewText.setTextSize(this.previewTextSizeLarge);
    this.previewText.setTypeface(Typeface.DEFAULT);
      }
  }
  this.previewText.measure(
          MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
          MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
  int popupWidth = Math.max(this.previewText.getMeasuredWidth(),
          key.width + this.previewText.getPaddingLeft()
                  + this.previewText.getPaddingRight());
  final int popupHeight = this.previewHeight;
  LayoutParams lp = this.previewText.getLayoutParams();
  if (lp != null) {
      lp.width = popupWidth;
      lp.height = popupHeight;
  }
  if (!this.mPreviewCentered) {
      this.mPopupPreviewX = key.x - this.previewText.getPaddingLeft()
        + getPaddingLeft();
      this.mPopupPreviewY = key.y - popupHeight + this.previewOffset;
  } else {
      this.mPopupPreviewX = 160 - this.previewText.getMeasuredWidth() / 2;
      this.mPopupPreviewY = -this.previewText.getMeasuredHeight();
  }
  this.handler.removeMessages(MSG_REMOVE_PREVIEW);
  if (this.offsetInWindow == null) {
      this.offsetInWindow = new int[2];
      getLocationInWindow(this.offsetInWindow);
      this.offsetInWindow[0] += this.mMiniKeyboardOffsetX; // Offset may
      // be zero
      this.offsetInWindow[1] += this.mMiniKeyboardOffsetY; // Offset may
      // be zero
  }
  // Set the preview background state
  Drawable background = this.previewText.getBackground();
  if (background != null) {
      int popupResId = 0;
      switch (touchInfo.currentSwiping) {
      case NO_SWIPING:
    popupResId = key.popupResId;
    break;
      case SWIPING_TOP:
    popupResId = key.popupResIdTop;
    break;
      case SWIPING_BOTTOM:
    popupResId = key.popupResIdBottom;
    break;
      case SWIPING_LEFT:
    popupResId = key.popupResIdLeft;
    break;
      case SWIPING_RIGHT:
    popupResId = key.popupResIdRight;
    break;
      }
      background.setState(popupResId != 0 ? LONG_PRESSABLE_STATE_SET
        : EMPTY_STATE_SET);
  }
  if (previewPopup.isShowing()) {
      previewPopup.update(this.mPopupPreviewX + this.offsetInWindow[0],
        this.mPopupPreviewY + this.offsetInWindow[1], popupWidth,
        popupHeight);
  } else {
      previewPopup.setWidth(popupWidth);
      previewPopup.setHeight(popupHeight);
      previewPopup.showAtLocation(this.popupParent, Gravity.NO_GRAVITY,
        this.mPopupPreviewX + this.offsetInWindow[0],
        this.mPopupPreviewY + this.offsetInWindow[1]);
  }
  this.previewText.setVisibility(VISIBLE);
    }

    private void invalidateAll() {
  this.dirtyRect.union(0, 0, getWidth(), getHeight());
  this.mDrawPending = true;
  invalidate();
    }

    private void invalidateKey(int keyIndex) {
  if ((keyIndex < 0) || (keyIndex >= this.keys.length)) {
      return;
  }
  final Key key = this.keys[keyIndex];
  this.invalidatedKeys.add(key);
  int centerOffset = (getWidth() - this.keyboard.getMinWidth()) / 2;
  this.dirtyRect.union(key.x + getPaddingLeft() + centerOffset, key.y
          + getPaddingTop(), key.x + key.width + getPaddingLeft()
          + centerOffset, key.y + key.height + getPaddingTop());
  onBufferDraw();
  invalidate(key.x + getPaddingLeft() + centerOffset, key.y
          + getPaddingTop(), key.x + key.width + getPaddingLeft()
          + centerOffset, key.y + key.height + getPaddingTop());
    }

    private boolean openPopupIfRequired(TouchInfo touchInfo) {
  // Check if we have a popup layout specified first.
  if (this.popupLayout == 0) {
      return false;
  }
  // Check if the key really exist
  if ((touchInfo.currentKeyIndex < 0)
          || (touchInfo.currentKeyIndex >= this.keys.length)) {
      return false;
  }

  // Retrieve the key
  Key popupKey = this.keys[touchInfo.currentKeyIndex];
  boolean result = onLongPress(touchInfo, popupKey);
  if (result) {
      cancelPreview();
  }
  return result;
    }

    /**
     * Called when a key is long pressed. By default this will open any popup
     * keyboard associated with this key through the attributes popupLayout and
     * popupCharacters.
     * 
     * @param popupKey
     *            the key that was long pressed
     * @return true if the long press is handled, false otherwise. Subclasses
     *         should call the method on the base class if the subclass doesn't
     *         wish to handle the call.
     */
    protected boolean onLongPress(TouchInfo touchInfo, Key popupKey) {
  int popupKeyboardId = 0;
  int codes[] = popupKey.codes;
  Object option = null;

  switch (touchInfo.currentSwiping) {
  case NO_SWIPING:
      popupKeyboardId = popupKey.popupResId;
      codes = popupKey.codes;
      option = popupKey.keyboard;
      break;
  case SWIPING_LEFT:
      popupKeyboardId = popupKey.popupResIdLeft;
      codes = popupKey.codesLeft;
      option = popupKey.keyboardLeft;
      break;
  case SWIPING_RIGHT:
      popupKeyboardId = popupKey.popupResIdRight;
      codes = popupKey.codesRight;
      option = popupKey.keyboardRight;
      break;
  case SWIPING_BOTTOM:
      popupKeyboardId = popupKey.popupResIdBottom;
      codes = popupKey.codesBottom;
      option = popupKey.keyboardBottom;
      break;
  case SWIPING_TOP:
      popupKeyboardId = popupKey.popupResIdTop;
      codes = popupKey.codesTop;
      option = popupKey.keyboardTop;
      break;
  }

  // there is no key on the swiping direction
  if (codes == null) {
      return false;
  }

  CacheKey cacheKey = new CacheKey(popupKey, popupKeyboardId);

  if (popupKeyboardId != 0) {
      this.miniKeyboardContainer = this.miniKeyboardCache.get(popupKey);
      if (this.miniKeyboardContainer == null) {
    this.miniKeyboardContainer = ViewTools.inflateView(
            getContext(), this.popupLayout);

    this.miniKeyboard = (SlideKeyboardView) this.miniKeyboardContainer
            .findViewById(R.id.popupKeyboardView);
    View closeButton = this.miniKeyboardContainer
            .findViewById(R.id.closeButton);
    if (closeButton != null) {
        closeButton.setOnClickListener(this);
    }
    this.miniKeyboard
            .setOnKeyboardActionListener(new OnKeyboardActionListener() {
          public void onKeyUp(int primaryCode,
                  int[] keyCodes, Object option) {
              SlideKeyboardView.this.keyboardActionListener
                      .onKeyUp(primaryCode, keyCodes, option);
              dismissPopupKeyboard();
          }

          public void onText(CharSequence text) {
              SlideKeyboardView.this.keyboardActionListener
                      .onText(text);
              dismissPopupKeyboard();
          }

          @Override
          public void swipeLeft() {
          }

          @Override
          public void swipeRight() {
          }

          @Override
          public void swipeUp() {
          }

          @Override
          public void swipeDown() {
          }

          @Override
          public void onPress(int primaryCode) {
              SlideKeyboardView.this.keyboardActionListener
                      .onPress(primaryCode);
          }

          @Override
          public void onRelease(int primaryCode) {
              SlideKeyboardView.this.keyboardActionListener
                      .onRelease(primaryCode);
          }

          @Override
          public void onKeyDown(int primaryCode,
                  int[] keyCodes, Object option) {
              SlideKeyboardView.this.keyboardActionListener
                      .onKeyDown(primaryCode, keyCodes,
                              option);

          }

          @Override
          public void onLongKeyDown(int primaryCode,
                  int[] keyCodes, Object option) {
              SlideKeyboardView.this.keyboardActionListener
                      .onLongKeyDown(primaryCode, keyCodes,
                              option);

          }
            });
    // mInputView.setSuggest(mSuggest);
    AsigbeKeyboard keyboard = new AsigbeKeyboard(getContext(),
            popupKeyboardId);
    this.miniKeyboard.setKeyboard(keyboard);
    this.miniKeyboard.setPopupParent(this);
    this.miniKeyboardContainer.measure(MeasureSpec.makeMeasureSpec(
            getWidth(), MeasureSpec.AT_MOST), MeasureSpec
            .makeMeasureSpec(getHeight(), MeasureSpec.AT_MOST));

    this.miniKeyboardCache
            .put(cacheKey, this.miniKeyboardContainer);
      } else {
    this.miniKeyboard = (SlideKeyboardView) this.miniKeyboardContainer
            .findViewById(R.id.popupKeyboardView);
      }
      if (this.mWindowOffset == null) {
    this.mWindowOffset = new int[2];
    getLocationInWindow(this.mWindowOffset);
      }
      this.popupX = popupKey.x + getPaddingLeft();
      this.popupY = popupKey.y + getPaddingTop();
      this.popupX = this.popupX + popupKey.width
        - this.miniKeyboardContainer.getMeasuredWidth();
      this.popupY = this.popupY
        - this.miniKeyboardContainer.getMeasuredHeight();
      final int x = this.popupX
        + this.miniKeyboardContainer.getPaddingRight()
        + this.mWindowOffset[0];
      final int y = this.popupY
        + this.miniKeyboardContainer.getPaddingBottom()
        + this.mWindowOffset[1];
      this.miniKeyboard.setPopupOffset(x < 0 ? 0 : x, y);
      this.miniKeyboard.setShifted(isShifted(), false);
      this.popupKeyboard.setContentView(this.miniKeyboardContainer);
      this.popupKeyboard.setWidth(this.miniKeyboardContainer
        .getMeasuredWidth());
      this.popupKeyboard.setHeight(this.miniKeyboardContainer
        .getMeasuredHeight());
      this.popupKeyboard.showAtLocation(this, Gravity.NO_GRAVITY, x, y);
      this.miniKeyboardOnScreen = true;
      // mMiniKeyboard.onTouchEvent(getTranslatedEvent(me));
      invalidateAll();
      return true;
  } else {
      Integer code = codes[0];
      if (code != Integer.MAX_VALUE) {
    SlideKeyboardView.this.keyboardActionListener.onLongKeyDown(
            code, null, option);
      }
  }
  return false;
    }

    private static class TouchInfo {
  private int     lastCodeX;
  private int     lastCodeY;
  private int     lastMoveX;
  private int     lastMoveY;
  private long    downTime;
  private long    lastMoveTime;
  private int     lastKey;
  private int     currentKeyIndex = NOT_A_KEY;
  private long    lastKeyTime;
  private long    currentKeyTime;
  private int     repeatKeyIndex  = NOT_A_KEY;
  private int     repeatSwiping;
  private boolean isRepeating;
  public Object   previousSwiping;
  public int      currentSwiping;

    }

    private final TouchInfo touchInfos[] = new TouchInfo[2];
    private int             pointerId1;
    private int             pointerId2;

    private boolean handleKeyDown(TouchInfo touchInfo, int touchX, int touchY,
      int keyIndex, long eventTime) {
  // Debug.waitForDebugger();
  touchInfo.lastCodeX = touchX;
  touchInfo.lastCodeY = touchY;
  touchInfo.lastMoveX = touchX;
  touchInfo.lastMoveY = touchY;
  touchInfo.lastKeyTime = 0;
  touchInfo.currentKeyTime = 0;
  touchInfo.lastKey = NOT_A_KEY;
  touchInfo.currentKeyIndex = keyIndex;
  touchInfo.downTime = eventTime;
  touchInfo.lastMoveTime = touchInfo.downTime;
  this.keyboardActionListener
          .onPress(((touchInfo.currentKeyIndex != NOT_A_KEY) && (this.keys[touchInfo.currentKeyIndex].codes != null)) ? this.keys[keyIndex].codes[0]
                  : 0);
  if (touchInfo.currentKeyIndex != NOT_A_KEY) {
      Message msg = this.handler.obtainMessage(MSG_LONGPRESS, touchInfo);
      this.handler.sendMessageDelayed(msg, this.longPressTimeOut);
      // Release the old key and press the new key
      final Key[] keys = this.keys;
      if (keys.length > touchInfo.currentKeyIndex) {
    keys[touchInfo.currentKeyIndex].onPressed();
    invalidateKey(touchInfo.currentKeyIndex);
      }
      showPreview(touchInfo);
  } else {
      return false;
  }
  if ((touchInfo.currentKeyIndex >= 0)
          && isCurrentKeyRepeatable(touchInfo)) {
      touchInfo.repeatKeyIndex = touchInfo.currentKeyIndex;
      touchInfo.repeatSwiping = touchInfo.currentSwiping;
      touchInfo.isRepeating = false;
      Message msg = this.handler.obtainMessage(MSG_REPEAT, touchInfo);
      this.handler.sendMessageDelayed(msg, REPEAT_START_DELAY);
  }
  identifySwipingMove(touchInfo, touchX, touchY);
  detectAndSendKey(touchInfo, true);
  return true;
    }

    private void handleKeyMove(TouchInfo touchInfo, int touchX, int touchY) {

  identifySwipingMove(touchInfo, touchX, touchY);
  if ((Math.abs(touchInfo.lastMoveX - touchX) > 2)
          || (Math.abs(touchInfo.lastMoveY - touchY) > 2)) {
      touchInfo.lastMoveX = touchX;
      touchInfo.lastMoveY = touchY;
      this.handler.removeMessages(MSG_LONGPRESS);
      Message msg = this.handler.obtainMessage(MSG_LONGPRESS, touchInfo);
      this.handler.sendMessageDelayed(msg, this.longPressTimeOut);
  }
    }

    private void handleKeyUp(TouchInfo touchInfo, int touchX, int touchY,
      int keyIndex, long eventTime) {

  identifySwipingMove(touchInfo, touchX, touchY);
  detectAndSendKey(touchInfo, false);
  touchInfo.repeatKeyIndex = NOT_A_KEY;
  this.handler.removeMessages(MSG_SHOW_PREVIEW);
  this.handler.removeMessages(MSG_REPEAT);
  this.handler.removeMessages(MSG_LONGPRESS);
  if (keyIndex == touchInfo.currentKeyIndex) {
      touchInfo.currentKeyTime += eventTime - touchInfo.lastMoveTime;
  } else {
      touchInfo.lastKey = touchInfo.currentKeyIndex;
      touchInfo.lastKeyTime = touchInfo.currentKeyTime + eventTime
        - touchInfo.lastMoveTime;
      touchInfo.currentKeyIndex = keyIndex;
      touchInfo.currentKeyTime = 0;
  }
  if ((touchInfo.currentKeyTime < touchInfo.lastKeyTime)
          && (touchInfo.lastKey != NOT_A_KEY)) {
      touchInfo.currentKeyIndex = touchInfo.lastKey;
      touchX = touchInfo.lastCodeX;
      touchY = touchInfo.lastCodeY;
  }
  cancelPreview();
  releaseKey(touchInfo);
  Arrays.fill(this.mKeyIndices, NOT_A_KEY);
  touchInfo.lastKey = NOT_A_KEY;
  touchInfo.currentKeyIndex = NOT_A_KEY;

  invalidateKey(keyIndex);
  resetSwiping();
    }

    private void releaseKey(TouchInfo touchInfo) {
  final Key[] keys = this.keys;
  if (keys.length > touchInfo.currentKeyIndex
          && touchInfo.currentKeyIndex >= 0) {
      keys[touchInfo.currentKeyIndex].onReleased();
      invalidateKey(touchInfo.currentKeyIndex);
  }
    }

    private void releaseAllKeys() {
  final Key[] keys = this.keys;
  for (Key key : keys) {
      key.onReleased();
  }
    }

    @Override
    public boolean onTouchEvent(MotionEvent me) {

  // Needs to be called after the gesture detector gets a turn, as it may
  // have
  // displayed the mini keyboard
  if (this.miniKeyboardOnScreen) {
      return true;
  }

  long eventTime = me.getEventTime();
  int touchX = (int) me.getX() - getPaddingLeft()
          - (getWidth() - this.keyboard.getMinWidth()) / 2;
  int touchY = (int) me.getY() + this.verticalCorrection
          - getPaddingTop();
  int action = me.getAction();
  int keyIndex = getKeyIndices(touchX, touchY, null);

  switch (action) {
  case MotionEvent.ACTION_DOWN:
      if (!handleKeyDown(this.touchInfos[0], touchX, touchY, keyIndex,
        eventTime)) {
    return false;
      }
      break;

  case MotionEvent.ACTION_MOVE:
      handleKeyMove(this.touchInfos[0], touchX, touchY);
      break;

  case MotionEvent.ACTION_UP:
      handleKeyUp(this.touchInfos[0], touchX, touchY, keyIndex, eventTime);
      break;
  }

  // Debug.waitForDebugger();
  /*
   * int touchX; int touchY; // Extract the index of the pointer that left
   * the touch sensor // final int pointerId =
   * me.getPointerId(pointerIndex); int pointerIndex = (action &
   * MotionEvent.ACTION_POINTER_ID_MASK) >>
   * MotionEvent.ACTION_POINTER_ID_SHIFT; int pointerId =
   * me.getPointerId(pointerIndex);
   * 
   * int keyIndex; switch (action & MotionEvent.ACTION_MASK) { case
   * MotionEvent.ACTION_DOWN: this.pointerId1 = pointerId; //
   * this.pointerId = me.getPointerId(pointerIndex); touchX = (int)
   * me.getX(pointerIndex) - getPaddingLeft() - (getWidth() -
   * this.keyboard.getMinWidth()) / 2; touchY = (int)
   * me.getY(pointerIndex) + this.verticalCorrection - getPaddingTop();
   * keyIndex = getKeyIndices(touchX, touchY, null); if
   * (!handleKeyDown(this.touchInfos[pointerIndex], touchX, touchY,
   * keyIndex, eventTime)) { return false; } break; case
   * MotionEvent.ACTION_POINTER_DOWN: this.pointerId2 = pointerId; //
   * this.pointerId = me.getPointerId(pointerIndex); touchX = (int)
   * me.getX(pointerIndex) - getPaddingLeft() - (getWidth() -
   * this.keyboard.getMinWidth()) / 2; touchY = (int)
   * me.getY(pointerIndex) + this.verticalCorrection - getPaddingTop();
   * keyIndex = getKeyIndices(touchX, touchY, null); if
   * (!handleKeyDown(this.touchInfos[pointerIndex], touchX, touchY,
   * keyIndex, eventTime)) { return false; } break;
   * 
   * // this.pointerId = me.getPointerId(pointerIndex); // touchX = (int)
   * me.getX(pointerIndex) - getPaddingLeft() // - (getWidth() -
   * this.keyboard.getMinWidth()) / 2; // touchY = (int)
   * me.getY(pointerIndex) + this.verticalCorrection // - getPaddingTop();
   * // keyIndex = getKeyIndices(touchX, touchY, null); // if
   * (!handleKeyDown(this.touchInfos[pointerIndex], touchX, touchY, //
   * keyIndex, eventTime)) { // return false; // } // break;
   * 
   * case MotionEvent.ACTION_MOVE: // pointerIndex = (action &
   * MotionEvent.ACTION_POINTER_ID_MASK) >> //
   * MotionEvent.ACTION_POINTER_ID_SHIFT; // if
   * (me.getPointerId(pointerIndex) == this.pointerId) {
   * 
   * pointerIndex = me.findPointerIndex(this.pointerId2); if (pointerIndex
   * != -1) { touchX = (int) me.getX(pointerIndex) - getPaddingLeft() -
   * (getWidth() - this.keyboard.getMinWidth()) / 2; touchY = (int)
   * me.getY(pointerIndex) + this.verticalCorrection - getPaddingTop();
   * 
   * handleKeyMove(this.touchInfos[pointerIndex], touchX, touchY);
   * Log.d("test", "x:" + touchX + ",y:" + touchY + ",pointerId:" +
   * pointerId); // } } break;
   * 
   * case MotionEvent.ACTION_POINTER_UP: case MotionEvent.ACTION_UP: //
   * pointerIndex = me.findPointerIndex(this.pointerId); touchX = (int)
   * me.getX(pointerIndex) - getPaddingLeft() - (getWidth() -
   * this.keyboard.getMinWidth()) / 2; touchY = (int)
   * me.getY(pointerIndex) + this.verticalCorrection - getPaddingTop();
   * keyIndex = getKeyIndices(touchX, touchY, null);
   * handleKeyUp(this.touchInfos[pointerIndex], touchX, touchY, keyIndex,
   * eventTime); break;
   * 
   * // pointerIndex = me.findPointerIndex(this.pointerId); // touchX =
   * (int) me.getX(pointerIndex) - getPaddingLeft() // - (getWidth() -
   * this.keyboard.getMinWidth()) / 2; // touchY = (int)
   * me.getY(pointerIndex) + this.verticalCorrection // - getPaddingTop();
   * // handleKeyUp(this.touchInfos[pointerIndex], touchX, touchY, //
   * keyIndex, eventTime); // break; }
   */
  return true;
    }

    private boolean isCurrentKeyRepeatable(TouchInfo touchInfo) {
  if (this.keys[touchInfo.currentKeyIndex] == null) {
      return false;
  }
  boolean isRepeatable = false;
  switch (touchInfo.currentSwiping) {
  case NO_SWIPING:
      isRepeatable = this.keys[touchInfo.currentKeyIndex].repeatable;
      break;
  case SWIPING_TOP:
      isRepeatable = this.keys[touchInfo.currentKeyIndex].repeatableTop;
      break;
  case SWIPING_BOTTOM:
      isRepeatable = this.keys[touchInfo.currentKeyIndex].repeatableBottom;
      break;
  case SWIPING_LEFT:
      isRepeatable = this.keys[touchInfo.currentKeyIndex].repeatableLeft;
      break;
  case SWIPING_RIGHT:
      isRepeatable = this.keys[touchInfo.currentKeyIndex].repeatableRight;
      break;
  }
  return isRepeatable;
    }

    public void cancelDetection() {
  if (this.touchInfos[0].currentKeyIndex >= 0
          || this.touchInfos[1].currentKeyIndex >= 0) {
      for (TouchInfo touchInfo : this.touchInfos) {
    releaseKey(touchInfo);
      }
      cancelPreview();
      this.handler.removeMessages(MSG_SHOW_PREVIEW);
      this.handler.removeMessages(MSG_REPEAT);
      this.handler.removeMessages(MSG_LONGPRESS);
      resetSwiping();
      dismissPopupKeyboard();
  }
    }

    private void identifySwipingMove(TouchInfo touchInfo, int touchX, int touchY) {
  final float moveX = touchInfo.lastCodeX - touchX;
  final float moveY = touchInfo.lastCodeY - touchY;

  if (Math.abs(moveX) > Math.abs(moveY)) {
      if (moveX < -this.sensitivity) {
    swipeRight(touchInfo);
      } else if (moveX > this.sensitivity) {
    swipeLeft(touchInfo);
      } else {
    noSwipe(touchInfo);
      }
  } else {
      if (moveY > this.sensitivity) {
    swipeUp(touchInfo);
      } else if (moveY < -this.sensitivity) {
    swipeDown(touchInfo);
      } else {
    noSwipe(touchInfo);
      }
  }
    }

    private void resetSwiping() {
  for (TouchInfo touchInfo : this.touchInfos) {
      touchInfo.currentSwiping = NO_SWIPING;
      touchInfo.previousSwiping = NO_SWIPING;
  }
    }

    protected void swipeRight(TouchInfo touchInfo) {
  touchInfo.previousSwiping = touchInfo.currentSwiping;
  touchInfo.currentSwiping = SWIPING_RIGHT;
  showPreview(touchInfo);
  this.keyboardActionListener.swipeRight();
    }

    protected void swipeLeft(TouchInfo touchInfo) {
  touchInfo.previousSwiping = touchInfo.currentSwiping;
  touchInfo.currentSwiping = SWIPING_LEFT;
  showPreview(touchInfo);
  this.keyboardActionListener.swipeLeft();
    }

    protected void swipeUp(TouchInfo touchInfo) {
  touchInfo.previousSwiping = touchInfo.currentSwiping;
  touchInfo.currentSwiping = SWIPING_TOP;
  showPreview(touchInfo);
  this.keyboardActionListener.swipeUp();
    }

    protected void swipeDown(TouchInfo touchInfo) {
  touchInfo.previousSwiping = touchInfo.currentSwiping;
  touchInfo.currentSwiping = SWIPING_BOTTOM;
  showPreview(touchInfo);
  this.keyboardActionListener.swipeDown();
    }

    protected void noSwipe(TouchInfo touchInfo) {
  touchInfo.previousSwiping = touchInfo.currentSwiping;
  touchInfo.currentSwiping = NO_SWIPING;
  showPreview(touchInfo);
    }

    public void closing() {
  if (this.previewPopup.isShowing()) {
      this.previewPopup.dismiss();
  }
  this.handler.removeMessages(MSG_LONGPRESS);
  this.handler.removeMessages(MSG_SHOW_PREVIEW);

  dismissPopupKeyboard();
  this.buffer = null;
  this.canvas = null;
  this.miniKeyboardCache.clear();
    }

    @Override
    public void onDetachedFromWindow() {
  super.onDetachedFromWindow();
  closing();
    }

    private void dismissPopupKeyboard() {
  if (this.popupKeyboard.isShowing()) {
      this.popupKeyboard.dismiss();
      this.miniKeyboardOnScreen = false;
      invalidateAll();
  }
    }

    /**
     * Handles when the back button is pressed on the phone.
     */
    public boolean handleBack() {
  if (this.popupKeyboard.isShowing()) {
      dismissPopupKeyboard();
      return true;
  }
  return false;
    }

    private boolean repeatKey(TouchInfo touchInfo) {
  if ((touchInfo.isRepeating || (touchInfo.repeatKeyIndex == touchInfo.currentKeyIndex && touchInfo.repeatSwiping == touchInfo.currentSwiping))
          && touchInfo.repeatKeyIndex < this.keys.length) {
      final Key key = this.keys[touchInfo.repeatKeyIndex];
      int code = key.codes[0];
      if (code != Integer.MAX_VALUE) {
    this.keyboardActionListener.onKeyUp(code, key.codes,
            key.keyboard);
    this.keyboardActionListener.onRelease(code);
    touchInfo.isRepeating = true;
    return true;
      }
  }
  return false;
    }

    /**
     * Sets the sensitivity of the keyboard when swiping.
     */
    public void setSensitivity(int level) {
  this.sensitivity = level * 10;
    }

    /**
     * Sets the time interval between two repetition of a character (en ms).
     */
    public void setRepeatInterval(int repeatInterval) {
  this.repeatInterval = repeatInterval;
    }

    /**
     * Sets the time before the popup keyboard is displayed (en ms).
     */
    public void setLongPressTimeOut(int popupKeyboardTimeOut) {
  this.longPressTimeOut = popupKeyboardTimeOut;
    }

    /**
     * Indicates if the view is temporary.
     */
    public void setTemporarySwitch(boolean isTemporarySwitch) {
  this.isTemporarySwitch = isTemporarySwitch;
  if (this.isTemporarySwitch) {
      setBackgroundColor(this.temporaryBackgroundColor);
  } else {
      setBackgroundColor(this.permanentBackgroundColor);
  }
    }

    /**
     * Gets if the view is temporary.
     */
    public boolean isTemporarySwitch() {
  return this.isTemporarySwitch;
    }

    /**
     * Sets the boolean which indicates if the preview popup is displayed.
     */
    public void setDisplayKeyPreview(boolean displayKeyPreview) {
  this.displayKeyPreview = displayKeyPreview;
    }
}




Java Source Code List

com.asigbe.inputmethod.latin.BinaryDictionary.java
com.asigbe.inputmethod.latin.Dictionary.java
com.asigbe.inputmethod.latin.Suggest.java
com.asigbe.inputmethod.latin.TextEntryState.java
com.asigbe.inputmethod.latin.WordComposer.java
com.asigbe.slidekeyboard.provider.ContactContractsWrapper.java
com.asigbe.slidekeyboard.view.GestureLibraryWrapper.java
com.asigbe.slidekeyboard.view.GestureOverlayViewWrapper.java
com.asigbe.slidekeyboardpro.AsigbeKeyboard.java
com.asigbe.slidekeyboardpro.CandidateViewContainer.java
com.asigbe.slidekeyboardpro.CandidateView.java
com.asigbe.slidekeyboardpro.FirstUsageConfiguration.java
com.asigbe.slidekeyboardpro.KeyboardSwitcher.java
com.asigbe.slidekeyboardpro.LatinIMESettings.java
com.asigbe.slidekeyboardpro.MainActivity.java
com.asigbe.slidekeyboardpro.SlideKeyboardView.java
com.asigbe.slidekeyboardpro.SlideKeyboard.java