blob: 98b31b79ae7805313695d71d6db886fe6eeebf9b [file] [log] [blame]
Adam Cohen9ec871d2012-10-24 19:25:44 -07001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Jim Miller5ecd8112013-01-09 18:50:26 -080016package com.android.keyguard;
Adam Cohen9ec871d2012-10-24 19:25:44 -070017
Adam Cohen70009e42012-10-30 16:48:22 -070018import android.animation.Animator;
Adam Cohen70009e42012-10-30 16:48:22 -070019import android.animation.AnimatorSet;
20import android.animation.ObjectAnimator;
21import android.animation.PropertyValuesHolder;
Adam Cohen9ec871d2012-10-24 19:25:44 -070022import android.content.Context;
23import android.util.AttributeSet;
Adam Cohenf9048cd2012-10-27 16:36:10 -070024import android.view.View;
Adam Cohen70009e42012-10-30 16:48:22 -070025import android.view.animation.AccelerateInterpolator;
26import android.view.animation.DecelerateInterpolator;
27import android.view.animation.Interpolator;
28
Adam Cohen2b0501b2012-11-21 16:49:13 -080029import java.util.ArrayList;
30
Adam Cohen9ec871d2012-10-24 19:25:44 -070031public class KeyguardWidgetCarousel extends KeyguardWidgetPager {
32
33 private float mAdjacentPagesAngle;
Adam Cohenf9048cd2012-10-27 16:36:10 -070034 private static float MAX_SCROLL_PROGRESS = 1.3f;
Adam Cohen9ec871d2012-10-24 19:25:44 -070035 private static float CAMERA_DISTANCE = 10000;
Adam Cohen70009e42012-10-30 16:48:22 -070036 protected AnimatorSet mChildrenTransformsAnimator;
37 float[] mTmpTransform = new float[3];
Adam Cohen9ec871d2012-10-24 19:25:44 -070038
39 public KeyguardWidgetCarousel(Context context, AttributeSet attrs) {
40 this(context, attrs, 0);
41 }
42
43 public KeyguardWidgetCarousel(Context context) {
44 this(context, null, 0);
45 }
46
47 public KeyguardWidgetCarousel(Context context, AttributeSet attrs, int defStyle) {
48 super(context, attrs, defStyle);
49 mAdjacentPagesAngle = context.getResources().getInteger(R.integer.kg_carousel_angle);
50 }
51
52 protected float getMaxScrollProgress() {
Adam Cohenf9048cd2012-10-27 16:36:10 -070053 return MAX_SCROLL_PROGRESS;
54 }
55
Adam Cohen2b0501b2012-11-21 16:49:13 -080056 public float getAlphaForPage(int screenCenter, int index, boolean showSidePages) {
Adam Cohenf9048cd2012-10-27 16:36:10 -070057 View child = getChildAt(index);
58 if (child == null) return 0f;
59
Adam Cohen2b0501b2012-11-21 16:49:13 -080060 boolean inVisibleRange = index >= getNextPage() - 1 && index <= getNextPage() + 1;
Adam Cohenf9048cd2012-10-27 16:36:10 -070061 float scrollProgress = getScrollProgress(screenCenter, child, index);
Adam Cohen2b0501b2012-11-21 16:49:13 -080062
63 if (isOverScrollChild(index, scrollProgress)) {
64 return 1.0f;
65 } else if ((showSidePages && inVisibleRange) || index == getNextPage()) {
Adam Cohenf9048cd2012-10-27 16:36:10 -070066 scrollProgress = getBoundedScrollProgress(screenCenter, child, index);
Adam Cohenab8635d2012-10-30 17:31:32 -070067 float alpha = 1.0f - 1.0f * Math.abs(scrollProgress / MAX_SCROLL_PROGRESS);
Adam Cohenf9048cd2012-10-27 16:36:10 -070068 return alpha;
69 } else {
Adam Cohen2b0501b2012-11-21 16:49:13 -080070 return 0f;
71 }
72 }
73
74 public float getOutlineAlphaForPage(int screenCenter, int index, boolean showSidePages) {
75 boolean inVisibleRange = index >= getNextPage() - 1 && index <= getNextPage() + 1;
76 if (inVisibleRange) {
77 return super.getOutlineAlphaForPage(screenCenter, index, showSidePages);
78 } else {
79 return 0f;
Adam Cohenf9048cd2012-10-27 16:36:10 -070080 }
Adam Cohen9ec871d2012-10-24 19:25:44 -070081 }
82
83 private void updatePageAlphaValues(int screenCenter) {
Adam Cohenf9048cd2012-10-27 16:36:10 -070084 if (mChildrenOutlineFadeAnimation != null) {
85 mChildrenOutlineFadeAnimation.cancel();
86 mChildrenOutlineFadeAnimation = null;
87 }
Adam Cohen2b0501b2012-11-21 16:49:13 -080088 boolean showSidePages = mShowingInitialHints || isPageMoving();
Adam Cohenf9048cd2012-10-27 16:36:10 -070089 if (!isReordering(false)) {
Adam Cohen9ec871d2012-10-24 19:25:44 -070090 for (int i = 0; i < getChildCount(); i++) {
91 KeyguardWidgetFrame child = getWidgetPageAt(i);
92 if (child != null) {
Adam Cohen2b0501b2012-11-21 16:49:13 -080093 float outlineAlpha = getOutlineAlphaForPage(screenCenter, i, showSidePages);
94 float contentAlpha = getAlphaForPage(screenCenter, i,showSidePages);
95 child.setBackgroundAlpha(outlineAlpha);
96 child.setContentAlpha(contentAlpha);
Adam Cohen9ec871d2012-10-24 19:25:44 -070097 }
98 }
99 }
100 }
101
Adam Cohen934d0832012-11-03 20:02:33 -0700102 public void showInitialPageHints() {
Adam Cohen2b0501b2012-11-21 16:49:13 -0800103 mShowingInitialHints = true;
Adam Cohen934d0832012-11-03 20:02:33 -0700104 int count = getChildCount();
105 for (int i = 0; i < count; i++) {
Adam Cohen2b0501b2012-11-21 16:49:13 -0800106 boolean inVisibleRange = i >= getNextPage() - 1 && i <= getNextPage() + 1;
Adam Cohen934d0832012-11-03 20:02:33 -0700107 KeyguardWidgetFrame child = getWidgetPageAt(i);
Adam Cohen2b0501b2012-11-21 16:49:13 -0800108 if (inVisibleRange) {
109 child.setBackgroundAlpha(KeyguardWidgetFrame.OUTLINE_ALPHA_MULTIPLIER);
110 child.setContentAlpha(1f);
111 } else {
112 child.setBackgroundAlpha(0f);
113 child.setContentAlpha(0f);
Adam Cohen934d0832012-11-03 20:02:33 -0700114 }
115 }
116 }
117
Adam Cohen9ec871d2012-10-24 19:25:44 -0700118 @Override
119 protected void screenScrolled(int screenCenter) {
Adam Cohenf9048cd2012-10-27 16:36:10 -0700120 mScreenCenter = screenCenter;
Adam Cohen9ec871d2012-10-24 19:25:44 -0700121 updatePageAlphaValues(screenCenter);
Adam Cohen70009e42012-10-30 16:48:22 -0700122 if (isReordering(false)) return;
Adam Cohen9ec871d2012-10-24 19:25:44 -0700123 for (int i = 0; i < getChildCount(); i++) {
124 KeyguardWidgetFrame v = getWidgetPageAt(i);
Adam Cohenf9048cd2012-10-27 16:36:10 -0700125 float scrollProgress = getScrollProgress(screenCenter, v, i);
Adam Cohen70009e42012-10-30 16:48:22 -0700126 float boundedProgress = getBoundedScrollProgress(screenCenter, v, i);
Adam Cohenf9048cd2012-10-27 16:36:10 -0700127 if (v == mDragView || v == null) continue;
128 v.setCameraDistance(CAMERA_DISTANCE);
129
130 if (isOverScrollChild(i, scrollProgress)) {
131 v.setRotationY(- OVERSCROLL_MAX_ROTATION * scrollProgress);
132 v.setOverScrollAmount(Math.abs(scrollProgress), scrollProgress < 0);
133 } else {
Adam Cohen9ec871d2012-10-24 19:25:44 -0700134 int width = v.getMeasuredWidth();
Adam Cohen70009e42012-10-30 16:48:22 -0700135 float pivotX = (width / 2f) + boundedProgress * (width / 2f);
Adam Cohen9ec871d2012-10-24 19:25:44 -0700136 float pivotY = v.getMeasuredHeight() / 2;
Adam Cohen70009e42012-10-30 16:48:22 -0700137 float rotationY = - mAdjacentPagesAngle * boundedProgress;
Adam Cohen9ec871d2012-10-24 19:25:44 -0700138 v.setPivotX(pivotX);
139 v.setPivotY(pivotY);
140 v.setRotationY(rotationY);
Adam Cohenf9048cd2012-10-27 16:36:10 -0700141 v.setOverScrollAmount(0f, false);
142 }
Adam Cohenf9048cd2012-10-27 16:36:10 -0700143 float alpha = v.getAlpha();
144 // If the view has 0 alpha, we set it to be invisible so as to prevent
145 // it from accepting touches
146 if (alpha == 0) {
147 v.setVisibility(INVISIBLE);
148 } else if (v.getVisibility() != VISIBLE) {
149 v.setVisibility(VISIBLE);
Adam Cohen9ec871d2012-10-24 19:25:44 -0700150 }
151 }
152 }
Adam Cohen70009e42012-10-30 16:48:22 -0700153
154 void animatePagesToNeutral() {
155 if (mChildrenTransformsAnimator != null) {
156 mChildrenTransformsAnimator.cancel();
157 mChildrenTransformsAnimator = null;
158 }
159
160 int count = getChildCount();
161 PropertyValuesHolder alpha;
162 PropertyValuesHolder outlineAlpha;
163 PropertyValuesHolder rotationY;
164 ArrayList<Animator> anims = new ArrayList<Animator>();
165
166 for (int i = 0; i < count; i++) {
167 KeyguardWidgetFrame child = getWidgetPageAt(i);
168 boolean inVisibleRange = (i >= mCurrentPage - 1 && i <= mCurrentPage + 1);
169 if (!inVisibleRange) {
170 child.setRotationY(0f);
171 }
172 alpha = PropertyValuesHolder.ofFloat("contentAlpha", 1.0f);
Adam Cohenab8635d2012-10-30 17:31:32 -0700173 outlineAlpha = PropertyValuesHolder.ofFloat("backgroundAlpha",
174 KeyguardWidgetFrame.OUTLINE_ALPHA_MULTIPLIER);
Adam Cohen70009e42012-10-30 16:48:22 -0700175 rotationY = PropertyValuesHolder.ofFloat("rotationY", 0f);
176 ObjectAnimator a = ObjectAnimator.ofPropertyValuesHolder(child, alpha, outlineAlpha, rotationY);
177 child.setVisibility(VISIBLE);
178 if (!inVisibleRange) {
179 a.setInterpolator(mSlowFadeInterpolator);
180 }
181 anims.add(a);
182 }
183
184 int duration = REORDERING_ZOOM_IN_OUT_DURATION;
185 mChildrenTransformsAnimator = new AnimatorSet();
186 mChildrenTransformsAnimator.playTogether(anims);
187
188 mChildrenTransformsAnimator.setDuration(duration);
189 mChildrenTransformsAnimator.start();
190 }
191
192 private void getTransformForPage(int screenCenter, int index, float[] transform) {
193 View child = getChildAt(index);
194 float boundedProgress = getBoundedScrollProgress(screenCenter, child, index);
195 float rotationY = - mAdjacentPagesAngle * boundedProgress;
196 int width = child.getMeasuredWidth();
197 float pivotX = (width / 2f) + boundedProgress * (width / 2f);
198 float pivotY = child.getMeasuredHeight() / 2;
199
200 transform[0] = pivotX;
201 transform[1] = pivotY;
202 transform[2] = rotationY;
203 }
204
205 Interpolator mFastFadeInterpolator = new Interpolator() {
206 Interpolator mInternal = new DecelerateInterpolator(1.5f);
207 float mFactor = 2.5f;
208 @Override
209 public float getInterpolation(float input) {
210 return mInternal.getInterpolation(Math.min(mFactor * input, 1f));
211 }
212 };
213
214 Interpolator mSlowFadeInterpolator = new Interpolator() {
215 Interpolator mInternal = new AccelerateInterpolator(1.5f);
216 float mFactor = 1.3f;
217 @Override
218 public float getInterpolation(float input) {
219 input -= (1 - 1 / mFactor);
220 input = mFactor * Math.max(input, 0f);
221 return mInternal.getInterpolation(input);
222 }
223 };
224
225 void animatePagesToCarousel() {
226 if (mChildrenTransformsAnimator != null) {
227 mChildrenTransformsAnimator.cancel();
228 mChildrenTransformsAnimator = null;
229 }
230
231 int count = getChildCount();
232 PropertyValuesHolder alpha;
233 PropertyValuesHolder outlineAlpha;
234 PropertyValuesHolder rotationY;
235 PropertyValuesHolder pivotX;
236 PropertyValuesHolder pivotY;
237 ArrayList<Animator> anims = new ArrayList<Animator>();
238
239 for (int i = 0; i < count; i++) {
240 KeyguardWidgetFrame child = getWidgetPageAt(i);
Adam Cohen2b0501b2012-11-21 16:49:13 -0800241 float finalAlpha = getAlphaForPage(mScreenCenter, i, true);
242 float finalOutlineAlpha = getOutlineAlphaForPage(mScreenCenter, i, true);
Adam Cohen70009e42012-10-30 16:48:22 -0700243 getTransformForPage(mScreenCenter, i, mTmpTransform);
244
245 boolean inVisibleRange = (i >= mCurrentPage - 1 && i <= mCurrentPage + 1);
246
247 ObjectAnimator a;
248 alpha = PropertyValuesHolder.ofFloat("contentAlpha", finalAlpha);
Adam Cohenab8635d2012-10-30 17:31:32 -0700249 outlineAlpha = PropertyValuesHolder.ofFloat("backgroundAlpha", finalOutlineAlpha);
Adam Cohen70009e42012-10-30 16:48:22 -0700250 pivotX = PropertyValuesHolder.ofFloat("pivotX", mTmpTransform[0]);
251 pivotY = PropertyValuesHolder.ofFloat("pivotY", mTmpTransform[1]);
252 rotationY = PropertyValuesHolder.ofFloat("rotationY", mTmpTransform[2]);
253
254 if (inVisibleRange) {
255 // for the central pages we animate into a rotated state
256 a = ObjectAnimator.ofPropertyValuesHolder(child, alpha, outlineAlpha,
257 pivotX, pivotY, rotationY);
258 } else {
259 a = ObjectAnimator.ofPropertyValuesHolder(child, alpha, outlineAlpha);
260 a.setInterpolator(mFastFadeInterpolator);
261 }
262 anims.add(a);
263 }
264
265 int duration = REORDERING_ZOOM_IN_OUT_DURATION;
266 mChildrenTransformsAnimator = new AnimatorSet();
267 mChildrenTransformsAnimator.playTogether(anims);
268
269 mChildrenTransformsAnimator.setDuration(duration);
270 mChildrenTransformsAnimator.start();
271 }
272
273 protected void reorderStarting() {
274 mViewStateManager.fadeOutSecurity(REORDERING_ZOOM_IN_OUT_DURATION);
275 animatePagesToNeutral();
276 }
277
278 protected boolean zoomIn(final Runnable onCompleteRunnable) {
279 animatePagesToCarousel();
280 return super.zoomIn(onCompleteRunnable);
281 }
282
283 @Override
284 protected void onEndReordering() {
285 super.onEndReordering();
286 mViewStateManager.fadeInSecurity(REORDERING_ZOOM_IN_OUT_DURATION);
287 }
Adam Cohen9ec871d2012-10-24 19:25:44 -0700288}