Fix Auth Credential PIN layout inconsistence layout in landscape
The layout of AuthCredentialPasswordView in landscape doesn't consist with layout in portrait. This change do: 1. Make layout consistence on both portrait & landscape 2. Hook IME insets change callback and refine layout size 3. Optomize layout complexity Test: atest SystemUITests Test: Update Display/Font size to largest, and trigger BioMetric prompt Bug: 230698721 Merged-In: If484225a9b75af42bc4fee4d288c67c7361a1c89 Change-Id: If484225a9b75af42bc4fee4d288c67c7361a1c89
This commit is contained in:
@@ -18,44 +18,70 @@
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="horizontal"
|
||||
android:elevation="@dimen/biometric_dialog_elevation">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/TextAppearance.AuthCredential.Title"/>
|
||||
<RelativeLayout
|
||||
android:id="@+id/auth_credential_header"
|
||||
style="@style/AuthCredentialHeaderStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/subtitle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/TextAppearance.AuthCredential.Subtitle"/>
|
||||
<ImageView
|
||||
android:id="@+id/icon"
|
||||
style="@style/TextAppearance.AuthNonBioCredential.Icon"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:contentDescription="@null"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/TextAppearance.AuthCredential.Description"/>
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
style="@style/TextAppearance.AuthNonBioCredential.Title"
|
||||
android:layout_below="@id/icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<ImeAwareEditText
|
||||
android:id="@+id/lockPassword"
|
||||
android:layout_width="208dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:minHeight="48dp"
|
||||
android:gravity="center"
|
||||
android:inputType="textPassword"
|
||||
android:maxLength="500"
|
||||
android:imeOptions="actionNext|flagNoFullscreen|flagForceAscii"
|
||||
style="@style/TextAppearance.AuthCredential.PasswordEntry"/>
|
||||
<TextView
|
||||
android:id="@+id/subtitle"
|
||||
style="@style/TextAppearance.AuthNonBioCredential.Subtitle"
|
||||
android:layout_below="@id/title"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/error"
|
||||
android:layout_width="match_parent"
|
||||
<TextView
|
||||
android:id="@+id/description"
|
||||
style="@style/TextAppearance.AuthNonBioCredential.Description"
|
||||
android:layout_below="@id/subtitle"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/auth_credential_input"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/TextAppearance.AuthCredential.Error"/>
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImeAwareEditText
|
||||
android:id="@+id/lockPassword"
|
||||
style="@style/TextAppearance.AuthCredential.PasswordEntry"
|
||||
android:layout_width="208dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:imeOptions="actionNext|flagNoFullscreen|flagForceAscii"
|
||||
android:inputType="textPassword"
|
||||
android:minHeight="48dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/error"
|
||||
style="@style/TextAppearance.AuthNonBioCredential.Error"
|
||||
android:layout_gravity="center"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</com.android.systemui.biometrics.AuthCredentialPasswordView>
|
||||
@@ -22,68 +22,63 @@
|
||||
android:orientation="vertical">
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/auth_credential_header"
|
||||
style="@style/AuthCredentialHeaderStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/auth_credential_header"
|
||||
style="@style/AuthCredentialHeaderStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true">
|
||||
<ImageView
|
||||
android:id="@+id/icon"
|
||||
style="@style/TextAppearance.AuthNonBioCredential.Icon"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:contentDescription="@null"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:contentDescription="@null" />
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
style="@style/TextAppearance.AuthNonBioCredential.Title"
|
||||
android:layout_below="@id/icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
style="@style/TextAppearance.AuthNonBioCredential.Title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/subtitle"
|
||||
style="@style/TextAppearance.AuthNonBioCredential.Subtitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/description"
|
||||
style="@style/TextAppearance.AuthNonBioCredential.Description"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:layout_alignParentBottom="true">
|
||||
|
||||
<ImeAwareEditText
|
||||
android:id="@+id/lockPassword"
|
||||
style="@style/TextAppearance.AuthCredential.PasswordEntry"
|
||||
android:layout_width="208dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:imeOptions="actionNext|flagNoFullscreen|flagForceAscii"
|
||||
android:inputType="textPassword"
|
||||
android:minHeight="48dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/error"
|
||||
style="@style/TextAppearance.AuthNonBioCredential.Error"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</LinearLayout>
|
||||
<TextView
|
||||
android:id="@+id/subtitle"
|
||||
style="@style/TextAppearance.AuthNonBioCredential.Subtitle"
|
||||
android:layout_below="@id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/description"
|
||||
style="@style/TextAppearance.AuthNonBioCredential.Description"
|
||||
android:layout_below="@id/subtitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
</RelativeLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/auth_credential_input"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImeAwareEditText
|
||||
android:id="@+id/lockPassword"
|
||||
style="@style/TextAppearance.AuthCredential.PasswordEntry"
|
||||
android:layout_width="208dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:imeOptions="actionNext|flagNoFullscreen|flagForceAscii"
|
||||
android:inputType="textPassword"
|
||||
android:minHeight="48dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/error"
|
||||
style="@style/TextAppearance.AuthNonBioCredential.Error"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</com.android.systemui.biometrics.AuthCredentialPasswordView>
|
||||
@@ -18,4 +18,13 @@
|
||||
<style name="BrightnessDialogContainer" parent="@style/BaseBrightnessDialogContainer">
|
||||
<item name="android:layout_width">360dp</item>
|
||||
</style>
|
||||
|
||||
<style name="AuthCredentialHeaderStyle">
|
||||
<item name="android:paddingStart">48dp</item>
|
||||
<item name="android:paddingEnd">24dp</item>
|
||||
<item name="android:paddingTop">48dp</item>
|
||||
<item name="android:paddingBottom">10dp</item>
|
||||
<item name="android:gravity">top|center_horizontal</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -949,6 +949,9 @@
|
||||
<dimen name="biometric_dialog_width">240dp</dimen>
|
||||
<dimen name="biometric_dialog_height">240dp</dimen>
|
||||
|
||||
<!-- Biometric Auth Credential values -->
|
||||
<dimen name="biometric_auth_icon_size">48dp</dimen>
|
||||
|
||||
<!-- Starting text size in sp of batteryLevel for wireless charging animation -->
|
||||
<item name="wireless_charging_anim_battery_level_text_size_start" format="float" type="dimen">
|
||||
0
|
||||
|
||||
@@ -198,6 +198,11 @@
|
||||
<item name="android:textColor">?android:attr/textColorPrimary</item>
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance.AuthNonBioCredential.Icon">
|
||||
<item name="android:layout_width">@dimen/biometric_auth_icon_size</item>
|
||||
<item name="android:layout_height">@dimen/biometric_auth_icon_size</item>
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance.AuthNonBioCredential.Title">
|
||||
<item name="android:fontFamily">google-sans</item>
|
||||
<item name="android:layout_marginTop">20dp</item>
|
||||
@@ -227,6 +232,7 @@
|
||||
|
||||
<style name="TextAppearance.AuthCredential.PasswordEntry" parent="@android:style/TextAppearance.DeviceDefault">
|
||||
<item name="android:gravity">center</item>
|
||||
<item name="android:paddingTop">28dp</item>
|
||||
<item name="android:singleLine">true</item>
|
||||
<item name="android:textColor">?android:attr/colorForeground</item>
|
||||
<item name="android:textSize">24sp</item>
|
||||
@@ -235,7 +241,7 @@
|
||||
|
||||
<style name="AuthCredentialHeaderStyle">
|
||||
<item name="android:paddingStart">48dp</item>
|
||||
<item name="android:paddingEnd">24dp</item>
|
||||
<item name="android:paddingEnd">48dp</item>
|
||||
<item name="android:paddingTop">28dp</item>
|
||||
<item name="android:paddingBottom">20dp</item>
|
||||
<item name="android:orientation">vertical</item>
|
||||
|
||||
@@ -16,12 +16,20 @@
|
||||
|
||||
package com.android.systemui.biometrics;
|
||||
|
||||
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
|
||||
import static android.view.WindowInsets.Type.ime;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.content.Context;
|
||||
import android.graphics.Insets;
|
||||
import android.os.UserHandle;
|
||||
import android.text.InputType;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.View.OnApplyWindowInsetsListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowInsets;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.ImeAwareEditText;
|
||||
@@ -31,18 +39,24 @@ import com.android.internal.widget.LockPatternChecker;
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.internal.widget.LockscreenCredential;
|
||||
import com.android.internal.widget.VerifyCredentialResponse;
|
||||
import com.android.systemui.Dumpable;
|
||||
import com.android.systemui.R;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
|
||||
/**
|
||||
* Pin and Password UI
|
||||
*/
|
||||
public class AuthCredentialPasswordView extends AuthCredentialView
|
||||
implements TextView.OnEditorActionListener {
|
||||
implements TextView.OnEditorActionListener, OnApplyWindowInsetsListener, Dumpable {
|
||||
|
||||
private static final String TAG = "BiometricPrompt/AuthCredentialPasswordView";
|
||||
|
||||
private final InputMethodManager mImm;
|
||||
private ImeAwareEditText mPasswordField;
|
||||
private ViewGroup mAuthCredentialHeader;
|
||||
private ViewGroup mAuthCredentialInput;
|
||||
private int mBottomInset = 0;
|
||||
|
||||
public AuthCredentialPasswordView(Context context,
|
||||
AttributeSet attrs) {
|
||||
@@ -53,6 +67,9 @@ public class AuthCredentialPasswordView extends AuthCredentialView
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
|
||||
mAuthCredentialHeader = findViewById(R.id.auth_credential_header);
|
||||
mAuthCredentialInput = findViewById(R.id.auth_credential_input);
|
||||
mPasswordField = findViewById(R.id.lockPassword);
|
||||
mPasswordField.setOnEditorActionListener(this);
|
||||
// TODO: De-dupe the logic with AuthContainerView
|
||||
@@ -66,6 +83,8 @@ public class AuthCredentialPasswordView extends AuthCredentialView
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
setOnApplyWindowInsetsListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -127,4 +146,65 @@ public class AuthCredentialPasswordView extends AuthCredentialView
|
||||
mPasswordField.setText("");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
super.onLayout(changed, left, top, right, bottom);
|
||||
|
||||
if (mAuthCredentialInput == null || mAuthCredentialHeader == null
|
||||
|| mSubtitleView == null || mPasswordField == null || mErrorView == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// b/157910732 In AuthContainerView#getLayoutParams() we used to prevent jank risk when
|
||||
// resizing by IME show or hide, we used to setFitInsetsTypes `~WindowInsets.Type.ime()` to
|
||||
// LP. As a result this view needs to listen onApplyWindowInsets() and handle onLayout.
|
||||
int inputLeftBound;
|
||||
int inputTopBound;
|
||||
int headerRightBound = right;
|
||||
if (getResources().getConfiguration().orientation == ORIENTATION_LANDSCAPE) {
|
||||
inputTopBound = (bottom - (mPasswordField.getHeight() + mErrorView.getHeight())) / 2;
|
||||
inputLeftBound = (right - left) / 2;
|
||||
headerRightBound = inputLeftBound;
|
||||
} else {
|
||||
inputTopBound = mSubtitleView.getBottom() + (bottom - mSubtitleView.getBottom()) / 2;
|
||||
inputLeftBound = (right - left - mAuthCredentialInput.getWidth()) / 2;
|
||||
}
|
||||
|
||||
mAuthCredentialHeader.layout(left, top, headerRightBound, bottom);
|
||||
mAuthCredentialInput.layout(inputLeftBound, inputTopBound, right, bottom);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
final int newHeight = MeasureSpec.getSize(heightMeasureSpec) - mBottomInset;
|
||||
|
||||
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), newHeight);
|
||||
|
||||
measureChildren(widthMeasureSpec,
|
||||
MeasureSpec.makeMeasureSpec(newHeight, MeasureSpec.AT_MOST));
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public WindowInsets onApplyWindowInsets(@NonNull View v, WindowInsets insets) {
|
||||
|
||||
final Insets bottomInset = insets.getInsets(ime());
|
||||
if (v instanceof AuthCredentialPasswordView && mBottomInset != bottomInset.bottom) {
|
||||
mBottomInset = bottomInset.bottom;
|
||||
requestLayout();
|
||||
}
|
||||
return insets;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dump(@NonNull PrintWriter pw, @NonNull String[] args) {
|
||||
pw.println(TAG + "State:");
|
||||
pw.println(" mBottomInset=" + mBottomInset);
|
||||
pw.println(" mAuthCredentialHeader size=(" + mAuthCredentialHeader.getWidth() + ","
|
||||
+ mAuthCredentialHeader.getHeight());
|
||||
pw.println(" mAuthCredentialInput size=(" + mAuthCredentialInput.getWidth() + ","
|
||||
+ mAuthCredentialInput.getHeight());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@ import android.app.admin.DevicePolicyManager;
|
||||
import android.content.Context;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.hardware.biometrics.BiometricPrompt;
|
||||
import android.hardware.biometrics.PromptInfo;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.CountDownTimer;
|
||||
@@ -87,7 +86,7 @@ public abstract class AuthCredentialView extends LinearLayout {
|
||||
private boolean mShouldAnimateContents;
|
||||
|
||||
private TextView mTitleView;
|
||||
private TextView mSubtitleView;
|
||||
protected TextView mSubtitleView;
|
||||
private TextView mDescriptionView;
|
||||
private ImageView mIconView;
|
||||
protected TextView mErrorView;
|
||||
|
||||
Reference in New Issue
Block a user