FileDocCategorySizeDatePackage
SkbContainer.javaAPI DocAndroid 1.5 API20865Wed May 06 22:42:48 BST 2009com.android.inputmethod.pinyin

SkbContainer

public class SkbContainer extends android.widget.RelativeLayout implements android.view.View.OnTouchListener
The top container to host soft keyboard view(s).

Fields Summary
private static final int
Y_BIAS_CORRECTION
For finger touch, user tends to press the bottom part of the target key, or he/she even presses the area out of it, so it is necessary to make a simple bias correction. If the input method runs on emulator, no bias correction will be used.
private static final int
MOVE_TOLERANCE
Used to skip these move events whose position is too close to the previous touch events.
private static boolean
POPUPWINDOW_FOR_PRESSED_UI
If this member is true, PopupWindow is used to show on-key highlight effect.
private int
mSkbLayout
The current soft keyboard layout.
private android.inputmethodservice.InputMethodService
mService
The input method service.
private InputModeSwitcher
mInputModeSwitcher
Input mode switcher used to switch between different modes like Chinese, English, etc.
private android.view.GestureDetector
mGestureDetector
The gesture detector.
private Environment
mEnvironment
private android.widget.ViewFlipper
mSkbFlipper
private BalloonHint
mBalloonPopup
The popup balloon hint for key press/release.
private BalloonHint
mBalloonOnKey
The on-key balloon hint for key press/release.
private SoftKeyboardView
mMajorView
The major sub soft keyboard.
private boolean
mLastCandidatesShowing
The last parameter when function {@link #toggleCandidateMode(boolean)} was called.
private boolean
mPopupSkbShow
Used to indicate whether a popup soft keyboard is shown.
private boolean
mPopupSkbNoResponse
Used to indicate whether a popup soft keyboard is just shown, and waits for the touch event to release. After the release, the popup window can response to touch events.
private android.widget.PopupWindow
mPopupSkb
Popup sub keyboard.
private SoftKeyboardView
mPopupSkbView
The view of the popup sub soft keyboard.
private int
mPopupX
private int
mPopupY
private volatile boolean
mWaitForTouchUp
When user presses a key, a timer is started, when it times out, it is necessary to detect whether user still holds the key.
private volatile boolean
mDiscardEvent
When user drags on the soft keyboard and the distance is enough, this drag will be recognized as a gesture and a gesture-based action will be taken, in this situation, ignore the consequent events.
private int
mYBiasCorrection
For finger touch, user tends to press the bottom part of the target key, or he/she even presses the area out of it, so it is necessary to make a simple bias correction in Y.
private int
mXLast
The x coordination of the last touch event.
private int
mYLast
The y coordination of the last touch event.
private SoftKeyboardView
mSkv
The soft keyboard view.
private int[]
mSkvPosInContainer
The position of the soft keyboard view in the container.
private SoftKey
mSoftKeyDown
The key pressed by user.
private LongPressTimer
mLongPressTimer
Used to timeout a press if user holds the key for a long time.
private int[]
mXyPosTmp
For temporary use.
Constructors Summary
public SkbContainer(android.content.Context context, android.util.AttributeSet attrs)


         
        super(context, attrs);

        mEnvironment = Environment.getInstance();

        mLongPressTimer = new LongPressTimer(this);

        // If it runs on an emulator, no bias correction
        if ("1".equals(SystemProperties.get("ro.kernel.qemu"))) {
            mYBiasCorrection = 0;
        } else {
            mYBiasCorrection = Y_BIAS_CORRECTION;
        }
        mBalloonPopup = new BalloonHint(context, this, MeasureSpec.AT_MOST);
        if (POPUPWINDOW_FOR_PRESSED_UI) {
            mBalloonOnKey = new BalloonHint(context, this, MeasureSpec.AT_MOST);
        }

        mPopupSkb = new PopupWindow(mContext);
        mPopupSkb.setBackgroundDrawable(null);
        mPopupSkb.setClippingEnabled(false);
    
Methods Summary
private voiddimSoftKeyboard(boolean dimSkb)

        mMajorView.dimSoftKeyboard(dimSkb);
    
private voiddismissPopupSkb()

        mPopupSkb.dismiss();
        mPopupSkbShow = false;
        dimSoftKeyboard(false);
        resetKeyPress(0);
    
public voiddismissPopups()

        handleBack(true);
        resetKeyPress(0);
    
public booleanhandleBack(boolean realAction)

        if (mPopupSkbShow) {
            if (!realAction) return true;

            dismissPopupSkb();
            mDiscardEvent = true;
            return true;
        }
        return false;
    
private SoftKeyboardViewinKeyboardView(int x, int y, int[] positionInParent)

        if (mPopupSkbShow) {
            if (mPopupX <= x && mPopupX + mPopupSkb.getWidth() > x
                    && mPopupY <= y && mPopupY + mPopupSkb.getHeight() > y) {
                positionInParent[0] = mPopupX;
                positionInParent[1] = mPopupY;
                mPopupSkbView.setOffsetToSkbContainer(positionInParent);
                return mPopupSkbView;
            }
            return null;
        }

        return mMajorView;
    
public booleanisCurrentSkbSticky()

        if (null == mMajorView) return true;
        SoftKeyboard skb = mMajorView.getSoftKeyboard();
        if (null != skb) {
            return skb.getStickyFlag();
        }
        return true;
    
protected voidonMeasure(int widthMeasureSpec, int heightMeasureSpec)

        Environment env = Environment.getInstance();
        int measuredWidth = env.getScreenWidth();
        int measuredHeight = getPaddingTop();
        measuredHeight += env.getSkbHeight();
        widthMeasureSpec = MeasureSpec.makeMeasureSpec(measuredWidth,
                MeasureSpec.EXACTLY);
        heightMeasureSpec = MeasureSpec.makeMeasureSpec(measuredHeight,
                MeasureSpec.EXACTLY);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    
public booleanonTouch(android.view.View v, android.view.MotionEvent event)

        // Translate the event to fit to the container.
        MotionEvent newEv = MotionEvent.obtain(event.getDownTime(), event
                .getEventTime(), event.getAction(), event.getX() + mPopupX,
                event.getY() + mPopupY, event.getPressure(), event.getSize(),
                event.getMetaState(), event.getXPrecision(), event
                        .getYPrecision(), event.getDeviceId(), event
                        .getEdgeFlags());
        boolean ret = onTouchEvent(newEv);
        return ret;
    
public booleanonTouchEvent(android.view.MotionEvent event)

        super.onTouchEvent(event);

        if (mSkbFlipper.isFlipping()) {
            resetKeyPress(0);
            return true;
        }

        int x = (int) event.getX();
        int y = (int) event.getY();
        // Bias correction
        y = y + mYBiasCorrection;

        // Ignore short-distance movement event to get better performance.
        if (event.getAction() == MotionEvent.ACTION_MOVE) {
            if (Math.abs(x - mXLast) <= MOVE_TOLERANCE
                    && Math.abs(y - mYLast) <= MOVE_TOLERANCE) {
                return true;
            }
        }

        mXLast = x;
        mYLast = y;

        if (!mPopupSkbShow) {
            if (mGestureDetector.onTouchEvent(event)) {
                resetKeyPress(0);
                mDiscardEvent = true;
                return true;
            }
        }

        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            resetKeyPress(0);

            mWaitForTouchUp = true;
            mDiscardEvent = false;

            mSkv = null;
            mSoftKeyDown = null;
            mSkv = inKeyboardView(x, y, mSkvPosInContainer);
            if (null != mSkv) {
                mSoftKeyDown = mSkv.onKeyPress(x - mSkvPosInContainer[0], y
                        - mSkvPosInContainer[1], mLongPressTimer, false);
            }
            break;

        case MotionEvent.ACTION_MOVE:
            if (x < 0 || x >= getWidth() || y < 0 || y >= getHeight()) {
                break;
            }
            if (mDiscardEvent) {
                resetKeyPress(0);
                break;
            }

            if (mPopupSkbShow && mPopupSkbNoResponse) {
                break;
            }

            SoftKeyboardView skv = inKeyboardView(x, y, mSkvPosInContainer);
            if (null != skv) {
                if (skv != mSkv) {
                    mSkv = skv;
                    mSoftKeyDown = mSkv.onKeyPress(x - mSkvPosInContainer[0], y
                            - mSkvPosInContainer[1], mLongPressTimer, true);
                } else if (null != skv) {
                    if (null != mSkv) {
                        mSoftKeyDown = mSkv.onKeyMove(
                                x - mSkvPosInContainer[0], y
                                        - mSkvPosInContainer[1]);
                        if (null == mSoftKeyDown) {
                            mDiscardEvent = true;
                        }
                    }
                }
            }
            break;

        case MotionEvent.ACTION_UP:
            if (mDiscardEvent) {
                resetKeyPress(0);
                break;
            }

            mWaitForTouchUp = false;

            // The view which got the {@link MotionEvent#ACTION_DOWN} event is
            // always used to handle this event.
            if (null != mSkv) {
                mSkv.onKeyRelease(x - mSkvPosInContainer[0], y
                        - mSkvPosInContainer[1]);
            }

            if (!mPopupSkbShow || !mPopupSkbNoResponse) {
                responseKeyEvent(mSoftKeyDown);
            }

            if (mSkv == mPopupSkbView && !mPopupSkbNoResponse) {
                dismissPopupSkb();
            }
            mPopupSkbNoResponse = false;
            break;

        case MotionEvent.ACTION_CANCEL:
            break;
        }

        if (null == mSkv) {
            return false;
        }

        return true;
    
