blob: 257fd2748b141996aa9ed4b9f4835469db1b45b6 [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 */
16package com.android.internal.policy.impl.keyguard;
17
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 Cohen9ec871d2012-10-24 19:25:44 -070029import com.android.internal.R;
30
Adam Cohen2b0501b2012-11-21 16:49:13 -080031import java.util.ArrayList;
32
Adam Cohen9ec871d2012-10-24 19:25:44 -070033public class KeyguardWidgetCarousel extends KeyguardWidgetPager {
34
35 private float mAdjacentPagesAngle;
Adam Cohenf9048cd2012-10-27 16:36:10 -070036 private static float MAX_SCROLL_PROGRESS = 1.3f;
Adam Cohen9ec871d2012-10-24 19:25:44 -070037 private static float CAMERA_DISTANCE = 10000;
Adam Cohen70009e42012-10-30 16:48:22 -070038 protected AnimatorSet mChildrenTransformsAnimator;
39 float[] mTmpTransform = new float[3];
Adam Cohen9ec871d2012-10-24 19:25:44 -070040
41 public KeyguardWidgetCarousel(Context context, AttributeSet attrs) {
42 this(context, attrs, 0);
43 }
44
45 public KeyguardWidgetCarousel(Context context) {
46 this(context, null, 0);
47 }
48
49 public KeyguardWidgetCarousel(Context context, AttributeSet attrs, int defStyle) {
50 super(context, attrs, defStyle);
51 mAdjacentPagesAngle = context.getResources().getInteger(R.integer.kg_carousel_angle);
52 }
53
54 protected float getMaxScrollProgress() {
Adam Cohenf9048cd2012-10-27 16:36:10 -070055 return MAX_SCROLL_PROGRESS;
56 }
57
Adam Cohen2b0501b2012-11-21 16:49:13 -080058 public float getAlphaForPage(int screenCenter, int index, boolean showSidePages) {
Adam Cohenf9048cd2012-10-27 16:36:10 -070059 View child = getChildAt(index);
60 if (child == null) return 0f;
61
Adam Cohen2b0501b2012-11-21 16:49:13 -080062 boolean inVisibleRange = index >= getNextPage() - 1 && index <= getNextPage() + 1;
Adam Cohenf9048cd2012-10-27 16:36:10 -070063 float scrollProgress = getScrollProgress(screenCenter, child, index);
Adam Cohen2b0501b2012-11-21 16:49:13 -080064
65 if (isOverScrollChild(index, scrollProgress)) {
66 return 1.0f;
67 } else if ((showSidePages && inVisibleRange) || index == getNextPage()) {
Adam Cohenf9048cd2012-10-27 16:36:10 -070068 scrollProgress = getBoundedScrollProgress(screenCenter, child, index);
Adam Cohenab8635d2012-10-30 17:31:32 -070069 float alpha = 1.0f - 1.0f * Math.abs(scrollProgress / MAX_SCROLL_PROGRESS);
Adam Cohenf9048cd2012-10-27 16:36:10 -070070 return alpha;
71 } else {
Adam Cohen2b0501b2012-11-21 16:49:13 -080072 return 0f;
73 }
74 }
75
76 public float getOutlineAlphaForPage(int screenCenter, int index, boolean showSidePages) {
77 boolean inVisibleRange = index >= getNextPage() - 1 && index <= getNextPage() + 1;
78 if (inVisibleRange) {
79 return super.getOutlineAlphaForPage(screenCenter, index, showSidePages);
80 } else {
81 return 0f;
Adam Cohenf9048cd2012-10-27 16:36:10 -070082 }
Adam Cohen9ec871d2012-10-24 19:25:44 -070083 }
84
85 private void updatePageAlphaValues(int screenCenter) {
Adam Cohenf9048cd2012-10-27 16:36:10 -070086 if (mChildrenOutlineFadeAnimation != null) {
87 mChildrenOutlineFadeAnimation.cancel();
88 mChildrenOutlineFadeAnimation = null;
89 }
Adam Cohen2b0501b2012-11-21 16:49:13 -080090 boolean showSidePages = mShowingInitialHints || isPageMoving();
Adam Cohenf9048cd2012-10-27 16:36:10 -070091 if (!isReordering(false)) {
Adam Cohen9ec871d2012-10-24 19:25:44 -070092 for (int i = 0; i < getChildCount(); i++) {
93 KeyguardWidgetFrame child = getWidgetPageAt(i);
94 if (child != null) {
Adam Cohen2b0501b2012-11-21 16:49:13 -080095 float outlineAlpha = getOutlineAlphaForPage(screenCenter, i, showSidePages);
96 float contentAlpha = getAlphaForPage(screenCenter, i,showSidePages);
97 child.setBackgroundAlpha(outlineAlpha);
98 child.setContentAlpha(contentAlpha);
Adam Cohen9ec871d2012-10-24 19:25:44 -070099 }
100 }
101 }
102 }
103
Adam Cohen934d0832012-11-03 20:02:33 -0700104 public void showInitialPageHints() {
Adam Cohen2b0501b2012-11-21 16:49:13 -0800105 mShowingInitialHints = true;
Adam Cohen934d0832012-11-03 20:02:33 -0700106 int count = getChildCount();
107 for (int i = 0; i < count; i++) {
Adam Cohen2b0501b2012-11-21 16:49:13 -0800108 boolean inVisibleRange = i >= getNextPage() - 1 && i <= getNextPage() + 1;
Adam Cohen934d0832012-11-03 20:02:33 -0700109 KeyguardWidgetFrame child = getWidgetPageAt(i);
Adam Cohen2b0501b2012-11-21 16:49:13 -0800110 if (inVisibleRange) {
111 child.setBackgroundAlpha(KeyguardWidgetFrame.OUTLINE_ALPHA_MULTIPLIER);
112 child.setContentAlpha(1f);
113 } else {
114 child.setBackgroundAlpha(0f);
115 child.setContentAlpha(0f);
Adam Cohen934d0832012-11-03 20:02:33 -0700116 }
117 }
118 }
119
Adam Cohen9ec871d2012-10-24 19:25:44 -0700120 @Override
121 protected void screenScrolled(int screenCenter) {
Adam Cohenf9048cd2012-10-27 16:36:10 -0700122 mScreenCenter = screenCenter;
Adam Cohen9ec871d2012-10-24 19:25:44 -0700123 updatePageAlphaValues(screenCenter);
Adam Cohen70009e42012-10-30 16:48:22 -0700124 if (isReordering(false)) return;
Adam Cohen9ec871d2012-10-24 19:25:44 -0700125 for (int i = 0; i < getChildCount(); i++) {
126 KeyguardWidgetFrame v = getWidgetPageAt(i);
Adam Cohenf9048cd2012-10-27 16:36:10 -0700127 float scrollProgress = getScrollProgress(screenCenter, v, i);
Adam Cohen70009e42012-10-30 16:48:22 -0700128 float boundedProgress = getBoundedScrollProgress(screenCenter, v, i);
Adam Cohenf9048cd2012-10-27 16:36:10 -0700129 if (v == mDragView || v == null) continue;
130 v.setCameraDistance(CAMERA_DISTANCE);
131
132 if (isOverScrollChild(i, scrollProgress)) {
133 v.setRotationY(- OVERSCROLL_MAX_ROTATION * scrollProgress);
134 v.setOverScrollAmount(Math.abs(scrollProgress), scrollProgress < 0);
135 } else {
Adam Cohen9ec871d2012-10-24 19:25:44 -0700136 int width = v.getMeasuredWidth();
Adam Cohen70009e42012-10-30 16:48:22 -0700137 float pivotX = (width / 2f) + boundedProgress * (width / 2f);
Adam Cohen9ec871d2012-10-24 19:25:44 -0700138 float pivotY = v.getMeasuredHeight() / 2;
Adam Cohen70009e42012-10-30 16:48:22 -0700139 float rotationY = - mAdjacentPagesAngle * boundedProgress;
Adam Cohen9ec871d2012-10-24 19:25:44 -0700140 v.setPivotX(pivotX);
141 v.setPivotY(pivotY);
142 v.setRotationY(rotationY);
Adam Cohenf9048cd2012-10-27 16:36:10 -0700143 v.setOverScrollAmount(0f, false);
144 }
Adam Cohenf9048cd2012-10-27 16:36:10 -0700145 float alpha = v.getAlpha();
146 // If the view has 0 alpha, we set it to be invisible so as to prevent
147 // it from accepting touches
148 if (alpha == 0) {
149 v.setVisibility(INVISIBLE);
150 } else if (v.getVisibility() != VISIBLE) {
151 v.setVisibility(VISIBLE);
Adam Cohen9ec871d2012-10-24 19:25:44 -0700152 }
153 }
154 }
Adam Cohen70009e42012-10-30 16:48:22 -0700155
156 void animatePagesToNeutral() {
157 if (mChildrenTransformsAnimator != null) {
158 mChildrenTransformsAnimator.cancel();
159 mChildrenTransformsAnimator = null;
160 }
161
162 int count = getChildCount();
163 PropertyValuesHolder alpha;
164 PropertyValuesHolder outlineAlpha;
165 PropertyValuesHolder rotationY;
166 ArrayList<Animator> anims = new ArrayList<Animator>();
167
168 for (int i = 0; i < count; i++) {
169 KeyguardWidgetFrame child = getWidgetPageAt(i);
170 boolean inVisibleRange = (i >= mCurrentPage - 1 && i <= mCurrentPage + 1);
171 if (!inVisibleRange) {
172 child.setRotationY(0f);
173 }
174 alpha = PropertyValuesHolder.ofFloat("contentAlpha", 1.0f);
Adam Cohenab8635d2012-10-30 17:31:32 -0700175 outlineAlpha = PropertyValuesHolder.ofFloat("backgroundAlpha",
176 KeyguardWidgetFrame.OUTLINE_ALPHA_MULTIPLIER);
Adam Cohen70009e42012-10-30 16:48:22 -0700177 rotationY = PropertyValuesHolder.ofFloat("rotationY", 0f);
178 ObjectAnimator a = ObjectAnimator.ofPropertyValuesHolder(child, alpha, outlineAlpha, rotationY);
179 child.setVisibility(VISIBLE);
180 if (!inVisibleRange) {
181 a.setInterpolator(mSlowFadeInterpolator);
182 }
183 anims.add(a);
184 }
185
186 int duration = REORDERING_ZOOM_IN_OUT_DURATION;
187 mChildrenTransformsAnimator = new AnimatorSet();
188 mChildrenTransformsAnimator.playTogether(anims);
189
190 mChildrenTransformsAnimator.setDuration(duration);
191 mChildrenTransformsAnimator.start();
192 }
193
194 private void getTransformForPage(int screenCenter, int index, float[] transform) {
195 View child = getChildAt(index);
196 float boundedProgress = getBoundedScrollProgress(screenCenter, child, index);
197 float rotationY = - mAdjacentPagesAngle * boundedProgress;
198 int width = child.getMeasuredWidth();
199 float pivotX = (width / 2f) + boundedProgress * (width / 2f);
200 float pivotY = child.getMeasuredHeight() / 2;
201
202 transform[0] = pivotX;
203 transform[1] = pivotY;
204 transform[2] = rotationY;
205 }
206
207 Interpolator mFastFadeInterpolator = new Interpolator() {
208 Interpolator mInternal = new DecelerateInterpolator(1.5f);
209 float mFactor = 2.5f;
210 @Override
211 public float getInterpolation(float input) {
212 return mInternal.getInterpolation(Math.min(mFactor * input, 1f));
213 }
214 };
215
216 Interpolator mSlowFadeInterpolator = new Interpolator() {
217 Interpolator mInternal = new AccelerateInterpolator(1.5f);
218 float mFactor = 1.3f;
219 @Override
220 public float getInterpolation(float input) {
221 input -= (1 - 1 / mFactor);
222 input = mFactor * Math.max(input, 0f);
223 return mInternal.getInterpolation(input);
224 }
225 };
226
227 void animatePagesToCarousel() {
228 if (mChildrenTransformsAnimator != null) {
229 mChildrenTransformsAnimator.cancel();
230 mChildrenTransformsAnimator = null;
231 }
232
233 int count = getChildCount();
234 PropertyValuesHolder alpha;
235 PropertyValuesHolder outlineAlpha;
236 PropertyValuesHolder rotationY;
237 PropertyValuesHolder pivotX;
238 PropertyValuesHolder pivotY;
239 ArrayList<Animator> anims = new ArrayList<Animator>();
240
241 for (int i = 0; i < count; i++) {
242 KeyguardWidgetFrame child = getWidgetPageAt(i);
Adam Cohen2b0501b2012-11-21 16:49:13 -0800243 float finalAlpha = getAlphaForPage(mScreenCenter, i, true);
244 float finalOutlineAlpha = getOutlineAlphaForPage(mScreenCenter, i, true);
Adam Cohen70009e42012-10-30 16:48:22 -0700245 getTransformForPage(mScreenCenter, i, mTmpTransform);
246
247 boolean inVisibleRange = (i >= mCurrentPage - 1 && i <= mCurrentPage + 1);
248
249 ObjectAnimator a;
250 alpha = PropertyValuesHolder.ofFloat("contentAlpha", finalAlpha);
Adam Cohenab8635d2012-10-30 17:31:32 -0700251 outlineAlpha = PropertyValuesHolder.ofFloat("backgroundAlpha", finalOutlineAlpha);
Adam Cohen70009e42012-10-30 16:48:22 -0700252 pivotX = PropertyValuesHolder.ofFloat("pivotX", mTmpTransform[0]);
253 pivotY = PropertyValuesHolder.ofFloat("pivotY", mTmpTransform[1]);
254 rotationY = PropertyValuesHolder.ofFloat("rotationY", mTmpTransform[2]);
255
256 if (inVisibleRange) {
257 // for the central pages we animate into a rotated state
258 a = ObjectAnimator.ofPropertyValuesHolder(child, alpha, outlineAlpha,
259 pivotX, pivotY, rotationY);
260 } else {
261 a = ObjectAnimator.ofPropertyValuesHolder(child, alpha, outlineAlpha);
262 a.setInterpolator(mFastFadeInterpolator);
263 }
264 anims.add(a);
265 }
266
267 int duration = REORDERING_ZOOM_IN_OUT_DURATION;
268 mChildrenTransformsAnimator = new AnimatorSet();
269 mChildrenTransformsAnimator.playTogether(anims);
270
271 mChildrenTransformsAnimator.setDuration(duration);
272 mChildrenTransformsAnimator.start();
273 }
274
275 protected void reorderStarting() {
276 mViewStateManager.fadeOutSecurity(REORDERING_ZOOM_IN_OUT_DURATION);
277 animatePagesToNeutral();
278 }
279
280 protected boolean zoomIn(final Runnable onCompleteRunnable) {
281 animatePagesToCarousel();
282 return super.zoomIn(onCompleteRunnable);
283 }
284
285 @Override
286 protected void onEndReordering() {
287 super.onEndReordering();
288 mViewStateManager.fadeInSecurity(REORDERING_ZOOM_IN_OUT_DURATION);
289 }
Adam Cohen9ec871d2012-10-24 19:25:44 -0700290}