KeyguardClockPositionAlgorithm.java revision f99d0007646781b99a63bc0d2103a45f0f72e724
1/* 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; 21import android.view.animation.AccelerateInterpolator; 22import 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; 35 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 39 40 private static final float CLOCK_ADJ_TOP_PADDING_MULTIPLIER_MIN = 1.4f; 41 private static final float CLOCK_ADJ_TOP_PADDING_MULTIPLIER_MAX = 3.2f; 42 43 private int mClockNotificationsMarginMin; 44 private int mClockNotificationsMarginMax; 45 private float mClockYFractionMin; 46 private float mClockYFractionMax; 47 private int mMaxKeyguardNotifications; 48 private int mMaxPanelHeight; 49 private float mExpandedHeight; 50 private int mNotificationCount; 51 private int mHeight; 52 private int mKeyguardStatusHeight; 53 54 /** 55 * The number (fractional) of notifications the "more" card counts when calculating how many 56 * notifications are currently visible for the y positioning of the clock. 57 */ 58 private float mMoreCardNotificationAmount; 59 60 private static final PathInterpolator sSlowDownInterpolator; 61 62 static { 63 Path path = new Path(); 64 path.moveTo(0, 0); 65 path.cubicTo(0.3f, 0.875f, 0.6f, 1f, 1f, 1f); 66 sSlowDownInterpolator = new PathInterpolator(path); 67 } 68 69 private AccelerateInterpolator mAccelerateInterpolator = new AccelerateInterpolator(); 70 71 /** 72 * Refreshes the dimension values. 73 */ 74 public void loadDimens(Resources res) { 75 mClockNotificationsMarginMin = res.getDimensionPixelSize( 76 R.dimen.keyguard_clock_notifications_margin_min); 77 mClockNotificationsMarginMax = res.getDimensionPixelSize( 78 R.dimen.keyguard_clock_notifications_margin_max); 79 mClockYFractionMin = res.getFraction(R.fraction.keyguard_clock_y_fraction_min, 1, 1); 80 mClockYFractionMax = res.getFraction(R.fraction.keyguard_clock_y_fraction_max, 1, 1); 81 mMoreCardNotificationAmount = 82 (float) res.getDimensionPixelSize(R.dimen.notification_summary_height) / 83 res.getDimensionPixelSize(R.dimen.notification_min_height); 84 } 85 86 public void setup(int maxKeyguardNotifications, int maxPanelHeight, float expandedHeight, 87 int notificationCount, int height, int keyguardStatusHeight) { 88 mMaxKeyguardNotifications = maxKeyguardNotifications; 89 mMaxPanelHeight = maxPanelHeight; 90 mExpandedHeight = expandedHeight; 91 mNotificationCount = notificationCount; 92 mHeight = height; 93 mKeyguardStatusHeight = keyguardStatusHeight; 94 } 95 96 public void run(Result result) { 97 int y = getClockY() - mKeyguardStatusHeight / 2; 98 float clockAdjustment = getClockYExpansionAdjustment(); 99 float topPaddingAdjMultiplier = getTopPaddingAdjMultiplier(); 100 result.stackScrollerPaddingAdjustment = (int) (clockAdjustment*topPaddingAdjMultiplier); 101 int clockNotificationsPadding = getClockNotificationsPadding() 102 + result.stackScrollerPaddingAdjustment; 103 int padding = y + clockNotificationsPadding; 104 result.clockY = y; 105 result.stackScrollerPadding = mKeyguardStatusHeight + padding; 106 result.clockScale = getClockScale(result.stackScrollerPadding, 107 result.clockY, 108 y + getClockNotificationsPadding() + mKeyguardStatusHeight); 109 result.clockAlpha = getClockAlpha(result.clockScale); 110 } 111 112 private float getClockScale(int notificationPadding, int clockY, int startPadding) { 113 float scaleMultiplier = getNotificationAmountT() == 0 ? 6.0f : 5.0f; 114 float scaleEnd = clockY - mKeyguardStatusHeight * scaleMultiplier; 115 float distanceToScaleEnd = notificationPadding - scaleEnd; 116 float progress = distanceToScaleEnd / (startPadding - scaleEnd); 117 progress = Math.max(0.0f, Math.min(progress, 1.0f)); 118 progress = mAccelerateInterpolator.getInterpolation(progress); 119 return progress; 120 } 121 122 private int getClockNotificationsPadding() { 123 float t = getNotificationAmountT(); 124 t = Math.min(t, 1.0f); 125 return (int) (t * mClockNotificationsMarginMin + (1 - t) * mClockNotificationsMarginMax); 126 } 127 128 private float getClockYFraction() { 129 float t = getNotificationAmountT(); 130 t = Math.min(t, 1.0f); 131 return (1 - t) * mClockYFractionMax + t * mClockYFractionMin; 132 } 133 134 private int getClockY() { 135 return (int) (getClockYFraction() * mHeight); 136 } 137 138 private float getClockYExpansionAdjustment() { 139 float rubberbandFactor = getClockYExpansionRubberbandFactor(); 140 float value = (rubberbandFactor * (mMaxPanelHeight - mExpandedHeight)); 141 float t = value / mMaxPanelHeight; 142 float slowedDownValue = -sSlowDownInterpolator.getInterpolation(t) * SLOW_DOWN_FACTOR 143 * mMaxPanelHeight; 144 if (mNotificationCount == 0) { 145 return (-2*value + slowedDownValue)/3; 146 } else { 147 return slowedDownValue; 148 } 149 } 150 151 private float getClockYExpansionRubberbandFactor() { 152 float t = getNotificationAmountT(); 153 t = Math.min(t, 1.0f); 154 t = (float) Math.pow(t, 0.3f); 155 return (1 - t) * CLOCK_RUBBERBAND_FACTOR_MAX + t * CLOCK_RUBBERBAND_FACTOR_MIN; 156 } 157 158 private float getTopPaddingAdjMultiplier() { 159 float t = getNotificationAmountT(); 160 t = Math.min(t, 1.0f); 161 return (1 - t) * CLOCK_ADJ_TOP_PADDING_MULTIPLIER_MIN 162 + t * CLOCK_ADJ_TOP_PADDING_MULTIPLIER_MAX; 163 } 164 165 private float getClockAlpha(float scale) { 166 float fadeEnd = getNotificationAmountT() == 0.0f 167 ? CLOCK_SCALE_FADE_END_NO_NOTIFS 168 : CLOCK_SCALE_FADE_END; 169 float alpha = (scale - fadeEnd) 170 / (CLOCK_SCALE_FADE_START - fadeEnd); 171 return Math.max(0, Math.min(1, alpha)); 172 } 173 174 /** 175 * @return a value from 0 to 1 depending on how many notification there are 176 */ 177 private float getNotificationAmountT() { 178 return mNotificationCount 179 / (mMaxKeyguardNotifications + mMoreCardNotificationAmount); 180 } 181 182 public static class Result { 183 184 /** 185 * The y translation of the clock. 186 */ 187 public int clockY; 188 189 /** 190 * The scale of the Clock 191 */ 192 public float clockScale; 193 194 /** 195 * The alpha value of the clock. 196 */ 197 public float clockAlpha; 198 199 /** 200 * The top padding of the stack scroller, in pixels. 201 */ 202 public int stackScrollerPadding; 203 204 /** 205 * The top padding adjustment of the stack scroller, in pixels. This value is used to adjust 206 * the padding, but not the overall panel size. 207 */ 208 public int stackScrollerPaddingAdjustment; 209 } 210} 211