Home | History | Annotate | Download | only in phone
      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 
     17 package com.android.systemui.statusbar.phone;
     18 
     19 import android.content.res.Resources;
     20 import android.graphics.Path;
     21 import android.view.animation.AccelerateInterpolator;
     22 import android.view.animation.PathInterpolator;
     23 
     24 import com.android.systemui.R;
     25 
     26 /**
     27  * Utility class to calculate the clock position and top padding of notifications on Keyguard.
     28  */
     29 public 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     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;
     52     private float mEmptyDragAmount;
     53     private float mDensity;
     54 
     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 
     70     private AccelerateInterpolator mAccelerateInterpolator = new AccelerateInterpolator();
     71 
     72     /**
     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 =
     83                 (float) res.getDimensionPixelSize(R.dimen.notification_summary_height) /
     84                         res.getDimensionPixelSize(R.dimen.notification_min_height);
     85         mDensity = res.getDisplayMetrics().density;
     86     }
     87 
     88     public void setup(int maxKeyguardNotifications, int maxPanelHeight, float expandedHeight,
     89             int notificationCount, int height, int keyguardStatusHeight, float emptyDragAmount) {
     90         mMaxKeyguardNotifications = maxKeyguardNotifications;
     91         mMaxPanelHeight = maxPanelHeight;
     92         mExpandedHeight = expandedHeight;
     93         mNotificationCount = notificationCount;
     94         mHeight = height;
     95         mKeyguardStatusHeight = keyguardStatusHeight;
     96         mEmptyDragAmount = emptyDragAmount;
     97     }
     98 
     99     public float getMinStackScrollerPadding(int height, int keyguardStatusHeight) {
    100         return mClockYFractionMin * height + keyguardStatusHeight / 2
    101                 + mClockNotificationsMarginMin;
    102     }
    103 
    104     public void run(Result result) {
    105         int y = getClockY() - mKeyguardStatusHeight / 2;
    106         float clockAdjustment = getClockYExpansionAdjustment();
    107         float topPaddingAdjMultiplier = getTopPaddingAdjMultiplier();
    108         result.stackScrollerPaddingAdjustment = (int) (clockAdjustment*topPaddingAdjMultiplier);
    109         int clockNotificationsPadding = getClockNotificationsPadding()
    110                 + result.stackScrollerPaddingAdjustment;
    111         int padding = y + clockNotificationsPadding;
    112         result.clockY = y;
    113         result.stackScrollerPadding = mKeyguardStatusHeight + padding;
    114         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);
    127         progress *= Math.pow(1 + mEmptyDragAmount / mDensity / 300, 0.3f);
    128         return progress;
    129     }
    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 
    147     private float getClockYExpansionAdjustment() {
    148         float rubberbandFactor = getClockYExpansionRubberbandFactor();
    149         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 
    160     private float getClockYExpansionRubberbandFactor() {
    161         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 
    174     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);
    180         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         /**
    199          * The scale of the Clock
    200          */
    201         public float clockScale;
    202 
    203         /**
    204          * 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 }
    220