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