Merge "Appear animation for PIN view." into lmp-preview-dev

This commit is contained in:
Jorim Jaggi
2014-05-28 15:34:33 +00:00
committed by Android (Google) Code Review
4 changed files with 187 additions and 25 deletions

View File

@@ -41,28 +41,16 @@
android:layout_weight="1"
android:layoutDirection="ltr"
>
<LinearLayout
<RelativeLayout
android:id="@+id/row0"
android:layout_width="match_parent"
android:layout_height="0dp"
android:orientation="horizontal"
android:layout_weight="1"
>
<TextView android:id="@+id/pinEntry"
android:editable="true"
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:layout_marginStart="@dimen/keyguard_lockscreen_pin_margin_left"
android:singleLine="true"
android:cursorVisible="false"
android:background="@null"
android:textAppearance="@style/TextAppearance.NumPadKey"
android:imeOptions="flagForceAscii|actionDone"
/>
<ImageButton android:id="@+id/delete_button"
<ImageButton android:id="@+id/delete_button"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentEnd="true"
android:gravity="center_vertical"
android:src="@drawable/ic_input_delete"
android:clickable="true"
@@ -73,13 +61,30 @@
android:background="?android:attr/selectableItemBackground"
android:contentDescription="@string/keyboardview_keycode_delete"
/>
</LinearLayout>
<View
android:layout_width="wrap_content"
android:layout_height="1dp"
android:background="#55FFFFFF"
/>
<TextView android:id="@+id/pinEntry"
android:editable="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_toStartOf="@+id/delete_button"
android:layout_alignParentStart="true"
android:gravity="center"
android:layout_marginStart="@dimen/keyguard_lockscreen_pin_margin_left"
android:singleLine="true"
android:cursorVisible="false"
android:background="@null"
android:textAppearance="@style/TextAppearance.NumPadKey"
android:imeOptions="flagForceAscii|actionDone"
/>
<View
android:id="@+id/divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_alignParentBottom="true"
android:background="#55FFFFFF"
/>
</RelativeLayout>
<LinearLayout
android:id="@+id/row1"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
@@ -114,6 +119,7 @@
/>
</LinearLayout>
<LinearLayout
android:id="@+id/row2"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
@@ -148,6 +154,7 @@
/>
</LinearLayout>
<LinearLayout
android:id="@+id/row3"
android:layout_width="match_parent"
android:layout_height="0dp"
android:orientation="horizontal"
@@ -182,6 +189,7 @@
/>
</LinearLayout>
<LinearLayout
android:id="@+id/row4"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"

View File

@@ -161,4 +161,6 @@
<dimen name="widget_big_font_size">68dp</dimen>
<dimen name="big_font_size">120dp</dimen>
<!-- The y translation to apply at the start in appear animations. -->
<dimen name="appear_y_translation_start">24dp</dimen>
</resources>

View File

@@ -0,0 +1,99 @@
/*
* 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.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.TimeInterpolator;
import android.content.Context;
import android.view.View;
import android.view.ViewPropertyAnimator;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
/**
* A class to make nice appear transitions for views in a tabular layout.
*/
public class AppearAnimationUtils {
public static final long APPEAR_DURATION = 220;
private final Interpolator mLinearOutSlowIn;
private final float mStartTranslation;
public AppearAnimationUtils(Context ctx) {
mLinearOutSlowIn = AnimationUtils.loadInterpolator(
ctx, android.R.interpolator.linear_out_slow_in);
mStartTranslation =
ctx.getResources().getDimensionPixelOffset(R.dimen.appear_y_translation_start);
}
public void startAppearAnimation(View[][] views, final Runnable finishListener) {
long maxDelay = 0;
ViewPropertyAnimator maxDelayAnimator = null;
for (int row = 0; row < views.length; row++) {
View[] columns = views[row];
for (int col = 0; col < columns.length; col++) {
long delay = calculateDelay(row, col);
ViewPropertyAnimator animator = startAppearAnimation(columns[col], delay);
if (animator != null && delay > maxDelay) {
maxDelay = delay;
maxDelayAnimator = animator;
}
}
}
if (maxDelayAnimator != null) {
maxDelayAnimator.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
finishListener.run();
}
});
} else {
finishListener.run();
}
}
private ViewPropertyAnimator startAppearAnimation(View view, long delay) {
if (view == null) return null;
view.setAlpha(0f);
view.setTranslationY(mStartTranslation);
view.animate()
.alpha(1f)
.translationY(0)
.setInterpolator(mLinearOutSlowIn)
.setDuration(APPEAR_DURATION)
.setStartDelay(delay)
.setListener(null);
if (view.hasOverlappingRendering()) {
view.animate().withLayer();
}
return view.animate();
}
private long calculateDelay(int row, int col) {
return (long) (row * 40 + col * (Math.pow(row, 0.4) + 0.4) * 20);
}
public TimeInterpolator getInterpolator() {
return mLinearOutSlowIn;
}
public float getStartTranslation() {
return mStartTranslation;
}
}

View File

@@ -22,6 +22,7 @@ import android.text.TextWatcher;
import android.text.method.DigitsKeyListener;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView.OnEditorActionListener;
/**
@@ -30,12 +31,21 @@ import android.widget.TextView.OnEditorActionListener;
public class KeyguardPINView extends KeyguardAbsKeyInputView
implements KeyguardSecurityView, OnEditorActionListener, TextWatcher {
private final AppearAnimationUtils mAppearAnimationUtils;
private ViewGroup mKeyguardBouncerFrame;
private ViewGroup mRow0;
private ViewGroup mRow1;
private ViewGroup mRow2;
private ViewGroup mRow3;
private View mDivider;
public KeyguardPINView(Context context) {
this(context, null);
}
public KeyguardPINView(Context context, AttributeSet attrs) {
super(context, attrs);
mAppearAnimationUtils = new AppearAnimationUtils(context);
}
protected void resetState() {
@@ -56,6 +66,12 @@ public class KeyguardPINView extends KeyguardAbsKeyInputView
protected void onFinishInflate() {
super.onFinishInflate();
mKeyguardBouncerFrame = (ViewGroup) findViewById(R.id.keyguard_bouncer_frame);
mRow0 = (ViewGroup) findViewById(R.id.row0);
mRow1 = (ViewGroup) findViewById(R.id.row1);
mRow2 = (ViewGroup) findViewById(R.id.row2);
mRow3 = (ViewGroup) findViewById(R.id.row3);
mDivider = findViewById(R.id.divider);
final View ok = findViewById(R.id.key_enter);
if (ok != null) {
ok.setOnClickListener(new View.OnClickListener() {
@@ -117,8 +133,45 @@ public class KeyguardPINView extends KeyguardAbsKeyInputView
@Override
public void startAppearAnimation() {
// TODO: Fancy animation.
setAlpha(0);
animate().alpha(1).withLayer().setDuration(200);
enableClipping(false);
setTranslationY(mAppearAnimationUtils.getStartTranslation());
animate()
.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
}},
new Runnable() {
@Override
public void run() {
enableClipping(true);
}
});
}
private void enableClipping(boolean enable) {
mKeyguardBouncerFrame.setClipToPadding(enable);
mKeyguardBouncerFrame.setClipChildren(enable);
mRow1.setClipToPadding(enable);
mRow2.setClipToPadding(enable);
mRow3.setClipToPadding(enable);
setClipChildren(enable);
}
}