Animations/success state for external confirm device credentials (2/2)
Bug: 20929186 Change-Id: I4489dd37f1148fb03315ec337a546eee04660cb5
This commit is contained in:
@@ -1407,7 +1407,7 @@
|
||||
android:theme="@style/Theme.ConfirmDeviceCredentials"/>
|
||||
|
||||
<activity android:name="ConfirmLockPassword"
|
||||
android:windowSoftInputMode="adjustResize"
|
||||
android:windowSoftInputMode="stateHidden|adjustResize"
|
||||
android:theme="@style/Theme.ConfirmDeviceCredentials"/>
|
||||
|
||||
<activity android:name=".fingerprint.FingerprintSettings" android:exported="false"/>
|
||||
|
30
res/anim/confirm_credential_close_enter.xml
Normal file
30
res/anim/confirm_credential_close_enter.xml
Normal file
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2015 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
|
||||
-->
|
||||
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shareInterpolator="false"
|
||||
android:zAdjustment="top">
|
||||
<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
|
||||
android:interpolator="@*android:interpolator/decelerate_quart"
|
||||
android:fillEnabled="true"
|
||||
android:fillBefore="false" android:fillAfter="true"
|
||||
android:duration="200"/>
|
||||
<translate android:fromYDelta="8%" android:toYDelta="0"
|
||||
android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
|
||||
android:interpolator="@*android:interpolator/decelerate_quint"
|
||||
android:duration="350"/>
|
||||
</set>
|
21
res/anim/confirm_credential_close_exit.xml
Normal file
21
res/anim/confirm_credential_close_exit.xml
Normal file
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2015 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
|
||||
-->
|
||||
|
||||
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:interpolator="@android:interpolator/linear_out_slow_in"
|
||||
android:fromAlpha="1.0" android:toAlpha="0.0"
|
||||
android:duration="350" />
|
21
res/anim/confirm_credential_open_enter.xml
Normal file
21
res/anim/confirm_credential_open_enter.xml
Normal file
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2015 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
|
||||
-->
|
||||
|
||||
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:interpolator="@android:interpolator/linear_out_slow_in"
|
||||
android:fromAlpha="0.0" android:toAlpha="1.0"
|
||||
android:duration="160" />
|
20
res/anim/confirm_credential_open_exit.xml
Normal file
20
res/anim/confirm_credential_open_exit.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2015 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
|
||||
-->
|
||||
|
||||
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:fromAlpha="1.0" android:toAlpha="1.0"
|
||||
android:duration="160" />
|
29
res/drawable/ic_fingerprint_success.xml
Normal file
29
res/drawable/ic_fingerprint_success.xml
Normal file
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!--
|
||||
~ Copyright (C) 2015 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
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="32.0dp"
|
||||
android:height="32.0dp"
|
||||
android:viewportWidth="40.0"
|
||||
android:viewportHeight="40.0">
|
||||
<path
|
||||
android:pathData="M20.0,20.0m-20.0,0.0a20.0,20.0 0.0,1.0 1.0,40.0 0.0a20.0,20.0 0.0,1.0 1.0,-40.0 0.0"
|
||||
android:fillColor="?android:attr/colorAccent"/>
|
||||
<path
|
||||
android:pathData="M11.2,21.41l1.63,-1.619999 4.17,4.169998 10.59,-10.589999 1.619999,1.63 -12.209999,12.209999z"
|
||||
android:fillColor="#FFFFFF"/>
|
||||
</vector>
|
@@ -225,6 +225,11 @@
|
||||
<item name="android:layout_height">wrap_content</item>
|
||||
</style>
|
||||
|
||||
<style name="ConfirmDeviceCredentialsAnimationStyle" parent="@*android:style/Animation.Material.Activity">
|
||||
<item name="android:activityOpenEnterAnimation">@anim/confirm_credential_open_enter</item>
|
||||
<item name="android:activityOpenExitAnimation">@anim/confirm_credential_open_exit</item>
|
||||
</style>
|
||||
|
||||
<style name="Transparent">
|
||||
<item name="android:windowBackground">@android:color/transparent</item>
|
||||
<item name="android:windowNoTitle">true</item>
|
||||
|
@@ -199,7 +199,7 @@
|
||||
<item name="android:colorPrimaryDark">@*android:color/material_blue_grey_950</item>
|
||||
<item name="android:windowActionBar">false</item>
|
||||
<item name="android:windowNoTitle">true</item>
|
||||
<item name="preferenceBackgroundColor">@color/confirm_device_credential_dark_background</item>
|
||||
<item name="android:windowBackground">@color/confirm_device_credential_dark_background</item>
|
||||
|
||||
<item name="confirmDeviceCredentialsSideMargin">32dp</item>
|
||||
<item name="confirmDeviceCredentialsTopMargin">32dp</item>
|
||||
@@ -208,6 +208,8 @@
|
||||
<item name="@*android:regularColor">@color/lock_pattern_view_regular_color_dark</item>
|
||||
<item name="@*android:successColor">@color/lock_pattern_view_regular_color_dark</item>
|
||||
<item name="@*android:errorColor">@color/lock_pattern_view_error_color</item>
|
||||
|
||||
<item name="android:windowAnimationStyle">@style/ConfirmDeviceCredentialsAnimationStyle</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.FingerprintEnroll" parent="@*android:style/Theme.Material.Settings.NoActionBar">
|
||||
|
@@ -16,17 +16,23 @@
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import android.app.Fragment;
|
||||
import android.app.KeyguardManager;
|
||||
import android.os.Bundle;
|
||||
import android.view.MenuItem;
|
||||
import android.view.WindowManager;
|
||||
|
||||
public class ConfirmDeviceCredentialBaseActivity extends SettingsActivity {
|
||||
public abstract class ConfirmDeviceCredentialBaseActivity extends SettingsActivity {
|
||||
|
||||
private boolean mRestoring;
|
||||
private boolean mDark;
|
||||
private boolean mEnterAnimationPending;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedState) {
|
||||
if (getIntent().getBooleanExtra(ConfirmDeviceCredentialBaseFragment.DARK_THEME, false)) {
|
||||
setTheme(R.style.Theme_ConfirmDeviceCredentialsDark);
|
||||
mDark = true;
|
||||
}
|
||||
super.onCreate(savedState);
|
||||
boolean deviceLocked = getSystemService(KeyguardManager.class).isKeyguardLocked();
|
||||
@@ -41,6 +47,7 @@ public class ConfirmDeviceCredentialBaseActivity extends SettingsActivity {
|
||||
getActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
getActionBar().setHomeButtonEnabled(true);
|
||||
}
|
||||
mRestoring = savedState != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -51,4 +58,37 @@ public class ConfirmDeviceCredentialBaseActivity extends SettingsActivity {
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
if (!isChangingConfigurations() && !mRestoring && mDark) {
|
||||
prepareEnterAnimation();
|
||||
mEnterAnimationPending = true;
|
||||
}
|
||||
}
|
||||
|
||||
private ConfirmDeviceCredentialBaseFragment getFragment() {
|
||||
Fragment fragment = getFragmentManager().findFragmentById(R.id.main_content);
|
||||
if (fragment != null && fragment instanceof ConfirmDeviceCredentialBaseFragment) {
|
||||
return (ConfirmDeviceCredentialBaseFragment) fragment;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnterAnimationComplete() {
|
||||
super.onEnterAnimationComplete();
|
||||
if (mEnterAnimationPending) {
|
||||
startEnterAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
public void prepareEnterAnimation() {
|
||||
getFragment().prepareEnterAnimation();
|
||||
}
|
||||
|
||||
public void startEnterAnimation() {
|
||||
getFragment().startEnterAnimation();
|
||||
}
|
||||
}
|
||||
|
@@ -45,6 +45,8 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFr
|
||||
|
||||
private FingerprintUiHelper mFingerprintHelper;
|
||||
private boolean mAllowFpAuthentication;
|
||||
protected Button mCancelButton;
|
||||
protected ImageView mFingerprintIcon;
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
@@ -56,14 +58,15 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFr
|
||||
@Override
|
||||
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
mCancelButton = (Button) view.findViewById(R.id.cancelButton);
|
||||
mFingerprintIcon = (ImageView) view.findViewById(R.id.fingerprintIcon);
|
||||
mFingerprintHelper = new FingerprintUiHelper(
|
||||
(ImageView) view.findViewById(R.id.fingerprintIcon),
|
||||
mFingerprintIcon,
|
||||
(TextView) view.findViewById(R.id.errorText), this);
|
||||
boolean showCancelButton = getActivity().getIntent().getBooleanExtra(
|
||||
SHOW_CANCEL_BUTTON, false);
|
||||
Button cancelButton = (Button) view.findViewById(R.id.cancelButton);
|
||||
cancelButton.setVisibility(showCancelButton ? View.VISIBLE : View.GONE);
|
||||
cancelButton.setOnClickListener(new View.OnClickListener() {
|
||||
mCancelButton.setVisibility(showCancelButton ? View.VISIBLE : View.GONE);
|
||||
mCancelButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
getActivity().finish();
|
||||
@@ -100,4 +103,10 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFr
|
||||
@Override
|
||||
public void onFingerprintIconVisibilityChanged(boolean visible) {
|
||||
}
|
||||
|
||||
public void prepareEnterAnimation() {
|
||||
}
|
||||
|
||||
public void startEnterAnimation() {
|
||||
}
|
||||
}
|
||||
|
@@ -19,9 +19,12 @@ package com.android.settings;
|
||||
import android.os.UserHandle;
|
||||
import android.text.TextUtils;
|
||||
import com.android.internal.logging.MetricsLogger;
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
import com.android.internal.widget.LockPatternChecker;
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.internal.widget.TextViewInputDisabler;
|
||||
import com.android.settingslib.animation.AppearAnimationUtils;
|
||||
import com.android.settingslib.animation.DisappearAnimationUtils;
|
||||
|
||||
import android.app.Fragment;
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
@@ -39,11 +42,14 @@ import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.TextView;
|
||||
import android.widget.TextView.OnEditorActionListener;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
|
||||
|
||||
public static class InternalActivity extends ConfirmLockPassword {
|
||||
@@ -89,6 +95,9 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
|
||||
private boolean mIsAlpha;
|
||||
private InputMethodManager mImm;
|
||||
private boolean mUsingFingerprint = false;
|
||||
private AppearAnimationUtils mAppearAnimationUtils;
|
||||
private DisappearAnimationUtils mDisappearAnimationUtils;
|
||||
private boolean mBlockImm;
|
||||
|
||||
// required constructor for fragments
|
||||
public ConfirmLockPasswordFragment() {
|
||||
@@ -144,6 +153,14 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
|
||||
int currentType = mPasswordEntry.getInputType();
|
||||
mPasswordEntry.setInputType(mIsAlpha ? currentType
|
||||
: (InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_PASSWORD));
|
||||
mAppearAnimationUtils = new AppearAnimationUtils(getContext(),
|
||||
220, 2f /* translationScale */, 1f /* delayScale*/,
|
||||
AnimationUtils.loadInterpolator(getContext(),
|
||||
android.R.interpolator.linear_out_slow_in));
|
||||
mDisappearAnimationUtils = new DisappearAnimationUtils(getContext(),
|
||||
110, 1f /* translationScale */,
|
||||
0.5f /* delayScale */, AnimationUtils.loadInterpolator(
|
||||
getContext(), android.R.interpolator.fast_out_linear_in));
|
||||
return view;
|
||||
}
|
||||
|
||||
@@ -162,6 +179,43 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
|
||||
: R.string.lockpassword_invalid_pin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareEnterAnimation() {
|
||||
super.prepareEnterAnimation();
|
||||
mHeaderTextView.setAlpha(0f);
|
||||
mDetailsTextView.setAlpha(0f);
|
||||
mCancelButton.setAlpha(0f);
|
||||
mPasswordEntry.setAlpha(0f);
|
||||
mFingerprintIcon.setAlpha(0f);
|
||||
mBlockImm = true;
|
||||
}
|
||||
|
||||
private View[] getActiveViews() {
|
||||
ArrayList<View> result = new ArrayList<>();
|
||||
result.add(mHeaderTextView);
|
||||
result.add(mDetailsTextView);
|
||||
if (mCancelButton.getVisibility() == View.VISIBLE) {
|
||||
result.add(mCancelButton);
|
||||
}
|
||||
result.add(mPasswordEntry);
|
||||
if (mFingerprintIcon.getVisibility() == View.VISIBLE) {
|
||||
result.add(mFingerprintIcon);
|
||||
}
|
||||
return result.toArray(new View[] {});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startEnterAnimation() {
|
||||
super.startEnterAnimation();
|
||||
mAppearAnimationUtils.startAnimation(getActiveViews(), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mBlockImm = false;
|
||||
resetState();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
@@ -199,9 +253,7 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
|
||||
|
||||
@Override
|
||||
protected void authenticationSucceeded() {
|
||||
Intent intent = new Intent();
|
||||
getActivity().setResult(RESULT_OK, intent);
|
||||
getActivity().finish();
|
||||
startDisappearAnimation(new Intent());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -210,6 +262,7 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
|
||||
}
|
||||
|
||||
private void resetState() {
|
||||
if (mBlockImm) return;
|
||||
mPasswordEntry.setEnabled(true);
|
||||
mPasswordEntryInputDisabler.setInputEnabled(true);
|
||||
if (shouldAutoShowSoftKeyboard()) {
|
||||
@@ -222,7 +275,7 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
|
||||
}
|
||||
|
||||
public void onWindowFocusChanged(boolean hasFocus) {
|
||||
if (!hasFocus) {
|
||||
if (!hasFocus || mBlockImm) {
|
||||
return;
|
||||
}
|
||||
// Post to let window focus logic to finish to allow soft input show/hide properly.
|
||||
@@ -312,11 +365,28 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
|
||||
});
|
||||
}
|
||||
|
||||
private void startDisappearAnimation(final Intent intent) {
|
||||
if (getActivity().getThemeResId() == R.style.Theme_ConfirmDeviceCredentialsDark) {
|
||||
mDisappearAnimationUtils.startAnimation(getActiveViews(), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
getActivity().setResult(RESULT_OK, intent);
|
||||
getActivity().finish();
|
||||
getActivity().overridePendingTransition(
|
||||
R.anim.confirm_credential_close_enter,
|
||||
R.anim.confirm_credential_close_exit);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
getActivity().setResult(RESULT_OK, intent);
|
||||
getActivity().finish();
|
||||
}
|
||||
}
|
||||
|
||||
private void onPasswordChecked(boolean matched, Intent intent, int timeoutMs) {
|
||||
mPasswordEntryInputDisabler.setInputEnabled(true);
|
||||
if (matched) {
|
||||
getActivity().setResult(RESULT_OK, intent);
|
||||
getActivity().finish();
|
||||
startDisappearAnimation(intent);
|
||||
} else {
|
||||
if (timeoutMs > 0) {
|
||||
long deadline = mLockPatternUtils.setLockoutAttemptDeadline(
|
||||
|
@@ -22,10 +22,21 @@ import com.android.internal.widget.LockPatternView;
|
||||
import com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient;
|
||||
import com.android.internal.widget.LockPatternChecker;
|
||||
import com.android.internal.widget.LockPatternView.Cell;
|
||||
import com.android.settingslib.animation.AppearAnimationCreator;
|
||||
import com.android.settingslib.animation.AppearAnimationUtils;
|
||||
import com.android.settingslib.animation.DisappearAnimationUtils;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.Activity;
|
||||
import android.app.Fragment;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffColorFilter;
|
||||
import android.os.CountDownTimer;
|
||||
import android.os.SystemClock;
|
||||
import android.os.AsyncTask;
|
||||
@@ -33,11 +44,16 @@ import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.os.storage.StorageManager;
|
||||
import android.view.MenuItem;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.widget.TextView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -70,7 +86,8 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static class ConfirmLockPatternFragment extends ConfirmDeviceCredentialBaseFragment {
|
||||
public static class ConfirmLockPatternFragment extends ConfirmDeviceCredentialBaseFragment
|
||||
implements AppearAnimationCreator<Object> {
|
||||
|
||||
// how long we wait to clear a wrong pattern
|
||||
private static final int WRONG_PATTERN_CLEAR_TIMEOUT_MS = 2000;
|
||||
@@ -93,6 +110,9 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
|
||||
private CharSequence mHeaderText;
|
||||
private CharSequence mDetailsText;
|
||||
|
||||
private AppearAnimationUtils mAppearAnimationUtils;
|
||||
private DisappearAnimationUtils mDisappearAnimationUtils;
|
||||
|
||||
// required constructor for fragments
|
||||
public ConfirmLockPatternFragment() {
|
||||
|
||||
@@ -144,6 +164,20 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
|
||||
getActivity().finish();
|
||||
}
|
||||
}
|
||||
mAppearAnimationUtils = new AppearAnimationUtils(getContext(),
|
||||
AppearAnimationUtils.DEFAULT_APPEAR_DURATION, 2f /* translationScale */,
|
||||
1.3f /* delayScale */, AnimationUtils.loadInterpolator(
|
||||
getContext(), android.R.interpolator.linear_out_slow_in));
|
||||
mDisappearAnimationUtils = new DisappearAnimationUtils(getContext(),
|
||||
125, 4f /* translationScale */,
|
||||
0.3f /* delayScale */, AnimationUtils.loadInterpolator(
|
||||
getContext(), android.R.interpolator.fast_out_linear_in),
|
||||
new AppearAnimationUtils.RowTranslationScaler() {
|
||||
@Override
|
||||
public float getRowTranslationScale(int row, int numRows) {
|
||||
return (float)(numRows - row) / numRows;
|
||||
}
|
||||
});
|
||||
return view;
|
||||
}
|
||||
|
||||
@@ -187,6 +221,51 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareEnterAnimation() {
|
||||
super.prepareEnterAnimation();
|
||||
mHeaderTextView.setAlpha(0f);
|
||||
mCancelButton.setAlpha(0f);
|
||||
mLockPatternView.setAlpha(0f);
|
||||
mDetailsTextView.setAlpha(0f);
|
||||
mFingerprintIcon.setAlpha(0f);
|
||||
}
|
||||
|
||||
private Object[][] getActiveViews() {
|
||||
ArrayList<ArrayList<Object>> result = new ArrayList<>();
|
||||
result.add(new ArrayList<Object>(Collections.singletonList(mHeaderTextView)));
|
||||
result.add(new ArrayList<Object>(Collections.singletonList(mDetailsTextView)));
|
||||
if (mCancelButton.getVisibility() == View.VISIBLE) {
|
||||
result.add(new ArrayList<Object>(Collections.singletonList(mCancelButton)));
|
||||
}
|
||||
LockPatternView.CellState[][] cellStates = mLockPatternView.getCellStates();
|
||||
for (int i = 0; i < cellStates.length; i++) {
|
||||
ArrayList<Object> row = new ArrayList<>();
|
||||
for (int j = 0; j < cellStates[i].length; j++) {
|
||||
row.add(cellStates[i][j]);
|
||||
}
|
||||
result.add(row);
|
||||
}
|
||||
if (mFingerprintIcon.getVisibility() == View.VISIBLE) {
|
||||
result.add(new ArrayList<Object>(Collections.singletonList(mFingerprintIcon)));
|
||||
}
|
||||
Object[][] resultArr = new Object[result.size()][cellStates[0].length];
|
||||
for (int i = 0; i < result.size(); i++) {
|
||||
ArrayList<Object> row = result.get(i);
|
||||
for (int j = 0; j < row.size(); j++) {
|
||||
resultArr[i][j] = row.get(j);
|
||||
}
|
||||
}
|
||||
return resultArr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startEnterAnimation() {
|
||||
super.startEnterAnimation();
|
||||
mLockPatternView.setAlpha(1f);
|
||||
mAppearAnimationUtils.startAnimation2d(getActiveViews(), null, this);
|
||||
}
|
||||
|
||||
private void updateStage(Stage stage) {
|
||||
switch (stage) {
|
||||
case NeedToUnlock:
|
||||
@@ -242,9 +321,27 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
|
||||
|
||||
@Override
|
||||
protected void authenticationSucceeded() {
|
||||
Intent intent = new Intent();
|
||||
getActivity().setResult(Activity.RESULT_OK, intent);
|
||||
startDisappearAnimation(new Intent());
|
||||
}
|
||||
|
||||
private void startDisappearAnimation(final Intent intent) {
|
||||
if (getActivity().getThemeResId() == R.style.Theme_ConfirmDeviceCredentialsDark) {
|
||||
mLockPatternView.clearPattern();
|
||||
mDisappearAnimationUtils.startAnimation2d(getActiveViews(),
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
getActivity().setResult(RESULT_OK, intent);
|
||||
getActivity().finish();
|
||||
getActivity().overridePendingTransition(
|
||||
R.anim.confirm_credential_close_enter,
|
||||
R.anim.confirm_credential_close_exit);
|
||||
}
|
||||
}, this);
|
||||
} else {
|
||||
getActivity().setResult(RESULT_OK, intent);
|
||||
getActivity().finish();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -357,8 +454,7 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
|
||||
boolean matched, Intent intent, int timeoutMs) {
|
||||
mLockPatternView.setEnabled(true);
|
||||
if (matched) {
|
||||
getActivity().setResult(Activity.RESULT_OK, intent);
|
||||
getActivity().finish();
|
||||
startDisappearAnimation(intent);
|
||||
} else {
|
||||
if (timeoutMs > 0) {
|
||||
long deadline = mLockPatternUtils.setLockoutAttemptDeadline(
|
||||
@@ -394,5 +490,52 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createAnimation(Object obj, long delay,
|
||||
long duration, float translationY, final boolean appearing,
|
||||
Interpolator interpolator,
|
||||
final Runnable finishListener) {
|
||||
if (obj instanceof LockPatternView.CellState) {
|
||||
final LockPatternView.CellState animatedCell = (LockPatternView.CellState) obj;
|
||||
if (appearing) {
|
||||
animatedCell.scale = 0.0f;
|
||||
animatedCell.alpha = 1.0f;
|
||||
}
|
||||
animatedCell.translateY = appearing ? translationY : 0;
|
||||
ValueAnimator animator = ValueAnimator.ofFloat(animatedCell.translateY,
|
||||
appearing ? 0 : translationY);
|
||||
animator.setInterpolator(interpolator);
|
||||
animator.setDuration(duration);
|
||||
animator.setStartDelay(delay);
|
||||
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
|
||||
@Override
|
||||
public void onAnimationUpdate(ValueAnimator animation) {
|
||||
float animatedFraction = animation.getAnimatedFraction();
|
||||
if (appearing) {
|
||||
animatedCell.scale = animatedFraction;
|
||||
} else {
|
||||
animatedCell.alpha = 1 - animatedFraction;
|
||||
}
|
||||
animatedCell.translateY = (float) animation.getAnimatedValue();
|
||||
mLockPatternView.invalidate();
|
||||
}
|
||||
});
|
||||
if (finishListener != null) {
|
||||
animator.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
finishListener.run();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
animator.start();
|
||||
mLockPatternView.invalidate();
|
||||
} else {
|
||||
mAppearAnimationUtils.createAnimation((View) obj, delay, duration, translationY,
|
||||
appearing, interpolator, finishListener);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -18,7 +18,6 @@ package com.android.settings.fingerprint;
|
||||
|
||||
import android.hardware.fingerprint.FingerprintManager;
|
||||
import android.os.CancellationSignal;
|
||||
import android.os.Vibrator;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
@@ -31,8 +30,6 @@ import com.android.settings.R;
|
||||
public class FingerprintUiHelper extends FingerprintManager.AuthenticationCallback {
|
||||
|
||||
private static final long ERROR_TIMEOUT = 1300;
|
||||
private static final long[] FP_ERROR_VIBRATE_PATTERN = new long[] {0, 30, 100, 30};
|
||||
private static final long[] FP_SUCCESS_VIBRATE_PATTERN = new long[] {0, 30};
|
||||
|
||||
private ImageView mIcon;
|
||||
private TextView mErrorTextView;
|
||||
@@ -92,7 +89,7 @@ public class FingerprintUiHelper extends FingerprintManager.AuthenticationCallba
|
||||
|
||||
@Override
|
||||
public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
|
||||
vibrateFingerprintSuccess();
|
||||
mIcon.setImageResource(R.drawable.ic_fingerprint_success);
|
||||
mCallback.onAuthenticated();
|
||||
}
|
||||
|
||||
@@ -101,21 +98,12 @@ public class FingerprintUiHelper extends FingerprintManager.AuthenticationCallba
|
||||
return;
|
||||
}
|
||||
|
||||
vibrateFingerprintError();
|
||||
mIcon.setImageResource(R.drawable.ic_fingerprint_error);
|
||||
mErrorTextView.setText(error);
|
||||
mErrorTextView.removeCallbacks(mResetErrorTextRunnable);
|
||||
mErrorTextView.postDelayed(mResetErrorTextRunnable, ERROR_TIMEOUT);
|
||||
}
|
||||
|
||||
private void vibrateFingerprintError() {
|
||||
mIcon.getContext().getSystemService(Vibrator.class).vibrate(FP_ERROR_VIBRATE_PATTERN, -1);
|
||||
}
|
||||
|
||||
private void vibrateFingerprintSuccess() {
|
||||
mIcon.getContext().getSystemService(Vibrator.class).vibrate(FP_SUCCESS_VIBRATE_PATTERN, -1);
|
||||
}
|
||||
|
||||
private Runnable mResetErrorTextRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
Reference in New Issue
Block a user