private voidpopupSymbols()

        int popupResId = mSoftKeyDown.getPopupResId();
        if (popupResId > 0) {
            int skbContainerWidth = getWidth();
            int skbContainerHeight = getHeight();
            // The paddings of the background are not included.
            int miniSkbWidth = (int) (skbContainerWidth * 0.8);
            int miniSkbHeight = (int) (skbContainerHeight * 0.23);

            SkbPool skbPool = SkbPool.getInstance();
            SoftKeyboard skb = skbPool.getSoftKeyboard(popupResId, popupResId,
                    miniSkbWidth, miniSkbHeight, mContext);
            if (null == skb) return;

            mPopupX = (skbContainerWidth - skb.getSkbTotalWidth()) / 2;
            mPopupY = (skbContainerHeight - skb.getSkbTotalHeight()) / 2;

            if (null == mPopupSkbView) {
                mPopupSkbView = new SoftKeyboardView(mContext, null);
                mPopupSkbView.onMeasure(LayoutParams.WRAP_CONTENT,
                        LayoutParams.WRAP_CONTENT);
            }
            mPopupSkbView.setOnTouchListener(this);
            mPopupSkbView.setSoftKeyboard(skb);
            mPopupSkbView.setBalloonHint(mBalloonOnKey, mBalloonPopup, true);

            mPopupSkb.setContentView(mPopupSkbView);
            mPopupSkb.setWidth(skb.getSkbCoreWidth()
                    + mPopupSkbView.getPaddingLeft()
                    + mPopupSkbView.getPaddingRight());
            mPopupSkb.setHeight(skb.getSkbCoreHeight()
                    + mPopupSkbView.getPaddingTop()
                    + mPopupSkbView.getPaddingBottom());

            getLocationInWindow(mXyPosTmp);
            mPopupSkb.showAtLocation(this, Gravity.NO_GRAVITY, mPopupX, mPopupY
                    + mXyPosTmp[1]);
            mPopupSkbShow = true;
            mPopupSkbNoResponse = true;
            // Invalidate itself to dim the current soft keyboards.
            dimSoftKeyboard(true);
            resetKeyPress(0);
        }
    
