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