Home | History | Annotate | Download | only in phone
      1 /*
      2  * Copyright (C) 2008 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.app.ActivityManager;
     20 import android.content.Context;
     21 import android.content.res.Resources;
     22 import android.content.res.Resources.NotFoundException;
     23 import android.util.AttributeSet;
     24 import android.util.EventLog;
     25 import android.util.Log;
     26 import android.view.MotionEvent;
     27 import android.view.View;
     28 import android.view.accessibility.AccessibilityEvent;
     29 
     30 import com.android.systemui.EventLogTags;
     31 import com.android.systemui.R;
     32 
     33 public class PhoneStatusBarView extends PanelBar {
     34     private static final String TAG = "PhoneStatusBarView";
     35     private static final boolean DEBUG = PhoneStatusBar.DEBUG;
     36     private static final boolean DEBUG_GESTURES = true;
     37 
     38     PhoneStatusBar mBar;
     39     int mScrimColor;
     40     float mSettingsPanelDragzoneFrac;
     41     float mSettingsPanelDragzoneMin;
     42 
     43     boolean mFullWidthNotifications;
     44     PanelView mFadingPanel = null;
     45     PanelView mLastFullyOpenedPanel = null;
     46     PanelView mNotificationPanel, mSettingsPanel;
     47     private boolean mShouldFade;
     48     private final PhoneStatusBarTransitions mBarTransitions;
     49 
     50     public PhoneStatusBarView(Context context, AttributeSet attrs) {
     51         super(context, attrs);
     52 
     53         Resources res = getContext().getResources();
     54         mScrimColor = res.getColor(R.color.notification_panel_scrim_color);
     55         mSettingsPanelDragzoneMin = res.getDimension(R.dimen.settings_panel_dragzone_min);
     56         try {
     57             mSettingsPanelDragzoneFrac = res.getFraction(R.dimen.settings_panel_dragzone_fraction, 1, 1);
     58         } catch (NotFoundException ex) {
     59             mSettingsPanelDragzoneFrac = 0f;
     60         }
     61         mFullWidthNotifications = mSettingsPanelDragzoneFrac <= 0f;
     62         mBarTransitions = new PhoneStatusBarTransitions(this);
     63     }
     64 
     65     public BarTransitions getBarTransitions() {
     66         return mBarTransitions;
     67     }
     68 
     69     public void setBar(PhoneStatusBar bar) {
     70         mBar = bar;
     71     }
     72 
     73     public boolean hasFullWidthNotifications() {
     74         return mFullWidthNotifications;
     75     }
     76 
     77     @Override
     78     public void onAttachedToWindow() {
     79         for (PanelView pv : mPanels) {
     80             pv.setRubberbandingEnabled(!mFullWidthNotifications);
     81         }
     82         mBarTransitions.init();
     83     }
     84 
     85     @Override
     86     public void addPanel(PanelView pv) {
     87         super.addPanel(pv);
     88         if (pv.getId() == R.id.notification_panel) {
     89             mNotificationPanel = pv;
     90         } else if (pv.getId() == R.id.settings_panel){
     91             mSettingsPanel = pv;
     92         }
     93         pv.setRubberbandingEnabled(!mFullWidthNotifications);
     94     }
     95 
     96     @Override
     97     public boolean panelsEnabled() {
     98         return mBar.panelsEnabled();
     99     }
    100 
    101     @Override
    102     public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) {
    103         if (super.onRequestSendAccessibilityEvent(child, event)) {
    104             // The status bar is very small so augment the view that the user is touching
    105             // with the content of the status bar a whole. This way an accessibility service
    106             // may announce the current item as well as the entire content if appropriate.
    107             AccessibilityEvent record = AccessibilityEvent.obtain();
    108             onInitializeAccessibilityEvent(record);
    109             dispatchPopulateAccessibilityEvent(record);
    110             event.appendRecord(record);
    111             return true;
    112         }
    113         return false;
    114     }
    115 
    116     @Override
    117     public PanelView selectPanelForTouch(MotionEvent touch) {
    118         final float x = touch.getX();
    119         final boolean isLayoutRtl = isLayoutRtl();
    120 
    121         if (mFullWidthNotifications) {
    122             // No double swiping. If either panel is open, nothing else can be pulled down.
    123             return ((mSettingsPanel == null ? 0 : mSettingsPanel.getExpandedHeight())
    124                         + mNotificationPanel.getExpandedHeight() > 0)
    125                     ? null
    126                     : mNotificationPanel;
    127         }
    128 
    129         // We split the status bar into thirds: the left 2/3 are for notifications, and the
    130         // right 1/3 for quick settings. If you pull the status bar down a second time you'll
    131         // toggle panels no matter where you pull it down.
    132 
    133         final float w = getMeasuredWidth();
    134         float region = (w * mSettingsPanelDragzoneFrac);
    135 
    136         if (DEBUG) {
    137             Log.v(TAG, String.format(
    138                 "w=%.1f frac=%.3f region=%.1f min=%.1f x=%.1f w-x=%.1f",
    139                 w, mSettingsPanelDragzoneFrac, region, mSettingsPanelDragzoneMin, x, (w-x)));
    140         }
    141 
    142         if (region < mSettingsPanelDragzoneMin) region = mSettingsPanelDragzoneMin;
    143 
    144         final boolean showSettings = isLayoutRtl ? (x < region) : (w - region < x);
    145         return showSettings ? mSettingsPanel : mNotificationPanel;
    146     }
    147 
    148     @Override
    149     public void onPanelPeeked() {
    150         super.onPanelPeeked();
    151         mBar.makeExpandedVisible();
    152     }
    153 
    154     @Override
    155     public void startOpeningPanel(PanelView panel) {
    156         super.startOpeningPanel(panel);
    157         // we only want to start fading if this is the "first" or "last" panel,
    158         // which is kind of tricky to determine
    159         mShouldFade = (mFadingPanel == null || mFadingPanel.isFullyExpanded());
    160         if (DEBUG) {
    161             Log.v(TAG, "start opening: " + panel + " shouldfade=" + mShouldFade);
    162         }
    163         mFadingPanel = panel;
    164     }
    165 
    166     @Override
    167     public void onAllPanelsCollapsed() {
    168         super.onAllPanelsCollapsed();
    169         // give animations time to settle
    170         mBar.makeExpandedInvisibleSoon();
    171         mFadingPanel = null;
    172         mLastFullyOpenedPanel = null;
    173         if (mScrimColor != 0 && ActivityManager.isHighEndGfx()) {
    174             mBar.mStatusBarWindow.setBackgroundColor(0);
    175         }
    176     }
    177 
    178     @Override
    179     public void onPanelFullyOpened(PanelView openPanel) {
    180         super.onPanelFullyOpened(openPanel);
    181         if (openPanel != mLastFullyOpenedPanel) {
    182             openPanel.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
    183         }
    184         mFadingPanel = openPanel;
    185         mLastFullyOpenedPanel = openPanel;
    186         mShouldFade = true; // now you own the fade, mister
    187     }
    188 
    189     @Override
    190     public boolean onTouchEvent(MotionEvent event) {
    191         boolean barConsumedEvent = mBar.interceptTouchEvent(event);
    192 
    193         if (DEBUG_GESTURES) {
    194             if (event.getActionMasked() != MotionEvent.ACTION_MOVE) {
    195                 EventLog.writeEvent(EventLogTags.SYSUI_PANELBAR_TOUCH,
    196                         event.getActionMasked(), (int) event.getX(), (int) event.getY(),
    197                         barConsumedEvent ? 1 : 0);
    198             }
    199         }
    200 
    201         return barConsumedEvent || super.onTouchEvent(event);
    202     }
    203 
    204     @Override
    205     public boolean onInterceptTouchEvent(MotionEvent event) {
    206         return mBar.interceptTouchEvent(event) || super.onInterceptTouchEvent(event);
    207     }
    208 
    209     @Override
    210     public void panelExpansionChanged(PanelView panel, float frac) {
    211         super.panelExpansionChanged(panel, frac);
    212 
    213         if (DEBUG) {
    214             Log.v(TAG, "panelExpansionChanged: f=" + frac);
    215         }
    216 
    217         if (panel == mFadingPanel && mScrimColor != 0 && ActivityManager.isHighEndGfx()) {
    218             if (mShouldFade) {
    219                 frac = mPanelExpandedFractionSum; // don't judge me
    220                 // let's start this 20% of the way down the screen
    221                 frac = frac * 1.2f - 0.2f;
    222                 if (frac <= 0) {
    223                     mBar.mStatusBarWindow.setBackgroundColor(0);
    224                 } else {
    225                     // woo, special effects
    226                     final float k = (float)(1f-0.5f*(1f-Math.cos(3.14159f * Math.pow(1f-frac, 2f))));
    227                     // attenuate background color alpha by k
    228                     final int color = (int) ((mScrimColor >>> 24) * k) << 24 | (mScrimColor & 0xFFFFFF);
    229                     mBar.mStatusBarWindow.setBackgroundColor(color);
    230                 }
    231             }
    232         }
    233 
    234         // fade out the panel as it gets buried into the status bar to avoid overdrawing the
    235         // status bar on the last frame of a close animation
    236         final int H = mBar.getStatusBarHeight();
    237         final float ph = panel.getExpandedHeight() + panel.getPaddingBottom();
    238         float alpha = 1f;
    239         if (ph < 2*H) {
    240             if (ph < H) alpha = 0f;
    241             else alpha = (ph - H) / H;
    242             alpha = alpha * alpha; // get there faster
    243         }
    244         if (panel.getAlpha() != alpha) {
    245             panel.setAlpha(alpha);
    246         }
    247 
    248         mBar.animateHeadsUp(mNotificationPanel == panel, mPanelExpandedFractionSum);
    249 
    250         mBar.updateCarrierLabelVisibility(false);
    251     }
    252 }
    253