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