diff --git a/java/res/values/attrs.xml b/java/res/values/attrs.xml
index 37ba3963b66903461d12c8959cc17d80f779f15a..91cd01723c91a6b3537a102489438fabf71b7491 100644
--- a/java/res/values/attrs.xml
+++ b/java/res/values/attrs.xml
@@ -293,7 +293,7 @@
         <attr name="keyLabelFlags" format="integer">
             <!-- This should be aligned with Key.LABEL_FLAGS__* -->
             <flag name="alignIconToBottom" value="0x04" />
-            <flag name="alignLeftOfCenter" value="0x08" />
+            <flag name="alignLabelOffCenter" value="0x08" />
             <flag name="fontNormal" value="0x10" />
             <flag name="fontMonoSpace" value="0x20" />
             <flag name="fontDefault" value="0x30" />
@@ -368,6 +368,14 @@
         <attr name="keyHintLabelRatio" format="fraction" />
         <!-- Size of the text for shifted letter hint, in the proportion of key height. -->
         <attr name="keyShiftedLetterHintRatio" format="fraction" />
+        <!-- The label's horizontal offset to the center of the key. Negative is to left and
+             positive is to right. The value is in proportion of the width of
+             TypefaceUtils.KEY_LABEL_REFERENCE_CHAR. -->
+        <attr name="keyLabelOffCenterRatio" format="fraction" />
+        <!-- The hint label's horizontal offset to the center of the key. Negative is to left and
+             positive is to right. The value is in proportion of the width of
+             TypefaceUtils.KEY_LABEL_REFERENCE_CHAR. -->
+        <attr name="keyHintLabelOffCenterRatio" format="fraction" />
         <!-- Color to use for the label in a key. -->
         <attr name="keyTextColor" format="color" />
         <attr name="keyTextShadowColor" format="color" />
diff --git a/java/res/values/themes-common.xml b/java/res/values/themes-common.xml
index cf7888ad6ecf1bd9d513717f6fb8e92d575a381d..fd1c9f8c4651d19e78d67c0e8c8767f29ec3565b 100644
--- a/java/res/values/themes-common.xml
+++ b/java/res/values/themes-common.xml
@@ -41,6 +41,8 @@
         <item name="keyHintLetterRatio">@fraction/config_key_hint_letter_ratio</item>
         <item name="keyHintLabelRatio">@fraction/config_key_hint_label_ratio</item>
         <item name="keyShiftedLetterHintRatio">@fraction/config_key_shifted_letter_hint_ratio</item>
+        <item name="keyLabelOffCenterRatio">-175%</item>
+        <item name="keyHintLabelOffCenterRatio">200%</item>
         <item name="keyTypeface">normal</item>
         <!-- A negative value to disable key text shadow layer. -->
         <item name="keyTextShadowRadius">-1.0</item>
diff --git a/java/res/xml/key_styles_number.xml b/java/res/xml/key_styles_number.xml
index 3038097d804dd1d0e49a7c3f9539273dcadc45df..14b202874c793661c7c8ab4060f1470699a9b3b0 100644
--- a/java/res/xml/key_styles_number.xml
+++ b/java/res/xml/key_styles_number.xml
@@ -39,7 +39,7 @@
         latin:parentStyle="numKeyBaseStyle" />
     <key-style
         latin:styleName="numberKeyStyle"
-        latin:keyLabelFlags="alignLeftOfCenter|hasHintLabel"
+        latin:keyLabelFlags="alignLabelOffCenter|hasHintLabel"
         latin:parentStyle="numKeyStyle" />
     <key-style
         latin:styleName="num0KeyStyle"
diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java
index aaa55d79c5b1953209769c39c5b44308bf670ada..18b81161cdcb46c19127989e2d72f4e3194214f5 100644
--- a/java/src/com/android/inputmethod/keyboard/Key.java
+++ b/java/src/com/android/inputmethod/keyboard/Key.java
@@ -59,7 +59,7 @@ public class Key implements Comparable<Key> {
     /** Flags of the label */
     private final int mLabelFlags;
     private static final int LABEL_FLAGS_ALIGN_ICON_TO_BOTTOM = 0x04;
-    private static final int LABEL_FLAGS_ALIGN_LEFT_OF_CENTER = 0x08;
+    private static final int LABEL_FLAGS_ALIGN_LABEL_OFF_CENTER = 0x08;
     // Font typeface specification.
     private static final int LABEL_FLAGS_FONT_MASK = 0x30;
     private static final int LABEL_FLAGS_FONT_NORMAL = 0x10;
@@ -648,8 +648,8 @@ public class Key implements Comparable<Key> {
         return (mLabelFlags & LABEL_FLAGS_ALIGN_ICON_TO_BOTTOM) != 0;
     }
 
-    public final boolean isAlignLeftOfCenter() {
-        return (mLabelFlags & LABEL_FLAGS_ALIGN_LEFT_OF_CENTER) != 0;
+    public final boolean isAlignLabelOffCenter() {
+        return (mLabelFlags & LABEL_FLAGS_ALIGN_LABEL_OFF_CENTER) != 0;
     }
 
     public final boolean hasPopupHint() {
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
index 4a791f325666b115dd02f1ce3270f94291333260..72b254756f7098fd80fbaec0fa07e57f648e5ca0 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
@@ -369,9 +369,9 @@ public class KeyboardView extends View {
             final float baseline = centerY + labelCharHeight / 2.0f;
 
             // Horizontal label text alignment
-            if (key.isAlignLeftOfCenter()) {
-                // TODO: Parameterise this?
-                positionX = centerX - labelCharWidth * 7.0f / 4.0f;
+            if (key.isAlignLabelOffCenter()) {
+                // The label is placed off center of the key. Used mainly on "phone number" layout.
+                positionX = centerX + params.mLabelOffCenterRatio * labelCharWidth;
                 paint.setTextAlign(Align.LEFT);
             } else {
                 positionX = centerX;
@@ -418,15 +418,12 @@ public class KeyboardView extends View {
             blendAlpha(paint, params.mAnimAlpha);
             final float labelCharHeight = TypefaceUtils.getReferenceCharHeight(paint);
             final float labelCharWidth = TypefaceUtils.getReferenceCharWidth(paint);
-            final KeyVisualAttributes visualAttr = key.getVisualAttributes();
-            final float adjustmentY = (visualAttr == null) ? 0.0f
-                    : visualAttr.mHintLabelVerticalAdjustment * labelCharHeight;
+            final float adjustmentY = params.mHintLabelVerticalAdjustment * labelCharHeight;
             final float hintX, hintY;
             if (key.hasHintLabel()) {
                 // The hint label is placed just right of the key label. Used mainly on
                 // "phone number" layout.
-                // TODO: Generalize the following calculations.
-                hintX = positionX + labelCharWidth * 2.0f;
+                hintX = positionX + params.mHintLabelOffCenterRatio * labelCharWidth;
                 hintY = centerY + labelCharHeight / 2.0f;
                 paint.setTextAlign(Align.LEFT);
             } else if (key.hasShiftedLetterHint()) {
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyDrawParams.java b/java/src/com/android/inputmethod/keyboard/internal/KeyDrawParams.java
index 07ac06babe78172ab27cdbd9416aa739b3abd5fe..6dbee55ae77d44f6e0da4a33d8eabe30fddc52e4 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyDrawParams.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyDrawParams.java
@@ -42,6 +42,10 @@ public final class KeyDrawParams {
     public int mShiftedLetterHintActivatedColor;
     public int mPreviewTextColor;
 
+    public float mHintLabelVerticalAdjustment;
+    public float mLabelOffCenterRatio;
+    public float mHintLabelOffCenterRatio;
+
     public int mAnimAlpha;
 
     public KeyDrawParams() {}
@@ -68,6 +72,10 @@ public final class KeyDrawParams {
         mShiftedLetterHintActivatedColor = copyFrom.mShiftedLetterHintActivatedColor;
         mPreviewTextColor = copyFrom.mPreviewTextColor;
 
+        mHintLabelVerticalAdjustment = copyFrom.mHintLabelVerticalAdjustment;
+        mLabelOffCenterRatio = copyFrom.mLabelOffCenterRatio;
+        mHintLabelOffCenterRatio = copyFrom.mHintLabelOffCenterRatio;
+
         mAnimAlpha = copyFrom.mAnimAlpha;
     }
 
@@ -103,6 +111,13 @@ public final class KeyDrawParams {
         mShiftedLetterHintActivatedColor = selectColor(
                 attr.mShiftedLetterHintActivatedColor, mShiftedLetterHintActivatedColor);
         mPreviewTextColor = selectColor(attr.mPreviewTextColor, mPreviewTextColor);
+
+        mHintLabelVerticalAdjustment = selectFloatIfNonZero(
+                attr.mHintLabelVerticalAdjustment, mHintLabelVerticalAdjustment);
+        mLabelOffCenterRatio = selectFloatIfNonZero(
+                attr.mLabelOffCenterRatio, mLabelOffCenterRatio);
+        mHintLabelOffCenterRatio = selectFloatIfNonZero(
+                attr.mHintLabelOffCenterRatio, mHintLabelOffCenterRatio);
     }
 
     public KeyDrawParams mayCloneAndUpdateParams(final int keyHeight,
@@ -115,7 +130,7 @@ public final class KeyDrawParams {
         return newParams;
     }
 
-    private static final int selectTextSizeFromDimensionOrRatio(final int keyHeight,
+    private static int selectTextSizeFromDimensionOrRatio(final int keyHeight,
             final int dimens, final float ratio, final int defaultDimens) {
         if (ResourceUtils.isValidDimensionPixelSize(dimens)) {
             return dimens;
@@ -126,7 +141,7 @@ public final class KeyDrawParams {
         return defaultDimens;
     }
 
-    private static final int selectTextSize(final int keyHeight, final float ratio,
+    private static int selectTextSize(final int keyHeight, final float ratio,
             final int defaultSize) {
         if (ResourceUtils.isValidFraction(ratio)) {
             return (int)(keyHeight * ratio);
@@ -134,10 +149,17 @@ public final class KeyDrawParams {
         return defaultSize;
     }
 
-    private static final int selectColor(final int attrColor, final int defaultColor) {
+    private static int selectColor(final int attrColor, final int defaultColor) {
         if (attrColor != 0) {
             return attrColor;
         }
         return defaultColor;
     }
+
+    private static float selectFloatIfNonZero(final float attrFloat, final float defaultFloat) {
+        if (attrFloat != 0) {
+            return attrFloat;
+        }
+        return defaultFloat;
+    }
 }
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyVisualAttributes.java b/java/src/com/android/inputmethod/keyboard/internal/KeyVisualAttributes.java
index 133462ac7e31148f4472d10da538a0cee46bc188..69cf2e38948056dcc341bad021f7aaf0f21aa3e0 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyVisualAttributes.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyVisualAttributes.java
@@ -48,6 +48,8 @@ public final class KeyVisualAttributes {
     public final int mPreviewTextColor;
 
     public final float mHintLabelVerticalAdjustment;
+    public final float mLabelOffCenterRatio;
+    public final float mHintLabelOffCenterRatio;
 
     private static final int[] VISUAL_ATTRIBUTE_IDS = {
         R.styleable.Keyboard_Key_keyTypeface,
@@ -69,6 +71,8 @@ public final class KeyVisualAttributes {
         R.styleable.Keyboard_Key_keyShiftedLetterHintActivatedColor,
         R.styleable.Keyboard_Key_keyPreviewTextColor,
         R.styleable.Keyboard_Key_keyHintLabelVerticalAdjustment,
+        R.styleable.Keyboard_Key_keyLabelOffCenterRatio,
+        R.styleable.Keyboard_Key_keyHintLabelOffCenterRatio
     };
     private static final SparseIntArray sVisualAttributeIds = new SparseIntArray();
     private static final int ATTR_DEFINED = 1;
@@ -135,5 +139,9 @@ public final class KeyVisualAttributes {
 
         mHintLabelVerticalAdjustment = ResourceUtils.getFraction(keyAttr,
                 R.styleable.Keyboard_Key_keyHintLabelVerticalAdjustment, 0.0f);
+        mLabelOffCenterRatio = ResourceUtils.getFraction(keyAttr,
+                R.styleable.Keyboard_Key_keyLabelOffCenterRatio, 0.0f);
+        mHintLabelOffCenterRatio = ResourceUtils.getFraction(keyAttr,
+                R.styleable.Keyboard_Key_keyHintLabelOffCenterRatio, 0.0f);
     }
 }