blob: 70beac8ea522f3463dc15e142c5bfe3ad85aa9a7 [file] [log] [blame]
Jorim Jaggi7d16bb12014-05-22 04:24:50 +02001/*
2 * Copyright (C) 2014 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
17package com.android.systemui.statusbar.phone;
18
19import android.content.res.Resources;
20import android.graphics.Path;
Selim Cinekf99d0002014-06-13 07:36:01 +020021import android.view.animation.AccelerateInterpolator;
Jorim Jaggi7d16bb12014-05-22 04:24:50 +020022import android.view.animation.PathInterpolator;
23
24import com.android.systemui.R;
25
26/**
27 * Utility class to calculate the clock position and top padding of notifications on Keyguard.
28 */
29public class KeyguardClockPositionAlgorithm {
30
31 private static final float SLOW_DOWN_FACTOR = 0.4f;
32
33 private static final float CLOCK_RUBBERBAND_FACTOR_MIN = 0.08f;
34 private static final float CLOCK_RUBBERBAND_FACTOR_MAX = 0.8f;
Selim Cinekf99d0002014-06-13 07:36:01 +020035 private static final float CLOCK_SCALE_FADE_START = 0.95f;
36 private static final float CLOCK_SCALE_FADE_END = 0.75f;
37 private static final float CLOCK_SCALE_FADE_END_NO_NOTIFS = 0.5f;
38
Jorim Jaggi7d16bb12014-05-22 04:24:50 +020039 private static final float CLOCK_ADJ_TOP_PADDING_MULTIPLIER_MIN = 1.4f;
40 private static final float CLOCK_ADJ_TOP_PADDING_MULTIPLIER_MAX = 3.2f;
41
42 private int mClockNotificationsMarginMin;
43 private int mClockNotificationsMarginMax;
44 private float mClockYFractionMin;
45 private float mClockYFractionMax;
46 private int mMaxKeyguardNotifications;
47 private int mMaxPanelHeight;
48 private float mExpandedHeight;
49 private int mNotificationCount;
50 private int mHeight;
51 private int mKeyguardStatusHeight;
Jorim Jaggi48bc36a2014-07-25 23:16:04 +020052 private float mEmptyDragAmount;
53 private float mDensity;
Jorim Jaggi7d16bb12014-05-22 04:24:50 +020054
55 /**
56 * The number (fractional) of notifications the "more" card counts when calculating how many
57 * notifications are currently visible for the y positioning of the clock.
58 */
59 private float mMoreCardNotificationAmount;
60
61 private static final PathInterpolator sSlowDownInterpolator;
62
63 static {
64 Path path = new Path();
65 path.moveTo(0, 0);
66 path.cubicTo(0.3f, 0.875f, 0.6f, 1f, 1f, 1f);
67 sSlowDownInterpolator = new PathInterpolator(path);
68 }
69
Selim Cinekf99d0002014-06-13 07:36:01 +020070 private AccelerateInterpolator mAccelerateInterpolator = new AccelerateInterpolator();
71
Jorim Jaggi7d16bb12014-05-22 04:24:50 +020072 /**
73 * Refreshes the dimension values.
74 */
75 public void loadDimens(Resources res) {
76 mClockNotificationsMarginMin = res.getDimensionPixelSize(
77 R.dimen.keyguard_clock_notifications_margin_min);
78 mClockNotificationsMarginMax = res.getDimensionPixelSize(
79 R.dimen.keyguard_clock_notifications_margin_max);
80 mClockYFractionMin = res.getFraction(R.fraction.keyguard_clock_y_fraction_min, 1, 1);
81 mClockYFractionMax = res.getFraction(R.fraction.keyguard_clock_y_fraction_max, 1, 1);
82 mMoreCardNotificationAmount =
Selim Cinek281c2022016-10-13 19:14:43 -070083 (float) res.getDimensionPixelSize(R.dimen.notification_shelf_height) /
Jorim Jaggi7d16bb12014-05-22 04:24:50 +020084 res.getDimensionPixelSize(R.dimen.notification_min_height);
Jorim Jaggi48bc36a2014-07-25 23:16:04 +020085 mDensity = res.getDisplayMetrics().density;
Jorim Jaggi7d16bb12014-05-22 04:24:50 +020086 }
87
88 public void setup(int maxKeyguardNotifications, int maxPanelHeight, float expandedHeight,
Jorim Jaggi48bc36a2014-07-25 23:16:04 +020089 int notificationCount, int height, int keyguardStatusHeight, float emptyDragAmount) {
Jorim Jaggi7d16bb12014-05-22 04:24:50 +020090 mMaxKeyguardNotifications = maxKeyguardNotifications;
91 mMaxPanelHeight = maxPanelHeight;
92 mExpandedHeight = expandedHeight;
93 mNotificationCount = notificationCount;
94 mHeight = height;
95 mKeyguardStatusHeight = keyguardStatusHeight;
Jorim Jaggi48bc36a2014-07-25 23:16:04 +020096 mEmptyDragAmount = emptyDragAmount;
Jorim Jaggi7d16bb12014-05-22 04:24:50 +020097 }
98
Selim Cinek5f71bee2015-11-18 10:25:23 -080099 public float getMinStackScrollerPadding(int height, int keyguardStatusHeight) {
100 return mClockYFractionMin * height + keyguardStatusHeight / 2
101 + mClockNotificationsMarginMin;
102 }
103
Jorim Jaggi7d16bb12014-05-22 04:24:50 +0200104 public void run(Result result) {
Selim Cinekf99d0002014-06-13 07:36:01 +0200105 int y = getClockY() - mKeyguardStatusHeight / 2;
Jorim Jaggicc693242014-06-14 03:04:35 +0000106 float clockAdjustment = getClockYExpansionAdjustment();
Jorim Jaggi7d16bb12014-05-22 04:24:50 +0200107 float topPaddingAdjMultiplier = getTopPaddingAdjMultiplier();
Jorim Jaggicc693242014-06-14 03:04:35 +0000108 result.stackScrollerPaddingAdjustment = (int) (clockAdjustment*topPaddingAdjMultiplier);
Jorim Jaggi7d16bb12014-05-22 04:24:50 +0200109 int clockNotificationsPadding = getClockNotificationsPadding()
110 + result.stackScrollerPaddingAdjustment;
111 int padding = y + clockNotificationsPadding;
Jorim Jaggi7d16bb12014-05-22 04:24:50 +0200112 result.clockY = y;
113 result.stackScrollerPadding = mKeyguardStatusHeight + padding;
Selim Cinekf99d0002014-06-13 07:36:01 +0200114 result.clockScale = getClockScale(result.stackScrollerPadding,
115 result.clockY,
116 y + getClockNotificationsPadding() + mKeyguardStatusHeight);
117 result.clockAlpha = getClockAlpha(result.clockScale);
118 }
119
120 private float getClockScale(int notificationPadding, int clockY, int startPadding) {
121 float scaleMultiplier = getNotificationAmountT() == 0 ? 6.0f : 5.0f;
122 float scaleEnd = clockY - mKeyguardStatusHeight * scaleMultiplier;
123 float distanceToScaleEnd = notificationPadding - scaleEnd;
124 float progress = distanceToScaleEnd / (startPadding - scaleEnd);
125 progress = Math.max(0.0f, Math.min(progress, 1.0f));
126 progress = mAccelerateInterpolator.getInterpolation(progress);
Jorim Jaggi48bc36a2014-07-25 23:16:04 +0200127 progress *= Math.pow(1 + mEmptyDragAmount / mDensity / 300, 0.3f);
Selim Cinekf99d0002014-06-13 07:36:01 +0200128 return progress;
Jorim Jaggi7d16bb12014-05-22 04:24:50 +0200129 }
130
131 private int getClockNotificationsPadding() {
132 float t = getNotificationAmountT();
133 t = Math.min(t, 1.0f);
134 return (int) (t * mClockNotificationsMarginMin + (1 - t) * mClockNotificationsMarginMax);
135 }
136
137 private float getClockYFraction() {
138 float t = getNotificationAmountT();
139 t = Math.min(t, 1.0f);
140 return (1 - t) * mClockYFractionMax + t * mClockYFractionMin;
141 }
142
143 private int getClockY() {
144 return (int) (getClockYFraction() * mHeight);
145 }
146
Jorim Jaggicc693242014-06-14 03:04:35 +0000147 private float getClockYExpansionAdjustment() {
148 float rubberbandFactor = getClockYExpansionRubberbandFactor();
Jorim Jaggi7d16bb12014-05-22 04:24:50 +0200149 float value = (rubberbandFactor * (mMaxPanelHeight - mExpandedHeight));
150 float t = value / mMaxPanelHeight;
151 float slowedDownValue = -sSlowDownInterpolator.getInterpolation(t) * SLOW_DOWN_FACTOR
152 * mMaxPanelHeight;
153 if (mNotificationCount == 0) {
154 return (-2*value + slowedDownValue)/3;
155 } else {
156 return slowedDownValue;
157 }
158 }
159
Jorim Jaggicc693242014-06-14 03:04:35 +0000160 private float getClockYExpansionRubberbandFactor() {
Jorim Jaggi7d16bb12014-05-22 04:24:50 +0200161 float t = getNotificationAmountT();
162 t = Math.min(t, 1.0f);
163 t = (float) Math.pow(t, 0.3f);
164 return (1 - t) * CLOCK_RUBBERBAND_FACTOR_MAX + t * CLOCK_RUBBERBAND_FACTOR_MIN;
165 }
166
167 private float getTopPaddingAdjMultiplier() {
168 float t = getNotificationAmountT();
169 t = Math.min(t, 1.0f);
170 return (1 - t) * CLOCK_ADJ_TOP_PADDING_MULTIPLIER_MIN
171 + t * CLOCK_ADJ_TOP_PADDING_MULTIPLIER_MAX;
172 }
173
Selim Cinekf99d0002014-06-13 07:36:01 +0200174 private float getClockAlpha(float scale) {
175 float fadeEnd = getNotificationAmountT() == 0.0f
176 ? CLOCK_SCALE_FADE_END_NO_NOTIFS
177 : CLOCK_SCALE_FADE_END;
178 float alpha = (scale - fadeEnd)
179 / (CLOCK_SCALE_FADE_START - fadeEnd);
Jorim Jaggi7d16bb12014-05-22 04:24:50 +0200180 return Math.max(0, Math.min(1, alpha));
181 }
182
183 /**
184 * @return a value from 0 to 1 depending on how many notification there are
185 */
186 private float getNotificationAmountT() {
187 return mNotificationCount
188 / (mMaxKeyguardNotifications + mMoreCardNotificationAmount);
189 }
190
191 public static class Result {
192
193 /**
194 * The y translation of the clock.
195 */
196 public int clockY;
197
198 /**
Selim Cinekf99d0002014-06-13 07:36:01 +0200199 * The scale of the Clock
200 */
201 public float clockScale;
202
203 /**
Jorim Jaggi7d16bb12014-05-22 04:24:50 +0200204 * The alpha value of the clock.
205 */
206 public float clockAlpha;
207
208 /**
209 * The top padding of the stack scroller, in pixels.
210 */
211 public int stackScrollerPadding;
212
213 /**
214 * The top padding adjustment of the stack scroller, in pixels. This value is used to adjust
215 * the padding, but not the overall panel size.
216 */
217 public int stackScrollerPaddingAdjustment;
218 }
219}