android:id="@+id/keyguard_host_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:orientation="horizontal">
+ android:orientation="horizontal"
+ android:clipChildren="false"
+ android:clipToPadding="false">
<com.android.keyguard.MultiPaneChallengeLayout
android:id="@+id/multi_pane_challenge"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
- android:clipChildren="false">
+ android:clipChildren="false"
+ android:clipToPadding="false">
<include layout="@layout/keyguard_widget_remove_drop_target"
android:id="@+id/keyguard_widget_pager_delete_target"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
+ android:clipChildren="false"
+ android:clipToPadding="false"
android:orientation="vertical">
<com.android.keyguard.SlidingChallengeLayout
android:id="@+id/sliding_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:clipChildren="false">
+ android:clipChildren="false"
+ android:clipToPadding="false">
<FrameLayout
android:layout_width="match_parent"
android:id="@+id/keyguard_host_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:orientation="horizontal">
+ android:orientation="horizontal"
+ android:clipChildren="false"
+ android:clipToPadding="false">
<com.android.keyguard.MultiPaneChallengeLayout
android:id="@+id/multi_pane_challenge"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
+ android:clipToPadding="false"
android:orientation="vertical">
<include layout="@layout/keyguard_widget_remove_drop_target"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/transparent"
+ android:clipChildren="false"
+ android:clipToPadding="false"
android:fitsSystemWindows="true">
<include
style="@style/BouncerSecurityContainer"
layout="@layout/keyguard_simple_host_view"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
+ android:layout_height="wrap_content" />
</FrameLayout>
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:clipChildren="false"
+ android:clipToPadding="false"
androidprv:layout_maxWidth="@dimen/keyguard_security_width"
androidprv:layout_maxHeight="@dimen/keyguard_security_height"
android:gravity="center_horizontal"
<FrameLayout
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="match_parent"
+ android:clipChildren="false"
+ android:clipToPadding="false">
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:orientation="vertical"
- android:layout_gravity="center_horizontal|bottom">
+ android:layout_gravity="center_horizontal|bottom"
+ android:clipChildren="false"
+ android:clipToPadding="false">
<include layout="@layout/keyguard_message_area"
android:layout_width="match_parent"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
+ android:clipChildren="false"
+ android:clipToPadding="false"
>
<com.android.internal.widget.LockPatternView
android:id="@+id/lockPatternView"
android:layout_marginStart="8dip"
android:layout_gravity="center_horizontal"
android:gravity="center"
- android:contentDescription="@string/keyguard_accessibility_pattern_area" />
+ android:contentDescription="@string/keyguard_accessibility_pattern_area"
+ android:clipChildren="false"
+ android:clipToPadding="false" />
</FrameLayout>
<include layout="@layout/keyguard_eca"
android:id="@+id/keyguard_selector_fade_container"
xmlns:androidprv="http://schemas.android.com/apk/res-auto"
android:id="@+id/keyguard_host_view"
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="match_parent"
+ android:clipChildren="false"
+ android:clipToPadding="false">
<com.android.keyguard.KeyguardSecurityContainer
android:id="@+id/keyguard_security_container"
*/
public interface AppearAnimationCreator<T> {
void createAnimation(T animatedObject, long delay, long duration,
- float startTranslationY, Interpolator interpolator, Runnable finishListener);
+ float translationY, boolean appearing, Interpolator interpolator,
+ Runnable finishListener);
}
private final Interpolator mInterpolator;
private final float mStartTranslation;
private final AppearAnimationProperties mProperties = new AppearAnimationProperties();
- private final float mDelayScale;
+ protected final float mDelayScale;
private final long mDuration;
+ protected boolean mScaleTranslationWithRow;
+ protected boolean mAppearing;
public AppearAnimationUtils(Context ctx) {
this(ctx, DEFAULT_APPEAR_DURATION,
R.dimen.appear_y_translation_start) * translationScaleFactor;
mDelayScale = delayScaleFactor;
mDuration = duration;
+ mScaleTranslationWithRow = false;
+ mAppearing = true;
}
- public void startAppearAnimation(View[][] objects, final Runnable finishListener) {
- startAppearAnimation(objects, finishListener, this);
+ public void startAnimation(View[][] objects, final Runnable finishListener) {
+ startAnimation(objects, finishListener, this);
}
- public void startAppearAnimation(View[] objects, final Runnable finishListener) {
- startAppearAnimation(objects, finishListener, this);
+ public void startAnimation(View[] objects, final Runnable finishListener) {
+ startAnimation(objects, finishListener, this);
}
- public <T> void startAppearAnimation(T[][] objects, final Runnable finishListener,
+ public <T> void startAnimation(T[][] objects, final Runnable finishListener,
AppearAnimationCreator<T> creator) {
AppearAnimationProperties properties = getDelays(objects);
startAnimations(properties, objects, finishListener, creator);
}
- public <T> void startAppearAnimation(T[] objects, final Runnable finishListener,
+ public <T> void startAnimation(T[] objects, final Runnable finishListener,
AppearAnimationCreator<T> creator) {
AppearAnimationProperties properties = getDelays(objects);
startAnimations(properties, objects, finishListener, creator);
endRunnable = finishListener;
}
creator.createAnimation(objects[row], delay, mDuration,
- mStartTranslation, mInterpolator, endRunnable);
+ mStartTranslation, true /* appearing */, mInterpolator, endRunnable);
}
}
}
for (int row = 0; row < properties.delays.length; row++) {
long[] columns = properties.delays[row];
+ float translation = mScaleTranslationWithRow
+ ? (float) (Math.pow((properties.delays.length - row), 2)
+ / properties.delays.length * mStartTranslation)
+ : mStartTranslation;
for (int col = 0; col < columns.length; col++) {
long delay = columns[col];
Runnable endRunnable = null;
endRunnable = finishListener;
}
creator.createAnimation(objects[row][col], delay, mDuration,
- mStartTranslation, mInterpolator, endRunnable);
+ mAppearing ? translation : -translation,
+ mAppearing, mInterpolator, endRunnable);
}
}
}
return mProperties;
}
- private long calculateDelay(int row, int col) {
+ protected long calculateDelay(int row, int col) {
return (long) ((row * 40 + col * (Math.pow(row, 0.4) + 0.4) * 20) * mDelayScale);
}
}
@Override
- public void createAnimation(View view, long delay, long duration, float startTranslationY,
- Interpolator interpolator, Runnable endRunnable) {
+ public void createAnimation(View view, long delay, long duration, float translationY,
+ boolean appearing, Interpolator interpolator, Runnable endRunnable) {
if (view != null) {
- view.setAlpha(0f);
- view.setTranslationY(startTranslationY);
+ view.setAlpha(appearing ? 0f : 1.0f);
+ view.setTranslationY(appearing ? translationY : 0);
view.animate()
- .alpha(1f)
- .translationY(0)
+ .alpha(appearing ? 1f : 0f)
+ .translationY(appearing ? 0 : translationY)
.setInterpolator(interpolator)
.setDuration(duration)
.setStartDelay(delay);
--- /dev/null
+/*
+ * Copyright (C) 2014 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.keyguard;
+
+import android.content.Context;
+import android.view.View;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
+
+/**
+ * A class to make nice disappear transitions for views in a tabular layout.
+ */
+public class DisappearAnimationUtils extends AppearAnimationUtils {
+
+ public DisappearAnimationUtils(Context ctx) {
+ this(ctx, DEFAULT_APPEAR_DURATION,
+ 1.0f, 1.0f,
+ AnimationUtils.loadInterpolator(ctx, android.R.interpolator.linear_out_slow_in));
+ }
+
+ public DisappearAnimationUtils(Context ctx, long duration, float translationScaleFactor,
+ float delayScaleFactor, Interpolator interpolator) {
+ super(ctx, duration, translationScaleFactor, delayScaleFactor, interpolator);
+ mScaleTranslationWithRow = true;
+ mAppearing = false;
+ }
+
+ protected long calculateDelay(int row, int col) {
+ return (long) ((row * 60 + col * (Math.pow(row, 0.4) + 0.4) * 10) * mDelayScale);
+ }
+}
public class KeyguardPINView extends KeyguardPinBasedInputView {
private final AppearAnimationUtils mAppearAnimationUtils;
+ private final DisappearAnimationUtils mDisappearAnimationUtils;
private ViewGroup mKeyguardBouncerFrame;
private ViewGroup mRow0;
private ViewGroup mRow1;
private ViewGroup mRow3;
private View mDivider;
private int mDisappearYTranslation;
+ private View[][] mViews;
public KeyguardPINView(Context context) {
this(context, null);
public KeyguardPINView(Context context, AttributeSet attrs) {
super(context, attrs);
mAppearAnimationUtils = new AppearAnimationUtils(context);
+ mDisappearAnimationUtils = new DisappearAnimationUtils(context,
+ 125, 0.6f /* translationScale */,
+ 0.6f /* delayScale */, AnimationUtils.loadInterpolator(
+ mContext, android.R.interpolator.fast_out_linear_in));
mDisappearYTranslation = getResources().getDimensionPixelSize(
R.dimen.disappear_y_translation);
}
mRow2 = (ViewGroup) findViewById(R.id.row2);
mRow3 = (ViewGroup) findViewById(R.id.row3);
mDivider = findViewById(R.id.divider);
+ mViews = new View[][]{
+ new View[]{
+ mRow0, null, null
+ },
+ new View[]{
+ findViewById(R.id.key1), findViewById(R.id.key2),
+ findViewById(R.id.key3)
+ },
+ new View[]{
+ findViewById(R.id.key4), findViewById(R.id.key5),
+ findViewById(R.id.key6)
+ },
+ new View[]{
+ findViewById(R.id.key7), findViewById(R.id.key8),
+ findViewById(R.id.key9)
+ },
+ new View[]{
+ null, findViewById(R.id.key0), findViewById(R.id.key_enter)
+ },
+ new View[]{
+ null, mEcaView, null
+ }};
}
@Override
.setDuration(500)
.setInterpolator(mAppearAnimationUtils.getInterpolator())
.translationY(0);
- mAppearAnimationUtils.startAppearAnimation(new View[][] {
- new View[] {
- mRow0, null, null
- },
- new View[] {
- findViewById(R.id.key1), findViewById(R.id.key2), findViewById(R.id.key3)
- },
- new View[] {
- findViewById(R.id.key4), findViewById(R.id.key5), findViewById(R.id.key6)
- },
- new View[] {
- findViewById(R.id.key7), findViewById(R.id.key8), findViewById(R.id.key9)
- },
- new View[] {
- null, findViewById(R.id.key0), findViewById(R.id.key_enter)
- },
- new View[] {
- null, mEcaView, null
- }},
+ mAppearAnimationUtils.startAnimation(mViews,
new Runnable() {
@Override
public void run() {
}
@Override
- public boolean startDisappearAnimation(Runnable finishRunnable) {
+ public boolean startDisappearAnimation(final Runnable finishRunnable) {
+ enableClipping(false);
+ setTranslationY(0);
animate()
- .alpha(0f)
- .translationY(mDisappearYTranslation)
- .setInterpolator(AnimationUtils
- .loadInterpolator(mContext, android.R.interpolator.fast_out_linear_in))
- .setDuration(100)
- .withEndAction(finishRunnable);
+ .setDuration(280)
+ .setInterpolator(mDisappearAnimationUtils.getInterpolator())
+ .translationY(mDisappearYTranslation);
+ mDisappearAnimationUtils.startAnimation(mViews,
+ new Runnable() {
+ @Override
+ public void run() {
+ enableClipping(true);
+ if (finishRunnable != null) {
+ finishRunnable.run();
+ }
+ }
+ });
return true;
}
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private final AppearAnimationUtils mAppearAnimationUtils;
+ private final DisappearAnimationUtils mDisappearAnimationUtils;
private CountDownTimer mCountdownTimer = null;
private LockPatternUtils mLockPatternUtils;
super(context, attrs);
mKeyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
mAppearAnimationUtils = new AppearAnimationUtils(context,
- AppearAnimationUtils.DEFAULT_APPEAR_DURATION, 1.5f /* delayScale */,
- 2.0f /* transitionScale */, AnimationUtils.loadInterpolator(
+ AppearAnimationUtils.DEFAULT_APPEAR_DURATION, 1.5f /* translationScale */,
+ 2.0f /* delayScale */, AnimationUtils.loadInterpolator(
mContext, android.R.interpolator.linear_out_slow_in));
+ mDisappearAnimationUtils = new DisappearAnimationUtils(context,
+ 125, 1.2f /* translationScale */,
+ 0.8f /* delayScale */, AnimationUtils.loadInterpolator(
+ mContext, android.R.interpolator.fast_out_linear_in));
mDisappearYTranslation = getResources().getDimensionPixelSize(
R.dimen.disappear_y_translation);
}
.setDuration(500)
.setInterpolator(mAppearAnimationUtils.getInterpolator())
.translationY(0);
- mAppearAnimationUtils.startAppearAnimation(
+ mAppearAnimationUtils.startAnimation(
mLockPatternView.getCellStates(),
new Runnable() {
@Override
mAppearAnimationUtils.createAnimation(mHelpMessage, 0,
AppearAnimationUtils.DEFAULT_APPEAR_DURATION,
mAppearAnimationUtils.getStartTranslation(),
+ true /* appearing */,
mAppearAnimationUtils.getInterpolator(),
null /* finishRunnable */);
}
}
@Override
- public boolean startDisappearAnimation(Runnable finishRunnable) {
+ public boolean startDisappearAnimation(final Runnable finishRunnable) {
mLockPatternView.clearPattern();
+ enableClipping(false);
+ setTranslationY(0);
animate()
- .alpha(0f)
- .translationY(mDisappearYTranslation)
- .setInterpolator(AnimationUtils.loadInterpolator(
- mContext, android.R.interpolator.fast_out_linear_in))
- .setDuration(100)
- .withEndAction(finishRunnable);
+ .setDuration(300)
+ .setInterpolator(mDisappearAnimationUtils.getInterpolator())
+ .translationY(-mDisappearAnimationUtils.getStartTranslation());
+ mDisappearAnimationUtils.startAnimation(mLockPatternView.getCellStates(),
+ new Runnable() {
+ @Override
+ public void run() {
+ enableClipping(true);
+ if (finishRunnable != null) {
+ finishRunnable.run();
+ }
+ }
+ }, KeyguardPatternView.this);
+ if (!TextUtils.isEmpty(mHelpMessage.getText())) {
+ mDisappearAnimationUtils.createAnimation(mHelpMessage, 0,
+ 200,
+ - mDisappearAnimationUtils.getStartTranslation() * 3,
+ false /* appearing */,
+ mDisappearAnimationUtils.getInterpolator(),
+ null /* finishRunnable */);
+ }
return true;
}
@Override
public void createAnimation(final LockPatternView.CellState animatedCell, long delay,
- long duration, float startTranslationY, Interpolator interpolator,
+ long duration, float translationY, final boolean appearing,
+ Interpolator interpolator,
final Runnable finishListener) {
- animatedCell.scale = 0.0f;
- animatedCell.translateY = startTranslationY;
- ValueAnimator animator = ValueAnimator.ofFloat(startTranslationY, 0.0f);
+ if (appearing) {
+ animatedCell.scale = 0.0f;
+ }
+ animatedCell.translateY = appearing ? translationY : 0;
+ ValueAnimator animator = ValueAnimator.ofFloat(animatedCell.translateY,
+ appearing ? 0 : translationY);
animator.setInterpolator(interpolator);
animator.setDuration(duration);
animator.setStartDelay(delay);
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float animatedFraction = animation.getAnimatedFraction();
- animatedCell.scale = animatedFraction;
+ if (appearing) {
+ animatedCell.scale = animatedFraction;
+ } else {
+ animatedCell.alpha = 1 - animatedFraction;
+ }
animatedCell.translateY = (float) animation.getAnimatedValue();
mLockPatternView.invalidate();
}
});
// Also animate the Emergency call
- mAppearAnimationUtils.createAnimation(mEcaView, delay, duration, startTranslationY,
- interpolator, null);
+ mAppearAnimationUtils.createAnimation(mEcaView, delay, duration, translationY,
+ appearing, interpolator, null);
}
animator.start();
mLockPatternView.invalidate();
}
mUserSwitcher.setClipChildren(false);
mUserSwitcher.setClipToPadding(false);
- mAppearAnimationUtils.startAppearAnimation(objects, new Runnable() {
+ mAppearAnimationUtils.startAnimation(objects, new Runnable() {
@Override
public void run() {
mUserSwitcher.setClipChildren(true);