• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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  */
16 package com.android.keyguard;
17 
18 import android.animation.Animator;
19 import android.animation.AnimatorSet;
20 import android.animation.ObjectAnimator;
21 import android.animation.PropertyValuesHolder;
22 import android.content.Context;
23 import android.util.AttributeSet;
24 import android.view.View;
25 import android.view.animation.AccelerateInterpolator;
26 import android.view.animation.DecelerateInterpolator;
27 import android.view.animation.Interpolator;
28 
29 import java.util.ArrayList;
30 
31 public class KeyguardWidgetCarousel extends KeyguardWidgetPager {
32 
33     private float mAdjacentPagesAngle;
34     private static float MAX_SCROLL_PROGRESS = 1.3f;
35     private static float CAMERA_DISTANCE = 10000;
36     protected AnimatorSet mChildrenTransformsAnimator;
37     float[] mTmpTransform = new float[3];
38 
KeyguardWidgetCarousel(Context context, AttributeSet attrs)39     public KeyguardWidgetCarousel(Context context, AttributeSet attrs) {
40         this(context, attrs, 0);
41     }
42 
KeyguardWidgetCarousel(Context context)43     public KeyguardWidgetCarousel(Context context) {
44         this(context, null, 0);
45     }
46 
KeyguardWidgetCarousel(Context context, AttributeSet attrs, int defStyle)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 
getMaxScrollProgress()52     protected float getMaxScrollProgress() {
53         return MAX_SCROLL_PROGRESS;
54     }
55 
getAlphaForPage(int screenCenter, int index, boolean showSidePages)56     public float getAlphaForPage(int screenCenter, int index, boolean showSidePages) {
57         View child = getChildAt(index);
58         if (child == null) return 0f;
59 
60         boolean inVisibleRange = index >= getNextPage() - 1 && index <= getNextPage() + 1;
61         float scrollProgress = getScrollProgress(screenCenter, child, index);
62 
63         if (isOverScrollChild(index, scrollProgress)) {
64             return 1.0f;
65         } else if ((showSidePages && inVisibleRange) || index == getNextPage()) {
66             scrollProgress = getBoundedScrollProgress(screenCenter, child, index);
67             float alpha = 1.0f - 1.0f * Math.abs(scrollProgress / MAX_SCROLL_PROGRESS);
68             return alpha;
69         } else {
70             return 0f;
71         }
72     }
73 
getOutlineAlphaForPage(int screenCenter, int index, boolean showSidePages)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;
80         }
81     }
82 
updatePageAlphaValues(int screenCenter)83     private void updatePageAlphaValues(int screenCenter) {
84         if (mChildrenOutlineFadeAnimation != null) {
85             mChildrenOutlineFadeAnimation.cancel();
86             mChildrenOutlineFadeAnimation = null;
87         }
88         boolean showSidePages = mShowingInitialHints || isPageMoving();
89         if (!isReordering(false)) {
90             for (int i = 0; i < getChildCount(); i++) {
91                 KeyguardWidgetFrame child = getWidgetPageAt(i);
92                 if (child != null) {
93                     float outlineAlpha = getOutlineAlphaForPage(screenCenter, i, showSidePages);
94                     float contentAlpha = getAlphaForPage(screenCenter, i,showSidePages);
95                     child.setBackgroundAlpha(outlineAlpha);
96                     child.setContentAlpha(contentAlpha);
97                 }
98             }
99         }
100     }
101 
showInitialPageHints()102     public void showInitialPageHints() {
103         mShowingInitialHints = true;
104         int count = getChildCount();
105         for (int i = 0; i < count; i++) {
106             boolean inVisibleRange = i >= getNextPage() - 1 && i <= getNextPage() + 1;
107             KeyguardWidgetFrame child = getWidgetPageAt(i);
108             if (inVisibleRange) {
109                 child.setBackgroundAlpha(KeyguardWidgetFrame.OUTLINE_ALPHA_MULTIPLIER);
110                 child.setContentAlpha(1f);
111             } else {
112                 child.setBackgroundAlpha(0f);
113                 child.setContentAlpha(0f);
114             }
115         }
116     }
117 
118     @Override
screenScrolled(int screenCenter)119     protected void screenScrolled(int screenCenter) {
120         mScreenCenter = screenCenter;
121         updatePageAlphaValues(screenCenter);
122         if (isReordering(false)) return;
123         for (int i = 0; i < getChildCount(); i++) {
124             KeyguardWidgetFrame v = getWidgetPageAt(i);
125             float scrollProgress = getScrollProgress(screenCenter, v, i);
126             float boundedProgress = getBoundedScrollProgress(screenCenter, v, i);
127             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 {
134                 int width = v.getMeasuredWidth();
135                 float pivotX = (width / 2f) + boundedProgress * (width / 2f);
136                 float pivotY = v.getMeasuredHeight() / 2;
137                 float rotationY = - mAdjacentPagesAngle * boundedProgress;
138                 v.setPivotX(pivotX);
139                 v.setPivotY(pivotY);
140                 v.setRotationY(rotationY);
141                 v.setOverScrollAmount(0f, false);
142             }
143             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);
150             }
151         }
152     }
153 
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);
173             outlineAlpha = PropertyValuesHolder.ofFloat("backgroundAlpha",
174                     KeyguardWidgetFrame.OUTLINE_ALPHA_MULTIPLIER);
175             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);
241             float finalAlpha = getAlphaForPage(mScreenCenter, i, true);
242             float finalOutlineAlpha = getOutlineAlphaForPage(mScreenCenter, i, true);
243             getTransformForPage(mScreenCenter, i, mTmpTransform);
244 
245             boolean inVisibleRange = (i >= mCurrentPage - 1 && i <= mCurrentPage + 1);
246 
247             ObjectAnimator a;
248             alpha = PropertyValuesHolder.ofFloat("contentAlpha", finalAlpha);
249             outlineAlpha = PropertyValuesHolder.ofFloat("backgroundAlpha", finalOutlineAlpha);
250             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     }
288 }
289