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