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