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