private voidresetKeyPress(long delay)

        mLongPressTimer.removeTimer();

        if (null != mSkv) {
            mSkv.resetKeyPress(delay);
        }
    
private voidresponseKeyEvent(SoftKey sKey)

        if (null == sKey) return;
        ((PinyinIME) mService).responseSoftKeyEvent(sKey);
        return;
    
public voidsetGestureDetector(android.view.GestureDetector gestureDetector)

        mGestureDetector = gestureDetector;
    
public voidsetInputModeSwitcher(InputModeSwitcher inputModeSwitcher)

        mInputModeSwitcher = inputModeSwitcher;
    
public voidsetService(android.inputmethodservice.InputMethodService service)

        mService = service;
    
public voidtoggleCandidateMode(boolean candidatesShowing)

        if (null == mMajorView || !mInputModeSwitcher.isChineseText()
                || mLastCandidatesShowing == candidatesShowing) return;
        mLastCandidatesShowing = candidatesShowing;

        SoftKeyboard skb = mMajorView.getSoftKeyboard();
        if (null == skb) return;

        int state = mInputModeSwitcher.getTooggleStateForCnCand();
        if (!candidatesShowing) {
            skb.disableToggleState(state, false);
            skb.enableToggleStates(mInputModeSwitcher.getToggleStates());
        } else {
            skb.enableToggleState(state, false);
        }

        mMajorView.invalidate();
    
