diff --git a/res/layout-land/confirm_lock_password.xml b/res/layout-land/confirm_lock_password.xml
index 63b7e48dfd8..0cc9339aa2e 100644
--- a/res/layout-land/confirm_lock_password.xml
+++ b/res/layout-land/confirm_lock_password.xml
@@ -22,7 +22,6 @@
-
-
+ android:layout_height="wrap_content"/>
+ android:layout_height="0dp"
+ android:layout_weight="1">
-
+ android:layout_gravity="center_vertical"
+ android:gravity="center_horizontal"
+ android:orientation="vertical">
-
+
+
+
+
+
-
-
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:orientation="vertical"
+ android:paddingBottom="8dp">
-
+
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:gravity="center"
+ android:inputType="textPassword"
+ android:imeOptions="actionNext|flagNoExtractUi|flagForceAscii"
+ android:textSize="24sp"
+ style="@style/TextAppearance.PasswordEntry"/>
+ android:id="@+id/password_requirements_view"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"/>
diff --git a/res/layout/confirm_lock_password_base.xml b/res/layout/confirm_lock_password_base.xml
index 6942863bb0a..0c65e86b7f1 100644
--- a/res/layout/confirm_lock_password_base.xml
+++ b/res/layout/confirm_lock_password_base.xml
@@ -47,8 +47,7 @@
android:layout_marginEnd="?attr/confirmDeviceCredentialsSideMargin"
android:layout_marginTop="12dp"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- />
+ android:layout_height="wrap_content" />
-
+ android:gravity="center_horizontal"
+ android:orientation="vertical">
-
+
+
+
+
+
+
+ android:layout_weight="1"/>
-
-
-
-
-
+ android:gravity="center_horizontal"
+ android:orientation="vertical">
-
+
+
+
+
+
+
+ android:layout_weight="1" />
8dp
14sp
-
- 20sp
40dp
diff --git a/src/com/android/settings/ChooseLockPassword.java b/src/com/android/settings/ChooseLockPassword.java
index 351c2a204eb..88f3165fb01 100644
--- a/src/com/android/settings/ChooseLockPassword.java
+++ b/src/com/android/settings/ChooseLockPassword.java
@@ -16,12 +16,19 @@
package com.android.settings;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX;
+
import android.app.Activity;
import android.app.Fragment;
import android.app.admin.DevicePolicyManager;
import android.app.admin.PasswordMetrics;
import android.content.Context;
import android.content.Intent;
+import android.graphics.Rect;
import android.graphics.drawable.InsetDrawable;
import android.os.Bundle;
import android.os.Handler;
@@ -34,13 +41,15 @@ import android.text.Selection;
import android.text.Spannable;
import android.text.TextUtils;
import android.text.TextWatcher;
+import android.util.AttributeSet;
import android.util.Log;
-import android.view.inputmethod.EditorInfo;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
+import android.view.ViewParent;
+import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
@@ -59,12 +68,6 @@ import com.android.setupwizardlib.GlifLayout;
import java.util.ArrayList;
import java.util.List;
-import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
-import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC;
-import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
-import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
-import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX;
-
public class ChooseLockPassword extends SettingsActivity {
public static final String PASSWORD_MIN_KEY = "lockscreen.password_min";
public static final String PASSWORD_MAX_KEY = "lockscreen.password_max";
@@ -357,23 +360,6 @@ public class ChooseLockPassword extends SettingsActivity {
FRAGMENT_TAG_SAVE_AND_FINISH);
}
- // Workaround to show one password requirement below EditText when IME is shown.
- // By adding an inset to the edit text background, we make the EditText occupy more
- // vertical space, and the keyboard will then avoid hiding it. We have also set
- // negative margin in the layout below in order to have them show in the correct
- // position.
- final int visibleVerticalSpaceBelowPassword =
- getResources().getDimensionPixelOffset(
- R.dimen.visible_vertical_space_below_password);
- InsetDrawable drawable =
- new InsetDrawable(
- mPasswordEntry.getBackground(), 0, 0, 0, visibleVerticalSpaceBelowPassword);
- mPasswordEntry.setBackgroundDrawable(drawable);
- LinearLayout bottomContainer = (LinearLayout) view.findViewById(R.id.bottom_container);
- LinearLayout.LayoutParams bottomContainerLp =
- (LinearLayout.LayoutParams) bottomContainer.getLayoutParams();
- bottomContainerLp.setMargins(0, -visibleVerticalSpaceBelowPassword, 0, 0);
-
if (activity instanceof SettingsActivity) {
final SettingsActivity sa = (SettingsActivity) activity;
int id = mIsAlphaMode ? R.string.lockpassword_choose_your_password_header
diff --git a/src/com/android/settings/ConfirmLockPassword.java b/src/com/android/settings/ConfirmLockPassword.java
index 9a285f2a7bc..489f7a5dc0b 100644
--- a/src/com/android/settings/ConfirmLockPassword.java
+++ b/src/com/android/settings/ConfirmLockPassword.java
@@ -136,6 +136,9 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
mPasswordEntryInputDisabler = new TextViewInputDisabler(mPasswordEntry);
mHeaderTextView = (TextView) view.findViewById(R.id.headerText);
+ if (mHeaderTextView == null) {
+ mHeaderTextView = view.findViewById(R.id.suw_layout_title);
+ }
mDetailsTextView = (TextView) view.findViewById(R.id.detailsText);
mErrorTextView = (TextView) view.findViewById(R.id.errorText);
mIsAlpha = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC == storedQuality
diff --git a/src/com/android/settings/widget/ScrollToParentEditText.java b/src/com/android/settings/widget/ScrollToParentEditText.java
new file mode 100644
index 00000000000..97602afd9b4
--- /dev/null
+++ b/src/com/android/settings/widget/ScrollToParentEditText.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.widget;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewParent;
+import android.widget.EditText;
+
+/**
+ * An EditText that, instead of scrolling to itself when focused, will request scrolling to its
+ * parent. This is used in ChooseLockPassword to do make a best effort for not hiding the error
+ * messages for why the password is invalid under the keyboard.
+ */
+public class ScrollToParentEditText extends EditText {
+
+ private Rect mRect = new Rect();
+
+ public ScrollToParentEditText(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
+ ViewParent parent = getParent();
+ if (parent instanceof View) {
+ // Request the entire parent view to be shown, which in ChooseLockPassword's case,
+ // will include messages for why the password is invalid (if any).
+ ((View) parent).getDrawingRect(mRect);
+ return ((View) parent).requestRectangleOnScreen(mRect, immediate);
+ } else {
+ return super.requestRectangleOnScreen(rectangle, immediate);
+ }
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/widget/ScrollToParentEditTextTest.java b/tests/robotests/src/com/android/settings/widget/ScrollToParentEditTextTest.java
new file mode 100644
index 00000000000..e30421ec3d3
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/widget/ScrollToParentEditTextTest.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.widget;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.robolectric.RuntimeEnvironment.application;
+import static org.robolectric.Shadows.shadowOf;
+
+import android.graphics.Rect;
+import android.widget.FrameLayout;
+
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.Robolectric;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowView;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class ScrollToParentEditTextTest {
+
+ private static final int EDIT_TEXT_SIZE = 20;
+ private static final int PARENT_SIZE = 50;
+ private static final int SCROLL_RECT_SIZE = 30;
+
+ private ScrollToParentEditText mEditText;
+ private FrameLayout mParent;
+
+ @Before
+ public void setUp() {
+ mEditText = new ScrollToParentEditText(
+ application,
+ Robolectric.buildAttributeSet().build());
+ mEditText.layout(0, 0, EDIT_TEXT_SIZE, EDIT_TEXT_SIZE);
+
+ mParent = spy(new FrameLayout(application));
+ mParent.layout(0, 0, PARENT_SIZE, PARENT_SIZE);
+
+ doReturn(true).when(mParent).requestRectangleOnScreen(any(Rect.class), anyBoolean());
+ }
+
+ @Test
+ public void requestRectangleOnScreen_noParent_shouldScrollToItself() {
+ assertThat(mEditText.requestRectangleOnScreen(
+ new Rect(0, 0, SCROLL_RECT_SIZE, SCROLL_RECT_SIZE), true)).isFalse();
+ }
+
+ @Test
+ public void requestRectangleOnScreen_withParent_shouldScrollToParent() {
+ ShadowView shadowEditText = shadowOf(mEditText);
+ shadowEditText.setMyParent(mParent);
+
+ assertThat(mEditText.requestRectangleOnScreen(
+ new Rect(0, 0, SCROLL_RECT_SIZE, SCROLL_RECT_SIZE), true)).isTrue();
+ verify(mParent)
+ .requestRectangleOnScreen(eq(new Rect(0, 0, PARENT_SIZE, PARENT_SIZE)), eq(true));
+ }
+}