diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
index 670564c39b20442367fdad92d43a16f5bd9fdc6a..4dab50fd8280fd4ed1f1a57ff080194f01e69af0 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
@@ -169,11 +169,11 @@ public class KeyboardView extends View {
     public void setKeyboard(final Keyboard keyboard) {
         mKeyboard = keyboard;
         LatinImeLogger.onSetKeyboard(keyboard);
-        requestLayout();
-        invalidateAllKeys();
         final int keyHeight = keyboard.mMostCommonKeyHeight - keyboard.mVerticalGap;
         mKeyDrawParams.updateParams(keyHeight, mKeyVisualAttributes);
         mKeyDrawParams.updateParams(keyHeight, keyboard.mKeyVisualAttributes);
+        invalidateAllKeys();
+        requestLayout();
     }
 
     /**
@@ -638,7 +638,6 @@ public class KeyboardView extends View {
     public void closing() {
         mInvalidateAllKeys = true;
         mKeyboard = null;
-        requestLayout();
     }
 
     @Override
diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
index d8ff5c265a998e6e03579ec468a34c7d9dc94de0..28a22f35cfb09cdab0be730d07861bba0c6d389e 100644
--- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
@@ -174,9 +174,9 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
     // More keys keyboard
     private final Paint mBackgroundDimAlphaPaint = new Paint();
     private boolean mNeedsToDimEntireKeyboard;
-    private final WeakHashMap<Key, MoreKeysPanel> mMoreKeysPanelCache =
-            new WeakHashMap<Key, MoreKeysPanel>();
-    private final int mMoreKeysLayout;
+    private final View mMoreKeysKeyboardContainer;
+    private final WeakHashMap<Key, Keyboard> mMoreKeysKeyboardCache =
+            CollectionUtils.newWeakHashMap();
     private final boolean mConfigShowMoreKeysKeyboardAtTouchedPoint;
     // More keys panel (used by both more keys keyboard and more suggestions view)
     // TODO: Consider extending to support multiple more keys panels
@@ -245,7 +245,7 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
                 break;
             case MSG_LONGPRESS_KEY:
                 if (tracker != null) {
-                    keyboardView.openMoreKeysKeyboardIfRequired(tracker.getKey(), tracker);
+                    keyboardView.onLongPress(tracker);
                 } else {
                     KeyboardSwitcher.getInstance().onLongPressTimeout(msg.arg1);
                 }
@@ -544,7 +544,7 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
         if (mKeyPreviewLayoutId == 0) {
             mShowKeyPreviewPopup = false;
         }
-        mMoreKeysLayout = mainKeyboardViewAttr.getResourceId(
+        final int moreKeysKeyboardLayoutId = mainKeyboardViewAttr.getResourceId(
                 R.styleable.MainKeyboardView_moreKeysKeyboardLayout, 0);
         mConfigShowMoreKeysKeyboardAtTouchedPoint = mainKeyboardViewAttr.getBoolean(
                 R.styleable.MainKeyboardView_showMoreKeysKeyboardAtTouchedPoint, false);
@@ -566,6 +566,8 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
         mPreviewPlacerView.addPreview(mSlidingKeyInputPreview);
         mainKeyboardViewAttr.recycle();
 
+        mMoreKeysKeyboardContainer = LayoutInflater.from(getContext())
+                .inflate(moreKeysKeyboardLayoutId, null);
         mLanguageOnSpacebarFadeoutAnimator = loadObjectAnimator(
                 languageOnSpacebarFadeoutAnimatorResId, this);
         mAltCodeKeyWhileTypingFadeoutAnimator = loadObjectAnimator(
@@ -653,7 +655,7 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
                 keyboard, -getPaddingLeft(), -getPaddingTop() + mVerticalCorrection);
         PointerTracker.setKeyDetector(mKeyDetector);
         mTouchScreenRegulator.setKeyboardGeometry(keyboard.mOccupiedWidth);
-        mMoreKeysPanelCache.clear();
+        mMoreKeysKeyboardCache.clear();
 
         mSpaceKey = keyboard.getKey(Constants.CODE_SPACE);
         mSpaceIcon = (mSpaceKey != null)
@@ -942,123 +944,105 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
         }
     }
 
-    private boolean openMoreKeysKeyboardIfRequired(final Key parentKey,
-            final PointerTracker tracker) {
-        // Check if we have a popup layout specified first.
-        if (mMoreKeysLayout == 0) {
-            return false;
-        }
-
-        // Check if we are already displaying popup panel.
-        if (mMoreKeysPanel != null) {
-            return false;
-        }
-        if (parentKey == null) {
-            return false;
-        }
-        return onLongPress(parentKey, tracker);
-    }
-
-    private MoreKeysPanel onCreateMoreKeysPanel(final Key parentKey) {
-        if (parentKey.mMoreKeys == null) {
+    private MoreKeysPanel onCreateMoreKeysPanel(final Key key, final Context context) {
+        if (key.mMoreKeys == null) {
             return null;
         }
-
-        final View container = LayoutInflater.from(getContext()).inflate(mMoreKeysLayout, null);
-        if (container == null) {
-            throw new NullPointerException();
+        Keyboard moreKeysKeyboard = mMoreKeysKeyboardCache.get(key);
+        if (moreKeysKeyboard == null) {
+            moreKeysKeyboard = new MoreKeysKeyboard.Builder(
+                    context, key, this, mKeyPreviewDrawParams).build();
+            mMoreKeysKeyboardCache.put(key, moreKeysKeyboard);
         }
 
+        final View container = mMoreKeysKeyboardContainer;
         final MoreKeysKeyboardView moreKeysKeyboardView =
                 (MoreKeysKeyboardView)container.findViewById(R.id.more_keys_keyboard_view);
-        final Keyboard moreKeysKeyboard = new MoreKeysKeyboard.Builder(
-                container, parentKey, this, mKeyPreviewDrawParams)
-                .build();
         moreKeysKeyboardView.setKeyboard(moreKeysKeyboard);
         container.measure(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
-
         return moreKeysKeyboardView;
     }
 
     /**
      * Called when a key is long pressed.
-     * @param parentKey the key that was long pressed
      * @param tracker the pointer tracker which pressed the parent key
      * @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.
      */
-    private boolean onLongPress(final Key parentKey, final PointerTracker tracker) {
+    private boolean onLongPress(final PointerTracker tracker) {
+        if (isShowingMoreKeysPanel()) {
+            return false;
+        }
+        final Key key = tracker.getKey();
+        if (key == null) {
+            return false;
+        }
         if (ProductionFlag.IS_EXPERIMENTAL) {
             ResearchLogger.mainKeyboardView_onLongPress();
         }
-        final int primaryCode = parentKey.mCode;
-        if (parentKey.hasEmbeddedMoreKey()) {
-            final int embeddedCode = parentKey.mMoreKeys[0].mCode;
+        final int code = key.mCode;
+        if (key.hasEmbeddedMoreKey()) {
+            final int embeddedCode = key.mMoreKeys[0].mCode;
             tracker.onLongPressed();
             invokeCodeInput(embeddedCode);
-            invokeReleaseKey(primaryCode);
-            KeyboardSwitcher.getInstance().hapticAndAudioFeedback(primaryCode);
+            invokeReleaseKey(code);
+            KeyboardSwitcher.getInstance().hapticAndAudioFeedback(code);
             return true;
         }
-        if (primaryCode == Constants.CODE_SPACE || primaryCode == Constants.CODE_LANGUAGE_SWITCH) {
+        if (code == Constants.CODE_SPACE || code == Constants.CODE_LANGUAGE_SWITCH) {
             // Long pressing the space key invokes IME switcher dialog.
             if (invokeCustomRequest(LatinIME.CODE_SHOW_INPUT_METHOD_PICKER)) {
                 tracker.onLongPressed();
-                invokeReleaseKey(primaryCode);
+                invokeReleaseKey(code);
                 return true;
             }
         }
-        return openMoreKeysPanel(parentKey, tracker);
+        return openMoreKeysPanel(key, tracker);
     }
 
-    private boolean invokeCustomRequest(final int code) {
-        return mKeyboardActionListener.onCustomRequest(code);
+    private boolean invokeCustomRequest(final int requestCode) {
+        return mKeyboardActionListener.onCustomRequest(requestCode);
     }
 
-    private void invokeCodeInput(final int primaryCode) {
+    private void invokeCodeInput(final int code) {
         mKeyboardActionListener.onCodeInput(
-                primaryCode, Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE);
+                code, Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE);
     }
 
-    private void invokeReleaseKey(final int primaryCode) {
-        mKeyboardActionListener.onReleaseKey(primaryCode, false);
+    private void invokeReleaseKey(final int code) {
+        mKeyboardActionListener.onReleaseKey(code, false);
     }
 
-    private boolean openMoreKeysPanel(final Key parentKey, final PointerTracker tracker) {
-        MoreKeysPanel moreKeysPanel = mMoreKeysPanelCache.get(parentKey);
+    private boolean openMoreKeysPanel(final Key key, final PointerTracker tracker) {
+        final MoreKeysPanel moreKeysPanel = onCreateMoreKeysPanel(key, getContext());
         if (moreKeysPanel == null) {
-            moreKeysPanel = onCreateMoreKeysPanel(parentKey);
-            if (moreKeysPanel == null) {
-                return false;
-            }
-            mMoreKeysPanelCache.put(parentKey, moreKeysPanel);
+            return false;
         }
 
         final int[] lastCoords = CoordinateUtils.newInstance();
         tracker.getLastCoordinates(lastCoords);
-        final boolean keyPreviewEnabled = isKeyPreviewPopupEnabled() && !parentKey.noKeyPreview();
+        final boolean keyPreviewEnabled = isKeyPreviewPopupEnabled() && !key.noKeyPreview();
         // The more keys keyboard is usually horizontally aligned with the center of the parent key.
         // If showMoreKeysKeyboardAtTouchedPoint is true and the key preview is disabled, the more
         // keys keyboard is placed at the touch point of the parent key.
         final int pointX = (mConfigShowMoreKeysKeyboardAtTouchedPoint && !keyPreviewEnabled)
                 ? CoordinateUtils.x(lastCoords)
-                : parentKey.mX + parentKey.mWidth / 2;
+                : key.mX + key.mWidth / 2;
         // The more keys keyboard is usually vertically aligned with the top edge of the parent key
         // (plus vertical gap). If the key preview is enabled, the more keys keyboard is vertically
         // aligned with the bottom edge of the visible part of the key preview.
         // {@code mPreviewVisibleOffset} has been set appropriately in
         // {@link KeyboardView#showKeyPreview(PointerTracker)}.
-        final int pointY = parentKey.mY + mKeyPreviewDrawParams.mPreviewVisibleOffset;
+        final int pointY = key.mY + mKeyPreviewDrawParams.mPreviewVisibleOffset;
         moreKeysPanel.showMoreKeysPanel(this, this, pointX, pointY, mKeyboardActionListener);
         final int translatedX = moreKeysPanel.translateX(CoordinateUtils.x(lastCoords));
         final int translatedY = moreKeysPanel.translateY(CoordinateUtils.y(lastCoords));
         tracker.onShowMoreKeysPanel(translatedX, translatedY, moreKeysPanel);
-        dimEntireKeyboard(true /* dimmed */);
         return true;
     }
 
     public boolean isInSlidingKeyInput() {
-        if (mMoreKeysPanel != null) {
+        if (isShowingMoreKeysPanel()) {
             return true;
         }
         return PointerTracker.isAnyInSlidingKeyInput();
@@ -1069,19 +1053,17 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
         if (isShowingMoreKeysPanel()) {
             onDismissMoreKeysPanel();
         }
+        mPreviewPlacerView.addView(panel.getContainerView());
         mMoreKeysPanel = panel;
-        mPreviewPlacerView.addView(mMoreKeysPanel.getContainerView());
+        dimEntireKeyboard(true /* dimmed */);
     }
 
     public boolean isShowingMoreKeysPanel() {
-        return (mMoreKeysPanel != null);
+        return mMoreKeysPanel != null && mMoreKeysPanel.isShowingInParent();
     }
 
     @Override
     public void onCancelMoreKeysPanel() {
-        if (isShowingMoreKeysPanel()) {
-            mMoreKeysPanel.dismissMoreKeysPanel();
-        }
         PointerTracker.dismissAllMoreKeysPanels();
     }
 
@@ -1254,9 +1236,9 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
     public void closing() {
         dismissAllKeyPreviews();
         cancelAllMessages();
+        onDismissMoreKeysPanel();
+        mMoreKeysKeyboardCache.clear();
         super.closing();
-        onCancelMoreKeysPanel();
-        mMoreKeysPanelCache.clear();
     }
 
     /**
@@ -1331,7 +1313,7 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
         invalidateKey(mSpaceKey);
     }
 
-    public void dimEntireKeyboard(final boolean dimmed) {
+    private void dimEntireKeyboard(final boolean dimmed) {
         final boolean needsRedrawing = mNeedsToDimEntireKeyboard != dimmed;
         mNeedsToDimEntireKeyboard = dimmed;
         if (needsRedrawing) {
diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java
index 6df883e416dfc455cde33a0a0831e4832f40825e..66c30149c3ed01c095343a470fc2f0fd8e5923ed 100644
--- a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java
@@ -16,9 +16,9 @@
 
 package com.android.inputmethod.keyboard;
 
+import android.content.Context;
 import android.graphics.Paint;
 import android.graphics.drawable.Drawable;
-import android.view.View;
 
 import com.android.inputmethod.annotations.UsedForTesting;
 import com.android.inputmethod.keyboard.internal.KeyPreviewDrawParams;
@@ -260,15 +260,15 @@ public final class MoreKeysKeyboard extends Keyboard {
 
         /**
          * The builder of MoreKeysKeyboard.
-         * @param containerView the container of {@link MoreKeysKeyboardView}.
+         * @param context the context of {@link MoreKeysKeyboardView}.
          * @param parentKey the {@link Key} that invokes more keys keyboard.
          * @param parentKeyboardView the {@link KeyboardView} that contains the parentKey.
          * @param keyPreviewDrawParams the parameter to place key preview.
          */
-        public Builder(final View containerView, final Key parentKey,
+        public Builder(final Context context, final Key parentKey,
                 final MainKeyboardView parentKeyboardView,
                 final KeyPreviewDrawParams keyPreviewDrawParams) {
-            super(containerView.getContext(), new MoreKeysKeyboardParams());
+            super(context, new MoreKeysKeyboardParams());
             final Keyboard parentKeyboard = parentKeyboardView.getKeyboard();
             load(parentKeyboard.mMoreKeysTemplate, parentKeyboard.mId);
 
diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java
index 0d42ab2fe4a36748add68251c5d6cc6499fcc85a..9e75f8b8a8057479ceadf520621f21bbe563b360 100644
--- a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java
@@ -174,6 +174,7 @@ public class MoreKeysKeyboardView extends KeyboardView implements MoreKeysPanel
 
     @Override
     public boolean dismissMoreKeysPanel() {
+        super.closing();
         if (mController == null) return false;
         return mController.onDismissMoreKeysPanel();
     }
diff --git a/java/src/com/android/inputmethod/latin/CollectionUtils.java b/java/src/com/android/inputmethod/latin/CollectionUtils.java
index c75f2df5c88db0227a21bc180e912fd2e364a1a4..a8623cc6332ebe754dd358e3757c7ecbd2ea3429 100644
--- a/java/src/com/android/inputmethod/latin/CollectionUtils.java
+++ b/java/src/com/android/inputmethod/latin/CollectionUtils.java
@@ -27,6 +27,7 @@ import java.util.LinkedList;
 import java.util.Map;
 import java.util.TreeMap;
 import java.util.TreeSet;
+import java.util.WeakHashMap;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.CopyOnWriteArrayList;
 
@@ -39,6 +40,10 @@ public final class CollectionUtils {
         return new HashMap<K,V>();
     }
 
+    public static <K, V> WeakHashMap<K, V> newWeakHashMap() {
+        return new WeakHashMap<K, V>();
+    }
+
     public static <K,V> TreeMap<K,V> newTreeMap() {
         return new TreeMap<K,V>();
     }
diff --git a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java
index 26a304ef898c76da5e9f0c1ced608d8c5421eced..438820d172bb14117a37c0466bb1077292de20e4 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java
@@ -19,7 +19,6 @@ package com.android.inputmethod.latin.suggestions;
 import android.content.Context;
 import android.util.AttributeSet;
 
-import com.android.inputmethod.keyboard.Keyboard;
 import com.android.inputmethod.keyboard.MoreKeysKeyboardView;
 import com.android.inputmethod.latin.R;
 
@@ -28,7 +27,6 @@ import com.android.inputmethod.latin.R;
  * key presses and touch movements.
  */
 public final class MoreSuggestionsView extends MoreKeysKeyboardView {
-
     public MoreSuggestionsView(final Context context, final AttributeSet attrs) {
         this(context, attrs, R.attr.moreSuggestionsViewStyle);
     }
@@ -44,32 +42,15 @@ public final class MoreSuggestionsView extends MoreKeysKeyboardView {
         return pane.mOccupiedWidth / 2;
     }
 
-    @Override
-    protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
-        final Keyboard keyboard = getKeyboard();
-        if (keyboard != null) {
-            final int width = keyboard.mOccupiedWidth + getPaddingLeft() + getPaddingRight();
-            final int height = keyboard.mOccupiedHeight + getPaddingTop() + getPaddingBottom();
-            setMeasuredDimension(width, height);
-        } else {
-            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-        }
-    }
-
     public void updateKeyboardGeometry(final int keyHeight) {
         mKeyDrawParams.updateParams(keyHeight, mKeyVisualAttributes);
     }
 
     @Override
-    public void onCodeInput(final int primaryCode, final int x, final int y) {
-        final int index = primaryCode - MoreSuggestions.SUGGESTION_CODE_BASE;
+    public void onCodeInput(final int code, final int x, final int y) {
+        final int index = code - MoreSuggestions.SUGGESTION_CODE_BASE;
         if (index >= 0 && index < SuggestionStripView.MAX_SUGGESTIONS) {
             mListener.onCustomRequest(index);
         }
     }
-
-    @Override
-    public boolean isShowingInParent() {
-        return (getContainerView().getParent() != null);
-    }
 }
diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
index 92b96e754b73da9851bc5c631a49489212deb270..bc51d5d62139b3de0e807a45b1c0bfc416e84f2f 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
@@ -676,12 +676,11 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
             new MoreKeysPanel.Controller() {
         @Override
         public boolean onDismissMoreKeysPanel() {
-            mMainKeyboardView.dimEntireKeyboard(false /* dimmed */);
             return mMainKeyboardView.onDismissMoreKeysPanel();
         }
 
         @Override
-        public void onShowMoreKeysPanel(MoreKeysPanel panel) {
+        public void onShowMoreKeysPanel(final MoreKeysPanel panel) {
             mMainKeyboardView.onShowMoreKeysPanel(panel);
         }
 
@@ -728,7 +727,6 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
         mMoreSuggestionsMode = MORE_SUGGESTIONS_CHECKING_MODAL_OR_SLIDING;
         mOriginX = mLastX;
         mOriginY = mLastY;
-        mMainKeyboardView.dimEntireKeyboard(true /* dimmed */);
         for (int i = 0; i < params.mSuggestionsCountInStrip; i++) {
             mWords.get(i).setPressed(false);
         }