public voidupdateInputMode()

        int skbLayout = mInputModeSwitcher.getSkbLayout();
        if (mSkbLayout != skbLayout) {
            mSkbLayout = skbLayout;
            updateSkbLayout();
        }

        mLastCandidatesShowing = false;

        if (null == mMajorView) return;

        SoftKeyboard skb = mMajorView.getSoftKeyboard();
        if (null == skb) return;
        skb.enableToggleStates(mInputModeSwitcher.getToggleStates());
        invalidate();
        return;
    
private voidupdateSkbLayout()

        int screenWidth = mEnvironment.getScreenWidth();
        int keyHeight = mEnvironment.getKeyHeight();
        int skbHeight = mEnvironment.getSkbHeight();

        Resources r = mContext.getResources();
        if (null == mSkbFlipper) {
            mSkbFlipper = (ViewFlipper) findViewById(R.id.alpha_floatable);
        }
        mMajorView = (SoftKeyboardView) mSkbFlipper.getChildAt(0);

        SoftKeyboard majorSkb = null;
        SkbPool skbPool = SkbPool.getInstance();

        switch (mSkbLayout) {
        case R.xml.skb_qwerty:
            majorSkb = skbPool.getSoftKeyboard(R.xml.skb_qwerty,
                    R.xml.skb_qwerty, screenWidth, skbHeight, mContext);
            break;

        case R.xml.skb_sym1:
            majorSkb = skbPool.getSoftKeyboard(R.xml.skb_sym1, R.xml.skb_sym1,
                    screenWidth, skbHeight, mContext);
            break;

        case R.xml.skb_sym2:
            majorSkb = skbPool.getSoftKeyboard(R.xml.skb_sym2, R.xml.skb_sym2,
                    screenWidth, skbHeight, mContext);
            break;

        case R.xml.skb_smiley:
            majorSkb = skbPool.getSoftKeyboard(R.xml.skb_smiley,
                    R.xml.skb_smiley, screenWidth, skbHeight, mContext);
            break;

        case R.xml.skb_phone:
            majorSkb = skbPool.getSoftKeyboard(R.xml.skb_phone,
                    R.xml.skb_phone, screenWidth, skbHeight, mContext);
            break;
        default:
        }

        if (null == majorSkb || !mMajorView.setSoftKeyboard(majorSkb)) {
            return;
        }
        mMajorView.setBalloonHint(mBalloonOnKey, mBalloonPopup, false);
        mMajorView.invalidate();