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.util.AttributeSet; 21 import android.util.Log; 22 import android.view.MotionEvent; 23 import android.view.View; 24 import android.widget.FrameLayout; 25 26 import java.util.ArrayList; 27 28 public abstract class PanelBar extends FrameLayout { 29 public static final boolean DEBUG = false; 30 public static final String TAG = PanelBar.class.getSimpleName(); 31 private static final boolean SPEW = false; 32 LOG(String fmt, Object... args)33 public static final void LOG(String fmt, Object... args) { 34 if (!DEBUG) return; 35 Log.v(TAG, String.format(fmt, args)); 36 } 37 38 public static final int STATE_CLOSED = 0; 39 public static final int STATE_OPENING = 1; 40 public static final int STATE_OPEN = 2; 41 42 PanelHolder mPanelHolder; 43 ArrayList<PanelView> mPanels = new ArrayList<PanelView>(); 44 PanelView mTouchingPanel; 45 private int mState = STATE_CLOSED; 46 private boolean mTracking; 47 48 float mPanelExpandedFractionSum; 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 PanelBar(Context context, AttributeSet attrs)55 public PanelBar(Context context, AttributeSet attrs) { 56 super(context, attrs); 57 } 58 59 @Override onFinishInflate()60 protected void onFinishInflate() { 61 super.onFinishInflate(); 62 } 63 addPanel(PanelView pv)64 public void addPanel(PanelView pv) { 65 mPanels.add(pv); 66 pv.setBar(this); 67 } 68 setPanelHolder(PanelHolder ph)69 public void setPanelHolder(PanelHolder ph) { 70 if (ph == null) { 71 Log.e(TAG, "setPanelHolder: null PanelHolder", new Throwable()); 72 return; 73 } 74 ph.setBar(this); 75 mPanelHolder = ph; 76 final int N = ph.getChildCount(); 77 for (int i=0; i<N; i++) { 78 final View v = ph.getChildAt(i); 79 if (v != null && v instanceof PanelView) { 80 addPanel((PanelView) v); 81 } 82 } 83 } 84 setBouncerShowing(boolean showing)85 public void setBouncerShowing(boolean showing) { 86 int important = showing ? IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS 87 : IMPORTANT_FOR_ACCESSIBILITY_AUTO; 88 89 setImportantForAccessibility(important); 90 91 if (mPanelHolder != null) { 92 mPanelHolder.setImportantForAccessibility(important); 93 } 94 } 95 getBarHeight()96 public float getBarHeight() { 97 return getMeasuredHeight(); 98 } 99 selectPanelForTouch(MotionEvent touch)100 public PanelView selectPanelForTouch(MotionEvent touch) { 101 final int N = mPanels.size(); 102 return mPanels.get((int)(N * touch.getX() / getMeasuredWidth())); 103 } 104 panelsEnabled()105 public boolean panelsEnabled() { 106 return true; 107 } 108 109 @Override onTouchEvent(MotionEvent event)110 public boolean onTouchEvent(MotionEvent event) { 111 // Allow subclasses to implement enable/disable semantics 112 if (!panelsEnabled()) { 113 if (event.getAction() == MotionEvent.ACTION_DOWN) { 114 Log.v(TAG, String.format("onTouch: all panels disabled, ignoring touch at (%d,%d)", 115 (int) event.getX(), (int) event.getY())); 116 } 117 return false; 118 } 119 120 // figure out which panel needs to be talked to here 121 if (event.getAction() == MotionEvent.ACTION_DOWN) { 122 final PanelView panel = selectPanelForTouch(event); 123 if (panel == null) { 124 // panel is not there, so we'll eat the gesture 125 Log.v(TAG, String.format("onTouch: no panel for touch at (%d,%d)", 126 (int) event.getX(), (int) event.getY())); 127 mTouchingPanel = null; 128 return true; 129 } 130 boolean enabled = panel.isEnabled(); 131 if (DEBUG) LOG("PanelBar.onTouch: state=%d ACTION_DOWN: panel %s %s", mState, panel, 132 (enabled ? "" : " (disabled)")); 133 if (!enabled) { 134 // panel is disabled, so we'll eat the gesture 135 Log.v(TAG, String.format( 136 "onTouch: panel (%s) is disabled, ignoring touch at (%d,%d)", 137 panel, (int) event.getX(), (int) event.getY())); 138 mTouchingPanel = null; 139 return true; 140 } 141 startOpeningPanel(panel); 142 } 143 final boolean result = mTouchingPanel != null 144 ? mTouchingPanel.onTouchEvent(event) 145 : true; 146 return result; 147 } 148 149 // called from PanelView when self-expanding, too startOpeningPanel(PanelView panel)150 public void startOpeningPanel(PanelView panel) { 151 if (DEBUG) LOG("startOpeningPanel: " + panel); 152 mTouchingPanel = panel; 153 mPanelHolder.setSelectedPanel(mTouchingPanel); 154 for (PanelView pv : mPanels) { 155 if (pv != panel) { 156 pv.collapse(false /* delayed */, 1.0f /* speedUpFactor */); 157 } 158 } 159 } 160 panelScrimMinFractionChanged(float minFraction)161 public abstract void panelScrimMinFractionChanged(float minFraction); 162 163 /** 164 * @param panel the panel which changed its expansion state 165 * @param frac the fraction from the expansion in [0, 1] 166 * @param expanded whether the panel is currently expanded; this is independent from the 167 * fraction as the panel also might be expanded if the fraction is 0 168 */ panelExpansionChanged(PanelView panel, float frac, boolean expanded)169 public void panelExpansionChanged(PanelView panel, float frac, boolean expanded) { 170 boolean fullyClosed = true; 171 PanelView fullyOpenedPanel = null; 172 if (SPEW) LOG("panelExpansionChanged: start state=%d panel=%s", mState, panel.getName()); 173 mPanelExpandedFractionSum = 0f; 174 for (PanelView pv : mPanels) { 175 pv.setVisibility(expanded ? View.VISIBLE : View.INVISIBLE); 176 // adjust any other panels that may be partially visible 177 if (expanded) { 178 if (mState == STATE_CLOSED) { 179 go(STATE_OPENING); 180 onPanelPeeked(); 181 } 182 fullyClosed = false; 183 final float thisFrac = pv.getExpandedFraction(); 184 mPanelExpandedFractionSum += thisFrac; 185 if (SPEW) LOG("panelExpansionChanged: -> %s: f=%.1f", pv.getName(), thisFrac); 186 if (panel == pv) { 187 if (thisFrac == 1f) fullyOpenedPanel = panel; 188 } 189 } 190 } 191 mPanelExpandedFractionSum /= mPanels.size(); 192 if (fullyOpenedPanel != null && !mTracking) { 193 go(STATE_OPEN); 194 onPanelFullyOpened(fullyOpenedPanel); 195 } else if (fullyClosed && !mTracking && mState != STATE_CLOSED) { 196 go(STATE_CLOSED); 197 onAllPanelsCollapsed(); 198 } 199 200 if (SPEW) LOG("panelExpansionChanged: end state=%d [%s%s ]", mState, 201 (fullyOpenedPanel!=null)?" fullyOpened":"", fullyClosed?" fullyClosed":""); 202 } 203 collapseAllPanels(boolean animate, boolean delayed, float speedUpFactor)204 public void collapseAllPanels(boolean animate, boolean delayed, float speedUpFactor) { 205 boolean waiting = false; 206 for (PanelView pv : mPanels) { 207 if (animate && !pv.isFullyCollapsed()) { 208 pv.collapse(delayed, speedUpFactor); 209 waiting = true; 210 } else { 211 pv.resetViews(); 212 pv.setExpandedFraction(0); // just in case 213 pv.cancelPeek(); 214 } 215 } 216 if (DEBUG) LOG("collapseAllPanels: 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 onAllPanelsCollapsed(); 222 } 223 } 224 onPanelPeeked()225 public void onPanelPeeked() { 226 if (DEBUG) LOG("onPanelPeeked"); 227 } 228 onAllPanelsCollapsed()229 public void onAllPanelsCollapsed() { 230 if (DEBUG) LOG("onAllPanelsCollapsed"); 231 } 232 onPanelFullyOpened(PanelView openPanel)233 public void onPanelFullyOpened(PanelView openPanel) { 234 if (DEBUG) LOG("onPanelFullyOpened"); 235 } 236 onTrackingStarted(PanelView panel)237 public void onTrackingStarted(PanelView panel) { 238 mTracking = true; 239 } 240 onTrackingStopped(PanelView panel, boolean expand)241 public void onTrackingStopped(PanelView panel, boolean expand) { 242 mTracking = false; 243 } 244 onExpandingFinished()245 public void onExpandingFinished() { 246 if (DEBUG) LOG("onExpandingFinished"); 247 } 248 onClosingFinished()249 public void onClosingFinished() { 250 251 } 252 } 253