PanelBar.java revision c38bbc391ae4ec5945d5fa408da3994552f775eb
1package com.android.systemui.statusbar.phone; 2 3import java.util.ArrayList; 4 5import android.content.Context; 6import android.util.AttributeSet; 7import android.util.Slog; 8import android.view.MotionEvent; 9import android.view.View; 10import android.widget.FrameLayout; 11 12public class PanelBar extends FrameLayout { 13 public static final boolean DEBUG = false; 14 public static final String TAG = PanelBar.class.getSimpleName(); 15 public static final void LOG(String fmt, Object... args) { 16 if (!DEBUG) return; 17 Slog.v(TAG, String.format(fmt, args)); 18 } 19 20 public static final int STATE_CLOSED = 0; 21 public static final int STATE_OPENING = 1; 22 public static final int STATE_OPEN = 2; 23 24 PanelHolder mPanelHolder; 25 ArrayList<PanelView> mPanels = new ArrayList<PanelView>(); 26 PanelView mTouchingPanel; 27 private int mState = STATE_CLOSED; 28 private boolean mTracking; 29 30 float mPanelExpandedFractionSum; 31 32 public void go(int state) { 33 if (DEBUG) LOG("go state: %d -> %d", mState, state); 34 mState = state; 35 } 36 37 public PanelBar(Context context, AttributeSet attrs) { 38 super(context, attrs); 39 } 40 41 @Override 42 protected void onFinishInflate() { 43 super.onFinishInflate(); 44 } 45 46 public void addPanel(PanelView pv) { 47 mPanels.add(pv); 48 pv.setBar(this); 49 } 50 51 public void setPanelHolder(PanelHolder ph) { 52 if (ph == null) { 53 Slog.e(TAG, "setPanelHolder: null PanelHolder", new Throwable()); 54 return; 55 } 56 ph.setBar(this); 57 mPanelHolder = ph; 58 final int N = ph.getChildCount(); 59 for (int i=0; i<N; i++) { 60 final PanelView v = (PanelView) ph.getChildAt(i); 61 if (v != null) { 62 addPanel(v); 63 } 64 } 65 } 66 67 public float getBarHeight() { 68 return getMeasuredHeight(); 69 } 70 71 public PanelView selectPanelForTouchX(float x) { 72 final int N = mPanels.size(); 73 return mPanels.get((int)(N * x / getMeasuredWidth())); 74 } 75 76 public boolean panelsEnabled() { 77 return true; 78 } 79 80 @Override 81 public boolean onTouchEvent(MotionEvent event) { 82 // Allow subclasses to implement enable/disable semantics 83 if (!panelsEnabled()) return false; 84 85 // figure out which panel needs to be talked to here 86 if (event.getAction() == MotionEvent.ACTION_DOWN) { 87 final PanelView panel = selectPanelForTouchX(event.getX()); 88 boolean enabled = panel.isEnabled(); 89 if (DEBUG) LOG("PanelBar.onTouch: state=%d ACTION_DOWN: panel %s %s", mState, panel, 90 (enabled ? "" : " (disabled)")); 91 if (!enabled) 92 return false; 93 startOpeningPanel(panel); 94 } 95 final boolean result = mTouchingPanel.getHandle().dispatchTouchEvent(event); 96 return result; 97 } 98 99 // called from PanelView when self-expanding, too 100 public void startOpeningPanel(PanelView panel) { 101 if (DEBUG) LOG("startOpeningPanel: " + panel); 102 mTouchingPanel = panel; 103 mPanelHolder.setSelectedPanel(mTouchingPanel); 104 for (PanelView pv : mPanels) { 105 if (pv != panel) { 106 pv.collapse(); 107 } 108 } 109 } 110 111 public void panelExpansionChanged(PanelView panel, float frac) { 112 boolean fullyClosed = true; 113 PanelView fullyOpenedPanel = null; 114 if (DEBUG) LOG("panelExpansionChanged: start state=%d panel=%s", mState, panel.getName()); 115 mPanelExpandedFractionSum = 0f; 116 for (PanelView pv : mPanels) { 117 final boolean visible = pv.getVisibility() == View.VISIBLE; 118 // adjust any other panels that may be partially visible 119 if (pv.getExpandedHeight() > 0f) { 120 if (mState == STATE_CLOSED) { 121 go(STATE_OPENING); 122 onPanelPeeked(); 123 } 124 fullyClosed = false; 125 final float thisFrac = pv.getExpandedFraction(); 126 mPanelExpandedFractionSum += (visible ? thisFrac : 0); 127 if (DEBUG) LOG("panelExpansionChanged: -> %s: f=%.1f", pv.getName(), thisFrac); 128 if (panel == pv) { 129 if (thisFrac == 1f) fullyOpenedPanel = panel; 130 } 131 } 132 if (pv.getExpandedHeight() > 0f) { 133 if (!visible) pv.setVisibility(View.VISIBLE); 134 } else { 135 if (visible) pv.setVisibility(View.GONE); 136 } 137 } 138 mPanelExpandedFractionSum /= mPanels.size(); 139 if (fullyOpenedPanel != null && !mTracking) { 140 go(STATE_OPEN); 141 onPanelFullyOpened(fullyOpenedPanel); 142 } else if (fullyClosed && !mTracking && mState != STATE_CLOSED) { 143 go(STATE_CLOSED); 144 onAllPanelsCollapsed(); 145 } 146 147 if (DEBUG) LOG("panelExpansionChanged: end state=%d [%s%s ]", mState, 148 (fullyOpenedPanel!=null)?" fullyOpened":"", fullyClosed?" fullyClosed":""); 149 } 150 151 public void collapseAllPanels(boolean animate) { 152 boolean waiting = false; 153 for (PanelView pv : mPanels) { 154 if (animate && !pv.isFullyCollapsed()) { 155 pv.collapse(); 156 waiting = true; 157 } else { 158 pv.setExpandedFraction(0); // just in case 159 pv.setVisibility(View.GONE); 160 } 161 } 162 if (DEBUG) LOG("collapseAllPanels: animate=%s waiting=%s", animate, waiting); 163 if (!waiting && mState != STATE_CLOSED) { 164 // it's possible that nothing animated, so we replicate the termination 165 // conditions of panelExpansionChanged here 166 go(STATE_CLOSED); 167 onAllPanelsCollapsed(); 168 } 169 } 170 171 public void onPanelPeeked() { 172 if (DEBUG) LOG("onPanelPeeked"); 173 } 174 175 public void onAllPanelsCollapsed() { 176 if (DEBUG) LOG("onAllPanelsCollapsed"); 177 } 178 179 public void onPanelFullyOpened(PanelView openPanel) { 180 if (DEBUG) LOG("onPanelFullyOpened"); 181 } 182 183 public void onTrackingStarted(PanelView panel) { 184 mTracking = true; 185 if (DEBUG && panel != mTouchingPanel) { 186 LOG("shouldn't happen: onTrackingStarted(%s) != mTouchingPanel(%s)", 187 panel, mTouchingPanel); 188 } 189 } 190 191 public void onTrackingStopped(PanelView panel) { 192 mTracking = false; 193 panelExpansionChanged(panel, panel.getExpandedFraction()); 194 } 195} 196