MoreKeysKeyboardView.java revision 2282e8520a2c1984989a14fb09896536f5033b26
1ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka/*
2ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka * Copyright (C) 2011 The Android Open Source Project
3ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka *
4ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka * Licensed under the Apache License, Version 2.0 (the "License");
5ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka * you may not use this file except in compliance with the License.
6ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka * You may obtain a copy of the License at
7ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka *
8ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka *      http://www.apache.org/licenses/LICENSE-2.0
9ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka *
10ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka * Unless required by applicable law or agreed to in writing, software
11ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka * distributed under the License is distributed on an "AS IS" BASIS,
12ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka * See the License for the specific language governing permissions and
14ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka * limitations under the License.
15ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka */
16ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka
17ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaokapackage com.android.inputmethod.keyboard;
18ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka
19ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaokaimport android.content.Context;
20ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaokaimport android.content.res.Resources;
21ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaokaimport android.util.AttributeSet;
2235580bad6f3da3b204653825bbb6871563e70728Tom Ouyangimport android.view.MotionEvent;
23ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaokaimport android.view.View;
247f8345d59a82a9b1d458b8e55ffd12c2a0d466a7Tadashi G. Takaokaimport android.view.ViewGroup;
25ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka
26ac78633be28e8990fc3b3a8de192c80966e746e3Tadashi G. Takaokaimport com.android.inputmethod.latin.Constants;
27e07b51e7c65220ac183546103010dd617d164f60Tadashi G. Takaokaimport com.android.inputmethod.latin.R;
28e28eba5074664d5716b8e58b8d0a235746b261ebKen Wakasaimport com.android.inputmethod.latin.utils.CoordinateUtils;
29e07b51e7c65220ac183546103010dd617d164f60Tadashi G. Takaoka
30ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka/**
312affaf91a04d63e0994102299816014a8bbe11e1Tadashi G. Takaoka * A view that renders a virtual {@link MoreKeysKeyboard}. It handles rendering of keys and
322affaf91a04d63e0994102299816014a8bbe11e1Tadashi G. Takaoka * detecting key presses and touch movements.
33ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka */
3435580bad6f3da3b204653825bbb6871563e70728Tom Ouyangpublic class MoreKeysKeyboardView extends KeyboardView implements MoreKeysPanel {
35359c35e0f6e534d096efc1d9f2ff585139e3b3acTadashi G. Takaoka    private final int[] mCoordinates = CoordinateUtils.newInstance();
36ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka
3751c38a441a09a4920703e765cb26179e7a80f029Tadashi G. Takaoka    protected final KeyDetector mKeyDetector;
3809e4530ca75d4664eb72708face83b466839c522Tadashi G. Takaoka    private Controller mController = EMPTY_CONTROLLER;
3935580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    protected KeyboardActionListener mListener;
40ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka    private int mOriginX;
41ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka    private int mOriginY;
4235580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    private Key mCurrentKey;
4363c233ab9f50d844be6e52e382c6664475606760Tadashi G. Takaoka
4435580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    private int mActivePointerId;
45ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka
46bc464e2952e102219f0b977fc1e9140ad5bd03e4Tadashi G. Takaoka    public MoreKeysKeyboardView(final Context context, final AttributeSet attrs) {
472affaf91a04d63e0994102299816014a8bbe11e1Tadashi G. Takaoka        this(context, attrs, R.attr.moreKeysKeyboardViewStyle);
48ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka    }
49ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka
50bc464e2952e102219f0b977fc1e9140ad5bd03e4Tadashi G. Takaoka    public MoreKeysKeyboardView(final Context context, final AttributeSet attrs,
51bc464e2952e102219f0b977fc1e9140ad5bd03e4Tadashi G. Takaoka            final int defStyle) {
52ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka        super(context, attrs, defStyle);
53ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka
54ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka        final Resources res = context.getResources();
5550e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka        mKeyDetector = new MoreKeysDetector(
562fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa                res.getDimension(R.dimen.config_more_keys_keyboard_slide_allowance));
57ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka    }
58ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka
59ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka    @Override
60bc464e2952e102219f0b977fc1e9140ad5bd03e4Tadashi G. Takaoka    protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
6138f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka        final Keyboard keyboard = getKeyboard();
6238f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka        if (keyboard != null) {
638da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka            final int width = keyboard.mOccupiedWidth + getPaddingLeft() + getPaddingRight();
648da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka            final int height = keyboard.mOccupiedHeight + getPaddingTop() + getPaddingBottom();
6538f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka            setMeasuredDimension(width, height);
6638f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka        } else {
6738f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
6838f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka        }
6938f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka    }
7038f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka
7138f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka    @Override
72bc464e2952e102219f0b977fc1e9140ad5bd03e4Tadashi G. Takaoka    public void setKeyboard(final Keyboard keyboard) {
7363c233ab9f50d844be6e52e382c6664475606760Tadashi G. Takaoka        super.setKeyboard(keyboard);
7463c233ab9f50d844be6e52e382c6664475606760Tadashi G. Takaoka        mKeyDetector.setKeyboard(keyboard, -getPaddingLeft(),
7508ae0d5ca03ed455827e82222df249d1cafb5d71Tadashi G. Takaoka                -getPaddingTop() + getVerticalCorrection());
7663c233ab9f50d844be6e52e382c6664475606760Tadashi G. Takaoka    }
7763c233ab9f50d844be6e52e382c6664475606760Tadashi G. Takaoka
7863c233ab9f50d844be6e52e382c6664475606760Tadashi G. Takaoka    @Override
79bc464e2952e102219f0b977fc1e9140ad5bd03e4Tadashi G. Takaoka    public void showMoreKeysPanel(final View parentView, final Controller controller,
80fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang            final int pointX, final int pointY, final KeyboardActionListener listener) {
81f44a01b40852dde2363a061cdc7df2ef4cb59aadTadashi G. Takaoka        mController = controller;
82f44a01b40852dde2363a061cdc7df2ef4cb59aadTadashi G. Takaoka        mListener = listener;
83fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang        final View container = getContainerView();
84bcbaffd9dd950c6b82c682a742c93f9319d908f5Tadashi G. Takaoka        // The coordinates of panel's left-top corner in parentView's coordinate system.
852fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa        // We need to consider background drawable paddings.
862fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa        final int x = pointX - getDefaultCoordX() - container.getPaddingLeft() - getPaddingLeft();
872fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa        final int y = pointY - container.getMeasuredHeight() + container.getPaddingBottom()
882fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa                + getPaddingBottom();
89ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka
90bcbaffd9dd950c6b82c682a742c93f9319d908f5Tadashi G. Takaoka        parentView.getLocationInWindow(mCoordinates);
912fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa        // Ensure the horizontal position of the panel does not extend past the parentView edges.
92fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang        final int maxX = parentView.getMeasuredWidth() - container.getMeasuredWidth();
93be68b41ccb1a16201c3b91f1576a731f7715aaf6Tom Ouyang        final int panelX = Math.max(0, Math.min(maxX, x)) + CoordinateUtils.x(mCoordinates);
94fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang        final int panelY = y + CoordinateUtils.y(mCoordinates);
95fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang        container.setX(panelX);
96fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang        container.setY(panelY);
97ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka
98bcbaffd9dd950c6b82c682a742c93f9319d908f5Tadashi G. Takaoka        mOriginX = x + container.getPaddingLeft();
99bcbaffd9dd950c6b82c682a742c93f9319d908f5Tadashi G. Takaoka        mOriginY = y + container.getPaddingTop();
100fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang        controller.onShowMoreKeysPanel(this);
101f3f3189adbce15d609d5e06632f8e0630db890d1Tadashi G. Takaoka    }
102f3f3189adbce15d609d5e06632f8e0630db890d1Tadashi G. Takaoka
10335580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    /**
10435580bad6f3da3b204653825bbb6871563e70728Tom Ouyang     * Returns the default x coordinate for showing this panel.
10535580bad6f3da3b204653825bbb6871563e70728Tom Ouyang     */
10635580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    protected int getDefaultCoordX() {
10735580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        return ((MoreKeysKeyboard)getKeyboard()).getDefaultCoordX();
10835580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    }
10935580bad6f3da3b204653825bbb6871563e70728Tom Ouyang
11035580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    @Override
11135580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    public void onDownEvent(final int x, final int y, final int pointerId, final long eventTime) {
11235580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        mActivePointerId = pointerId;
11335580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        onMoveKeyInternal(x, y, pointerId);
11435580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    }
11535580bad6f3da3b204653825bbb6871563e70728Tom Ouyang
11635580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    @Override
11735580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    public void onMoveEvent(int x, int y, final int pointerId, long eventTime) {
118ac69ab400d1ea4f90b4ca24486d62212decf1069Tom Ouyang        if (mActivePointerId != pointerId) {
119ac69ab400d1ea4f90b4ca24486d62212decf1069Tom Ouyang            return;
120ac69ab400d1ea4f90b4ca24486d62212decf1069Tom Ouyang        }
121ac69ab400d1ea4f90b4ca24486d62212decf1069Tom Ouyang        final boolean hasOldKey = (mCurrentKey != null);
12235580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        onMoveKeyInternal(x, y, pointerId);
123ac69ab400d1ea4f90b4ca24486d62212decf1069Tom Ouyang        if (hasOldKey && mCurrentKey == null) {
124ac69ab400d1ea4f90b4ca24486d62212decf1069Tom Ouyang            // If the pointer has moved too far away from any target then cancel the panel.
1251f215a58c99f0eb2f536e9cccd51371f2883e201Tadashi G. Takaoka            mController.onCancelMoreKeysPanel();
126ac69ab400d1ea4f90b4ca24486d62212decf1069Tom Ouyang        }
12735580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    }
12835580bad6f3da3b204653825bbb6871563e70728Tom Ouyang
12935580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    @Override
13035580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    public void onUpEvent(final int x, final int y, final int pointerId, final long eventTime) {
13135580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        if (mCurrentKey != null && mActivePointerId == pointerId) {
13235580bad6f3da3b204653825bbb6871563e70728Tom Ouyang            updateReleaseKeyGraphics(mCurrentKey);
1337dc60f9db729e93cb591492574a436418c553ebfTadashi G. Takaoka            onCodeInput(mCurrentKey.getCode(), x, y);
13435580bad6f3da3b204653825bbb6871563e70728Tom Ouyang            mCurrentKey = null;
13535580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        }
13635580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    }
13735580bad6f3da3b204653825bbb6871563e70728Tom Ouyang
13835580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    /**
13935580bad6f3da3b204653825bbb6871563e70728Tom Ouyang     * Performs the specific action for this panel when the user presses a key on the panel.
14035580bad6f3da3b204653825bbb6871563e70728Tom Ouyang     */
14135580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    protected void onCodeInput(final int code, final int x, final int y) {
14235580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        if (code == Constants.CODE_OUTPUT_TEXT) {
14335580bad6f3da3b204653825bbb6871563e70728Tom Ouyang            mListener.onTextInput(mCurrentKey.getOutputText());
14435580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        } else if (code != Constants.CODE_UNSPECIFIED) {
145a91dfff5e54f68c4003327eeca47286084c35a2fJean Chalard            if (getKeyboard().hasProximityCharsCorrection(code)) {
1462282e8520a2c1984989a14fb09896536f5033b26Jean Chalard                mListener.onCodeInput(code, x, y, false /* isKeyRepeat */);
147a91dfff5e54f68c4003327eeca47286084c35a2fJean Chalard            } else {
1482282e8520a2c1984989a14fb09896536f5033b26Jean Chalard                mListener.onCodeInput(code, Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE,
1492282e8520a2c1984989a14fb09896536f5033b26Jean Chalard                        false /* isKeyRepeat */);
150a91dfff5e54f68c4003327eeca47286084c35a2fJean Chalard            }
15135580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        }
15235580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    }
15335580bad6f3da3b204653825bbb6871563e70728Tom Ouyang
15435580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    private void onMoveKeyInternal(int x, int y, int pointerId) {
15535580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        if (mActivePointerId != pointerId) {
15635580bad6f3da3b204653825bbb6871563e70728Tom Ouyang            // Ignore old pointers when newer pointer is active.
15735580bad6f3da3b204653825bbb6871563e70728Tom Ouyang            return;
15835580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        }
15935580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        final Key oldKey = mCurrentKey;
16035580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        final Key newKey = mKeyDetector.detectHitKey(x, y);
16135580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        if (newKey != oldKey) {
16235580bad6f3da3b204653825bbb6871563e70728Tom Ouyang            mCurrentKey = newKey;
16335580bad6f3da3b204653825bbb6871563e70728Tom Ouyang            invalidateKey(mCurrentKey);
16435580bad6f3da3b204653825bbb6871563e70728Tom Ouyang            if (oldKey != null) {
16535580bad6f3da3b204653825bbb6871563e70728Tom Ouyang                updateReleaseKeyGraphics(oldKey);
16635580bad6f3da3b204653825bbb6871563e70728Tom Ouyang            }
16735580bad6f3da3b204653825bbb6871563e70728Tom Ouyang            if (newKey != null) {
16835580bad6f3da3b204653825bbb6871563e70728Tom Ouyang                updatePressKeyGraphics(newKey);
16935580bad6f3da3b204653825bbb6871563e70728Tom Ouyang            }
17035580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        }
17135580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    }
17235580bad6f3da3b204653825bbb6871563e70728Tom Ouyang
17335580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    private void updateReleaseKeyGraphics(final Key key) {
17435580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        key.onReleased();
17535580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        invalidateKey(key);
17635580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    }
17735580bad6f3da3b204653825bbb6871563e70728Tom Ouyang
17835580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    private void updatePressKeyGraphics(final Key key) {
17935580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        key.onPressed();
18035580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        invalidateKey(key);
18135580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    }
18235580bad6f3da3b204653825bbb6871563e70728Tom Ouyang
183ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka    @Override
18409e4530ca75d4664eb72708face83b466839c522Tadashi G. Takaoka    public void dismissMoreKeysPanel() {
18509e4530ca75d4664eb72708face83b466839c522Tadashi G. Takaoka        if (!isShowingInParent()) {
18609e4530ca75d4664eb72708face83b466839c522Tadashi G. Takaoka            return;
18709e4530ca75d4664eb72708face83b466839c522Tadashi G. Takaoka        }
1881f215a58c99f0eb2f536e9cccd51371f2883e201Tadashi G. Takaoka        mController.onDismissMoreKeysPanel();
1899ec80d9d89eb599329c354451acdc482cc3de836Tadashi G. Takaoka    }
1909ec80d9d89eb599329c354451acdc482cc3de836Tadashi G. Takaoka
1919ec80d9d89eb599329c354451acdc482cc3de836Tadashi G. Takaoka    @Override
192bc464e2952e102219f0b977fc1e9140ad5bd03e4Tadashi G. Takaoka    public int translateX(final int x) {
19363c233ab9f50d844be6e52e382c6664475606760Tadashi G. Takaoka        return x - mOriginX;
19463c233ab9f50d844be6e52e382c6664475606760Tadashi G. Takaoka    }
19563c233ab9f50d844be6e52e382c6664475606760Tadashi G. Takaoka
19663c233ab9f50d844be6e52e382c6664475606760Tadashi G. Takaoka    @Override
197bc464e2952e102219f0b977fc1e9140ad5bd03e4Tadashi G. Takaoka    public int translateY(final int y) {
19863c233ab9f50d844be6e52e382c6664475606760Tadashi G. Takaoka        return y - mOriginY;
199ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka    }
200fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang
201fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang    @Override
20235580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    public boolean onTouchEvent(final MotionEvent me) {
20335580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        final int action = me.getActionMasked();
20435580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        final long eventTime = me.getEventTime();
20535580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        final int index = me.getActionIndex();
20635580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        final int x = (int)me.getX(index);
20735580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        final int y = (int)me.getY(index);
20835580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        final int pointerId = me.getPointerId(index);
20935580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        switch (action) {
21035580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        case MotionEvent.ACTION_DOWN:
21135580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        case MotionEvent.ACTION_POINTER_DOWN:
21235580bad6f3da3b204653825bbb6871563e70728Tom Ouyang            onDownEvent(x, y, pointerId, eventTime);
21335580bad6f3da3b204653825bbb6871563e70728Tom Ouyang            break;
21435580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        case MotionEvent.ACTION_UP:
21535580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        case MotionEvent.ACTION_POINTER_UP:
21635580bad6f3da3b204653825bbb6871563e70728Tom Ouyang            onUpEvent(x, y, pointerId, eventTime);
21735580bad6f3da3b204653825bbb6871563e70728Tom Ouyang            break;
21835580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        case MotionEvent.ACTION_MOVE:
21935580bad6f3da3b204653825bbb6871563e70728Tom Ouyang            onMoveEvent(x, y, pointerId, eventTime);
22035580bad6f3da3b204653825bbb6871563e70728Tom Ouyang            break;
22135580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        }
22233482a9b9ccf605c63fab7c9b8273a240bbc2035Tadashi G. Takaoka        return true;
22335580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    }
22435580bad6f3da3b204653825bbb6871563e70728Tom Ouyang
2257f8345d59a82a9b1d458b8e55ffd12c2a0d466a7Tadashi G. Takaoka    private View getContainerView() {
226fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang        return (View)getParent();
227fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang    }
228fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang
229fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang    @Override
2307f8345d59a82a9b1d458b8e55ffd12c2a0d466a7Tadashi G. Takaoka    public void showInParent(final ViewGroup parentView) {
2317f8345d59a82a9b1d458b8e55ffd12c2a0d466a7Tadashi G. Takaoka        removeFromParent();
2327f8345d59a82a9b1d458b8e55ffd12c2a0d466a7Tadashi G. Takaoka        parentView.addView(getContainerView());
2337f8345d59a82a9b1d458b8e55ffd12c2a0d466a7Tadashi G. Takaoka    }
2347f8345d59a82a9b1d458b8e55ffd12c2a0d466a7Tadashi G. Takaoka
2357f8345d59a82a9b1d458b8e55ffd12c2a0d466a7Tadashi G. Takaoka    @Override
2367f8345d59a82a9b1d458b8e55ffd12c2a0d466a7Tadashi G. Takaoka    public void removeFromParent() {
2377f8345d59a82a9b1d458b8e55ffd12c2a0d466a7Tadashi G. Takaoka        final View containerView = getContainerView();
2387f8345d59a82a9b1d458b8e55ffd12c2a0d466a7Tadashi G. Takaoka        final ViewGroup currentParent = (ViewGroup)containerView.getParent();
2397f8345d59a82a9b1d458b8e55ffd12c2a0d466a7Tadashi G. Takaoka        if (currentParent != null) {
2407f8345d59a82a9b1d458b8e55ffd12c2a0d466a7Tadashi G. Takaoka            currentParent.removeView(containerView);
2417f8345d59a82a9b1d458b8e55ffd12c2a0d466a7Tadashi G. Takaoka        }
2427f8345d59a82a9b1d458b8e55ffd12c2a0d466a7Tadashi G. Takaoka    }
2437f8345d59a82a9b1d458b8e55ffd12c2a0d466a7Tadashi G. Takaoka
2447f8345d59a82a9b1d458b8e55ffd12c2a0d466a7Tadashi G. Takaoka    @Override
245fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang    public boolean isShowingInParent() {
246fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang        return (getContainerView().getParent() != null);
247fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang    }
248ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka}
249