1 /* 2 * Copyright (C) 2012 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 static java.lang.Float.isNaN; 20 21 import android.content.Context; 22 import android.os.Bundle; 23 import android.os.Parcelable; 24 import android.util.AttributeSet; 25 import android.util.Log; 26 import android.view.MotionEvent; 27 import android.widget.FrameLayout; 28 29 public abstract class PanelBar extends FrameLayout { 30 public static final boolean DEBUG = false; 31 public static final String TAG = PanelBar.class.getSimpleName(); 32 private static final boolean SPEW = false; 33 private static final String PANEL_BAR_SUPER_PARCELABLE = "panel_bar_super_parcelable"; 34 private static final String STATE = "state"; 35 private boolean mBouncerShowing; 36 private boolean mExpanded; 37 protected float mPanelFraction; 38 LOG(String fmt, Object... args)39 public static final void LOG(String fmt, Object... args) { 40 if (!DEBUG) return; 41 Log.v(TAG, String.format(fmt, args)); 42 } 43 44 public static final int STATE_CLOSED = 0; 45 public static final int STATE_OPENING = 1; 46 public static final int STATE_OPEN = 2; 47 48 PanelViewController mPanel; 49 private int mState = STATE_CLOSED; 50 private boolean mTracking; 51 go(int state)52 public void go(int state) { 53 if (DEBUG) LOG("go state: %d -> %d", mState, state); 54 mState = state; 55 if (mPanel != null) { 56 mPanel.setIsShadeOpening(state == STATE_OPENING); 57 } 58 } 59 isShadeOpening()60 protected boolean isShadeOpening() { 61 return mState == STATE_OPENING; 62 } 63 64 @Override onSaveInstanceState()65 protected Parcelable onSaveInstanceState() { 66 Bundle bundle = new Bundle(); 67 bundle.putParcelable(PANEL_BAR_SUPER_PARCELABLE, super.onSaveInstanceState()); 68 bundle.putInt(STATE, mState); 69 return bundle; 70 } 71 72 @Override onRestoreInstanceState(Parcelable state)73 protected void onRestoreInstanceState(Parcelable state) { 74 if (state == null || !(state instanceof Bundle)) { 75 super.onRestoreInstanceState(state); 76 return; 77 } 78 79 Bundle bundle = (Bundle) state; 80 super.onRestoreInstanceState(bundle.getParcelable(PANEL_BAR_SUPER_PARCELABLE)); 81 if (((Bundle) state).containsKey(STATE)) { 82 go(bundle.getInt(STATE, STATE_CLOSED)); 83 } 84 } 85 PanelBar(Context context, AttributeSet attrs)86 public PanelBar(Context context, AttributeSet attrs) { 87 super(context, attrs); 88 } 89 90 @Override onFinishInflate()91 protected void onFinishInflate() { 92 super.onFinishInflate(); 93 } 94 95 /** Set the PanelViewController */ setPanel(PanelViewController pv)96 public void setPanel(PanelViewController pv) { 97 mPanel = pv; 98 pv.setBar(this); 99 } 100 setBouncerShowing(boolean showing)101 public void setBouncerShowing(boolean showing) { 102 mBouncerShowing = showing; 103 int important = showing ? IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS 104 : IMPORTANT_FOR_ACCESSIBILITY_AUTO; 105 106 setImportantForAccessibility(important); 107 updateVisibility(); 108 109 if (mPanel != null) mPanel.getView().setImportantForAccessibility(important); 110 } 111 getExpansionFraction()112 public float getExpansionFraction() { 113 return mPanelFraction; 114 } 115 isExpanded()116 public boolean isExpanded() { 117 return mExpanded; 118 } 119 updateVisibility()120 protected void updateVisibility() { 121 mPanel.getView().setVisibility(shouldPanelBeVisible() ? VISIBLE : INVISIBLE); 122 } 123 shouldPanelBeVisible()124 protected boolean shouldPanelBeVisible() { 125 return mExpanded || mBouncerShowing; 126 } 127 panelEnabled()128 public boolean panelEnabled() { 129 return true; 130 } 131 132 @Override onTouchEvent(MotionEvent event)133 public boolean onTouchEvent(MotionEvent event) { 134 // Allow subclasses to implement enable/disable semantics 135 if (!panelEnabled()) { 136 if (event.getAction() == MotionEvent.ACTION_DOWN) { 137 Log.v(TAG, String.format("onTouch: all panels disabled, ignoring touch at (%d,%d)", 138 (int) event.getX(), (int) event.getY())); 139 } 140 return false; 141 } 142 143 if (event.getAction() == MotionEvent.ACTION_DOWN) { 144 final PanelViewController panel = mPanel; 145 if (panel == null) { 146 // panel is not there, so we'll eat the gesture 147 Log.v(TAG, String.format("onTouch: no panel for touch at (%d,%d)", 148 (int) event.getX(), (int) event.getY())); 149 return true; 150 } 151 boolean enabled = panel.isEnabled(); 152 if (DEBUG) LOG("PanelBar.onTouch: state=%d ACTION_DOWN: panel %s %s", mState, panel, 153 (enabled ? "" : " (disabled)")); 154 if (!enabled) { 155 // panel is disabled, so we'll eat the gesture 156 Log.v(TAG, String.format( 157 "onTouch: panel (%s) is disabled, ignoring touch at (%d,%d)", 158 panel, (int) event.getX(), (int) event.getY())); 159 return true; 160 } 161 } 162 return mPanel == null || mPanel.getView().dispatchTouchEvent(event); 163 } 164 panelScrimMinFractionChanged(float minFraction)165 public abstract void panelScrimMinFractionChanged(float minFraction); 166 167 /** 168 * @param frac the fraction from the expansion in [0, 1] 169 * @param expanded whether the panel is currently expanded; this is independent from the 170 * fraction as the panel also might be expanded if the fraction is 0 171 */ panelExpansionChanged(float frac, boolean expanded)172 public void panelExpansionChanged(float frac, boolean expanded) { 173 if (isNaN(frac)) { 174 throw new IllegalArgumentException("frac cannot be NaN"); 175 } 176 boolean fullyClosed = true; 177 boolean fullyOpened = false; 178 if (SPEW) LOG("panelExpansionChanged: start state=%d", mState); 179 PanelViewController pv = mPanel; 180 mExpanded = expanded; 181 mPanelFraction = frac; 182 updateVisibility(); 183 // adjust any other panels that may be partially visible 184 if (expanded) { 185 if (mState == STATE_CLOSED) { 186 go(STATE_OPENING); 187 onPanelPeeked(); 188 } 189 fullyClosed = false; 190 final float thisFrac = pv.getExpandedFraction(); 191 if (SPEW) LOG("panelExpansionChanged: -> %s: f=%.1f", pv.getName(), thisFrac); 192 fullyOpened = thisFrac >= 1f; 193 } 194 if (fullyOpened && !mTracking) { 195 go(STATE_OPEN); 196 onPanelFullyOpened(); 197 } else if (fullyClosed && !mTracking && mState != STATE_CLOSED) { 198 go(STATE_CLOSED); 199 onPanelCollapsed(); 200 } 201 202 if (SPEW) LOG("panelExpansionChanged: end state=%d [%s%s ]", mState, 203 fullyOpened?" fullyOpened":"", fullyClosed?" fullyClosed":""); 204 } 205 collapsePanel(boolean animate, boolean delayed, float speedUpFactor)206 public void collapsePanel(boolean animate, boolean delayed, float speedUpFactor) { 207 boolean waiting = false; 208 PanelViewController pv = mPanel; 209 if (animate && !pv.isFullyCollapsed()) { 210 pv.collapse(delayed, speedUpFactor); 211 waiting = true; 212 } else { 213 pv.resetViews(false /* animate */); 214 pv.setExpandedFraction(0); // just in case 215 } 216 if (DEBUG) LOG("collapsePanel: animate=%s waiting=%s", animate, waiting); 217 if (!waiting && mState != STATE_CLOSED) { 218 // it's possible that nothing animated, so we replicate the termination 219 // conditions of panelExpansionChanged here 220 go(STATE_CLOSED); 221 onPanelCollapsed(); 222 } 223 } 224 onPanelPeeked()225 public void onPanelPeeked() { 226 if (DEBUG) LOG("onPanelPeeked"); 227 } 228 isClosed()229 public boolean isClosed() { 230 return mState == STATE_CLOSED; 231 } 232 onPanelCollapsed()233 public void onPanelCollapsed() { 234 if (DEBUG) LOG("onPanelCollapsed"); 235 } 236 onPanelFullyOpened()237 public void onPanelFullyOpened() { 238 if (DEBUG) LOG("onPanelFullyOpened"); 239 } 240 onTrackingStarted()241 public void onTrackingStarted() { 242 mTracking = true; 243 } 244 onTrackingStopped(boolean expand)245 public void onTrackingStopped(boolean expand) { 246 mTracking = false; 247 } 248 onExpandingFinished()249 public void onExpandingFinished() { 250 if (DEBUG) LOG("onExpandingFinished"); 251 } 252 onClosingFinished()253 public void onClosingFinished() { 254 255 } 256 } 257